Как создать простую полосу прокрутки страницы без использования jQuery?

Я рассмотрел, я думаю, весь код полос прокрутки, но пока не смог найти простой, который не использует jQuery или несколько сложную библиотеку.

Кто-нибудь создал там собственную простую полосу прокрутки, используя только Javascript? То, что я ищу, является примером того, как это можно сделать. В частности, у меня есть простая веб-страница Bootstrap с:

<body>
   <header> ....</header>
   <main> ......</main>
</body>

То, что я хотел бы сделать, - это иметь небольшую полосу прокрутки страницы справа от области <main>, если содержимое там больше, чем умещается на одной странице. В целях стилизации я бы хотел, чтобы эта , а не была полосой прокрутки браузера по умолчанию.

Вот пример того, что я ищу, но этот действительно использует jQuery, поэтому я не могу использовать его на своем сайте:

http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/complete_examples.html

Я ищу какой-то способ сделать это, используя Javascript в современном браузере IE9 и выше. Поскольку я думаю, что это было бы полезно для многих людей, я открыл за это премию в 200 человек в надежде, что кто-то сможет предоставить хороший пример перетаскиваемой полосы прокрутки страницы, которая также будет реагировать на колесо мыши при нахождении над областью содержимого страницы.

Просто обновление. Я не ищу мобильное решение для этого. Я просто ищу решение, которое будет работать в браузере ПК /Mac. Сайт не настроен или не подходит для телефона. Можно использовать на iPad/планшете, но для этих целей я бы хотел иметь по умолчанию полосу прокрутки, чтобы использовать только обычный метод прокрутки планшета.

Ответы

Ответ 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, продолжая контролировать заполнение.

Вот схема: Scroll Diagram

Причина, по которой нам нужно поддерживать встроенную возможность прокрутки, заключается в том, что событие прокрутки JavaScript запускается только для элементов, для которых переполнение установлено для прокрутки. См. Ссылку MDN на прокрутку. Преимущество в том, что если JS отключен, мы все равно будем грациозно отступать от прокрутки без полосы прокрутки.


НОТА
Обратите внимание, что вам придется изменить свою версию, чтобы в некоторых случаях пересчитать размер скроллера:
1.) Размер экрана или
2.) Если добавлено больше контента.

Во-вторых, нужно будет внести изменения, если у вас есть несколько "прокручиваемых" элементов. В этом случае вам нужно будет зациклить эти элементы, чтобы добавить элемент прокрутки и прослушать событие прокрутки.

Ответ 2

Я знаю, что на этот вопрос уже есть ответ, но как только OP захотел создать простое решение для ванильного javascript, которое работает на современных браузерах, - и я думаю, что больше людей, вероятно, тоже это понадобится, я буду поздно, отвечая на этот вопрос здесь, потому что я разработал очень простую и легкую библиотеку в чистом ванильном JS (DEMO), и это только 1 КБ после gzipping и minification.

Он использует родной прокрутки, поэтому он работает во всех современных браузерах (Firefox, Chrome, Opera, Safari, Edge), а также в IE10 и IE11. Вы также можете использовать его в IE9, включив классList polyfill.

Поддерживаются все браузеры Android, iOS и Windows Phone.

См. более подробный ответ здесь: Пользовательские полосы прокрутки

Или прочитайте полный учебник на странице SimpleScrollbar Github README.

Ответ 3

Существует потрясающая библиотека baron.js. Это может быть пользователь с jQuery или без него. Идея точно такая же, как @AdamSchuld описать в своем ответе.

Его преимущества:

  • Не заменяет собственный механизм прокрутки системы (важно, когда вы хотите, чтобы ваша полоса прокрутки выглядела индивидуально, но сохраняла оригинальную платформу или поведение устройства).

  • Настраиваемый дизайн прокрутки с полной поддержкой CSS.

  • Нет сильных зависимостей от jQuery.

  • Система плагинов (фиксируемые заголовки, липкий нижний колонтитул, автотесты и многое другое)

  • Может быть включен в скрытые блоки

Вот простая демонстрация этого.