JavaScript обёртка скроллбара в виде jQuery плагина

в 8:02, , рубрики: css, html, jquery, scrollbar, метки: , , ,

Проблема стилизации скроллбара браузера до сих пор актуальна, несмотря на огромное количество скриптов, предназначенных для решения данной задачи. Рассмотрим реализацию стилизуемого скроллбара, максимально приближенного к родному поведению браузера.

Существует два основных подхода для стилизации скроллбара средствами HTML/CSS, каждый из которых имеет свои плюсы и минусы:

  • Эмуляция скролла средствами JavaScript
  • JavaScript обёртка над родным скроллом

Эмуляция скролла средствами JavaScript

Огромным преимуществом данного подхода является то, что это полностью JavaScript решение. Благодаря этому данное решение легче в разработке и является максимально кроссбраузерным (в том плане, что поведение скролла во всех браузерах будет одинаковым, не зависимо от особенностей реализации скролла браузера), оказывая минимальное влияние на HTML структуру и применяемые CSS стили. Подобным подходом пользуются jScrollPane, FleXcroll, Tiny Scrollbar и многие другие.

Однако сильная сторона данного подхода является одновременно и его слабой стороной:

  • Сложность или невозможность эмулировать/перехватить все события
  • JavaScript эмуляция работает медленнее родного скролла

JavaScript обёртка над родным скроллом

Данный подход заключается в том, что родной скролл скрывается средствами HTML/CSS, продолжая выполнять своё предназначение — прокрутку содержимого. Подобное решение является более предпочтительным по той причине, что родной скролл в любом случае работает лучше эмулированного. Многие пробовали создавать плагины на базе этого подхода, но из-за отсутствия каких-либо стандартов, кроссбраузерная реализация очень сложна, и накладывает определённые ограничения на HTML структуру и используемые стили CSS. По этой причине многие разработчики создают реализацию только вертикального скролла, который ведёт себя во всех браузерах более-менее предсказуемо.

Одна из неплохих реализаций подобного подхода была описана совсем недавно в статье Кроссбраузерная кастомизация системного скроллбара с достаточно подробным объяснением.

Изобретение трёхколёсного велосипеда

Одной из причин создания очередного велосипеда явилось то, что поиск по скриптам для стилизации скролла показал более 20 разнообразных плагинов, ни один из которых не подошёл для заказанного проекта. Большинство из известных плагинов не подошли по причине медленной работы при большом количестве инициализированных скроллов на странице. Другие же не подошли из-за неудобной реализации или недостаточной кроссбраузерности.

Было решено сделать собственную реализацию, отвечающую следующим требованиям:

  • Поведение скролла должно быть максимально приближённым к родному
  • Вертикальный и горизонтальный скроллбар
  • Минимальная нагрузка на процессор
  • Полная стилизация внешнего вида средствами HTML/CSS
  • Возможность применить свою HTML структуру для скроллбара, либо указать плагину использовать уже существующий элемент в качестве скроллбара
  • Автоматическое изменение скролла при изменении содержимого или изменении размеров самого контейнера без необходимости переинициализации скрипта
  • Ширина и высота контейнера может быть установлена как в пикселях, так и в процентах, либо ограничена средствами CSS max-height/max-width
  • Скролл может находиться как в любом месте внутри контейнера, так и за его пределами
  • Автоматическое вычисление размеров скроллбара, либо значение, устанавливаемое через CSS стили
  • Поддержка IE7+, Firefox, Chrome, Opera, Safari
  • Возможность «из коробки» отключения скролла для мобильных браузеров

В качестве подхода было выбрано решение сделать плагин в виде JavaScript обёртки над родным скроллом — т.е. оставить функциональность родного скролла, скрыть родной скролл средствами CSS и показать стилизованный скролл. Это даёт преимущество в том, что не нужно эмулировать поведение стандартного скролла, а лишь отлавливать изменения в позиционировании с помощью JavaScript.

Избежать полной эмуляции скролла всё же не получилось — необходимо эмулировать поведение скролла, когда мышь находится над стилизуемым скроллом: отлавливать скролл мыши, drag&drop, клики по самому скроллу и стрелочкам. Идеального решения «Подключил и забыл», конечно же, не получилось. Но практически всех поставленных целей удалось добиться в полной мере.

Демонстрация

Исходные файлы

На заметку

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

  1. Исходный контейнер не должен содержать инлайновые стили
  2. Следует избегать использования padding/margin для контейнера. Если нужен отступ, лучше добавить внутрь ещё один контейнер с необходимым отступом
  3. При изменении содержимого контейнера не стоит обращаться к контейнеру по классу, т.к. эти классы будут использоваться и контейнером-обёрткой

К небольшим недочётам можно отнести разность высоты/ширины прокрутки колёсиком мыши в случаях, когда мышь находится над содержимым контейнера (родное поведение) и когда мышь находится над скроллбаром (эмулируемый скролл). Есть несколько идей, которые довольно сложны в реализации, поэтому оставляю их «на потом».

Также пока не удаётся избавиться от неприятного эффекта прокрутки контейнера при выделении текста в WebKit браузерах Chrome и Safari Частично удалось это сделать при использовании outer-скролла (есть в демонстрации).

Примечания

Из-за разности поведения скролла не только в разных браузерах, но и в разных версиях одного и того же браузера (да-да, того самого браузера), пришлось перепробовать множество комбинаций margin/padding/border/position для вычисления схожего поведения. Во время поиска решения, нашлось несколько интересных особенностей:

  • В ИЕ8 — баги с использованием max-height: в некоторых случаях рендерер 8-й версии ИЕ крашится, либо пытается сделать высоту контейнера равной max-height (официальный баг релиз версии)
  • WebKit-браузеры (Chrome, Safari) при выделении текста делают прокрутку внутреннего контейнера, «обнажая» скрытый скроллбар
  • Если содержимое превышает размеры контейнера, то отображение правого и нижнего паддинга остаётся на усмотрение самого браузера
  • При поиске плагинов, чтобы быстро узнать используется ли стандартный механизм скроллинга, достаточно нажать на скролл мыши, находясь над прокручиваемым контентом

Автор: Gromo

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js