Ответ 1
Удивительно, но не существует отличного, простого решения, использующего ванильный JavaScript. Я сделал чисто JS легкое, минимальное кросс-браузерное решение. Подстраивайтесь под свои нужды и эстетику
* Обновление 2019
W3C имеет рабочий документ, который находится на пути к стандартам, чтобы улучшить это из коробки через спецификацию css. Несмотря на ограничения, если вы хотите использовать режущий край CSS, теперь вы можете настроить полосы прокрутки с помощью scrollbar-color
и scrollbar-width
. Для получения дополнительной информации, пожалуйста, проверьте https://drafts.csswg.org/css-scrollbars/
Примеры:
Вот скрипка и CodePen
HTML
<body>
<div id="main" class="scrollable">
<div class="content-wrapper">
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt accusamus maxime voluptatem quasi. Recusandae optio nobis ratione iste consectetur consequatur cupiditate saepe laborum natus neque a provident eum explicabo delectus qui accusantium nostrum reiciendis soluta hic ut at sed laboriosam possimus repudiandae deserunt velit rerum. Aliquam ratione itaque corrupti aperiam quisquam unde aspernatur odio id repellendus corporis eaque expedita in ab minus possimus! Quo tempore consequatur repellat consectetur nemo molestiae perferendis ipsum esse nesciunt blanditiis nobis dicta? Laudantium quaerat inventore deleniti exercitationem explicabo quos pariatur sunt earum labore sed eius blanditiis architecto consequuntur ad consectetur unde sapiente nisi. Sunt eos.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt accusamus maxime voluptatem quasi. Recusandae optio nobis ratione iste consectetur consequatur cupiditate saepe laborum natus neque a provident eum explicabo delectus qui accusantium nostrum reiciendis soluta hic ut at sed laboriosam possimus repudiandae deserunt velit rerum. Aliquam ratione itaque corrupti aperiam quisquam unde aspernatur odio id repellendus corporis eaque expedita in ab minus possimus! Quo tempore consequatur repellat consectetur nemo molestiae perferendis ipsum esse nesciunt blanditiis nobis dicta? Laudantium quaerat inventore deleniti exercitationem explicabo quos pariatur sunt earum labore sed eius blanditiis architecto consequuntur ad consectetur unde sapiente nisi. Sunt eos.</p>
</div>
</div>
</div>
<div>Not special and not contained within scrolling</div>
</body>
CSS
.scrollable {
padding: 0% 10%;
position: relative;
border: 1px solid gray;
overflow: hidden;
height: 400px;
}
.scrollable.showScroll::after {
position: absolute;
content: '';
top: 5%;
right: 7px;
height: 90%;
width: 3px;
background: rgba(224, 224, 255, .3);
}
.scrollable .content-wrapper {
width: 100%;
height: 100%;
padding-right: 50%;
overflow-y: scroll;
}
.scroller {
z-index: 5;
cursor: pointer;
position: absolute;
width: 10px;
border-radius: 5px;
background: rgb(111, 111, 190);
top: 0px;
right: 3px;
-webkit-transition: top .08s;
-moz-transition: top .08s;
-ms-transition: top .08s;
-o-transition: top .08s;
transition: top .08s;
}
.content {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
JS
(function () {
var scrollContainer = document.querySelector('.scrollable'),
scrollContentWrapper = document.querySelector('.scrollable .content-wrapper'),
scrollContent = document.querySelector('.scrollable .content'),
contentPosition = 0,
scrollerBeingDragged = false,
scroller,
topPosition,
scrollerHeight;
function calculateScrollerHeight() {
// *Calculation of how tall scroller should be
var visibleRatio = scrollContainer.offsetHeight / scrollContentWrapper.scrollHeight;
return visibleRatio * scrollContainer.offsetHeight;
}
function moveScroller(evt) {
// Move Scroll bar to top offset
var scrollPercentage = evt.target.scrollTop / scrollContentWrapper.scrollHeight;
topPosition = scrollPercentage * (scrollContainer.offsetHeight - 5); // 5px arbitrary offset so scroll bar doesn't move too far beyond content wrapper bounding box
scroller.style.top = topPosition + 'px';
}
function startDrag(evt) {
normalizedPosition = evt.pageY;
contentPosition = scrollContentWrapper.scrollTop;
scrollerBeingDragged = true;
}
function stopDrag(evt) {
scrollerBeingDragged = false;
}
function scrollBarScroll(evt) {
if (scrollerBeingDragged === true) {
var mouseDifferential = evt.pageY - normalizedPosition;
var scrollEquivalent = mouseDifferential * (scrollContentWrapper.scrollHeight / scrollContainer.offsetHeight);
scrollContentWrapper.scrollTop = contentPosition + scrollEquivalent;
}
}
function createScroller() {
// *Creates scroller element and appends to '.scrollable' div
// create scroller element
scroller = document.createElement("div");
scroller.className = 'scroller';
// determine how big scroller should be based on content
scrollerHeight = calculateScrollerHeight();
if (scrollerHeight / scrollContainer.offsetHeight < 1){
// *If there is a need to have scroll bar based on content size
scroller.style.height = scrollerHeight + 'px';
// append scroller to scrollContainer div
scrollContainer.appendChild(scroller);
// show scroll path divot
scrollContainer.className += ' showScroll';
// attach related draggable listeners
scroller.addEventListener('mousedown', startDrag);
window.addEventListener('mouseup', stopDrag);
window.addEventListener('mousemove', scrollBarScroll)
}
}
createScroller();
// *** Listeners ***
scrollContentWrapper.addEventListener('scroll', moveScroller);
}());
Концепция проста. У нас есть основной div с прокручиваемым классом. JavaScript распознает этот элемент и добавляет элемент прокрутки, который можно стилизовать с помощью CSS. Вложив дочерний элемент содержимого-обертки, мы можем эффективно вытолкнуть собственный скроллер за пределы родительского элемента div, продолжая контролировать заполнение.
Вот схема:
Причина, по которой нам нужно поддерживать встроенную возможность прокрутки, заключается в том, что событие прокрутки JavaScript запускается только для элементов, для которых переполнение установлено для прокрутки. См. Ссылку MDN на прокрутку. Преимущество в том, что если JS отключен, мы все равно будем грациозно отступать от прокрутки без полосы прокрутки.
НОТА
Обратите внимание, что вам придется изменить свою версию, чтобы в некоторых случаях пересчитать размер скроллера:
1.) Размер экрана или
2.) Если добавлено больше контента.
Во-вторых, нужно будет внести изменения, если у вас есть несколько "прокручиваемых" элементов. В этом случае вам нужно будет зациклить эти элементы, чтобы добавить элемент прокрутки и прослушать событие прокрутки.