JScrollPane. Делаем красивый скроллинг

Автор: Александр Головко Дата публикации: 28.06.2010
Последнее обновление: 07.06.2011

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

Например, такой:

ахриненно красивый скроллбар

Задача

Реализовать вертикальный скроллбар, отвечающий следующим требованиям:

  • соответствие дизайну;
  • кроссбраузерность;
  • возможность скроллить колесиком мыши.

Решение

Не будем изобретать велосипед, благо умные люди уже поработали за нас. Используем бесплатный плагин jScrollPane — он полностью отвечает перечисленным требованиям.

Update 7.06.2011. Далее идет речь о первой версии данного плагина. Версии 2 посвящена отдельная статья JScrollPane 2 — настраиваемый скроллбар.

С помощью этого плагина можно сделать вот такой скролл или вот такой.

Проверено в:

  • IE 6-8
  • Firefox 3
  • Opera 9.5-10
  • Safari 3

Кому мало, можно посмотреть другие примеры на официальной странице плагина.

Что качать?

Быстрый старт

Подключаем библиотеки и не забываем про CSS:

<link type="text/css" rel="stylesheet" href="css/jScrollPane.css"/>

<script type="text/javascript" src="js/jquery-1.4.2.min.js" ></script>
<script type="text/javascript" src="js/jquery.mousewheel.min.js"></script>
<script type="text/javascript" src="js/jScrollPane.js"></script>

Создаем в HTML контейнер для скролла:

<div class="scrollBox">
	<div id="pane" class="scroll-pane">
		Хочу себе необычный скролл!
	</div>
</div>

В CSS задаем оформление контейнера:

.scroll-pane {
	width: 700px; /* Ширина видимой области*/
	height: 275px; /* Высота видимой области*/
	overflow: auto; /* Если отключены скрипты это правило позволит отобразить обычный скролл */
}

Настраиваем стили из jScrollPane.css и рисуем картинки (подробнее об этом ниже).

Последний шаг — инициализируем скролл скриптом:

<script type="text/javascript">
	jQuery(function()
	{
		jQuery('#pane').jScrollPane({scrollbarWidth:18, showArrows:true});
	});
</script>

А теперь обо всем подробнее

Подробнее о HTML

В примере выше создается два контейнера: scroll-pane и scrollBox, а используется фактически только scroll-pane. Для чего же нужен внешний контейнер scrollBox? Он пригодится для позиционирования области с прокруткой, так как спозиционировать сам scroll-pane достаточно трудно, ведь скрипт обернет его еще и своим собственным контейнером. Вообще говоря, использовать внешний див (у нас scrollBox) для позиционирования — это совет из официального сайта плагина.

Подробнее о CSS

Обещаный подробный разбор jScrollPane.css:

.jScrollPaneContainer {
	position: relative;
	overflow: hidden;
	z-index: 1;
}

/* Трек - полоса по которой бегает ползунок */
.jScrollPaneTrack {
	position: absolute;
	cursor: pointer;
	right: 0;
	top: 0;
	height: 100%;
	background: url(../images/scrollTrak.gif) repeat-y; /* задаем фоновую картинку или просто цвет фона */
}

/* Средняя часть ползунка (резиновая, т.к. ползунок меняет высоту в зависимости от количества содержимого) */
.jScrollPaneDrag {
	position: absolute;
	background: url(../images/scrollDrag.gif) repeat-y; /* задаем фоновую картинку или просто цвет фона */
	cursor: pointer;
	overflow: hidden;
	left:1px;
}
/* верхушка ползунка (можно задать height:0, если ползунок не имеет выраженной верхушки) */
.jScrollPaneDragTop {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	background: url(../images/scrollDragTop.gif) no-repeat; /* задаем фоновую картинку или просто цвет фона */
	height:3px; /* высота верхушки */
}
/* низ ползунка (можно задать height:0, если ползунок не имеет выраженного низа) */
.jScrollPaneDragBottom {
	position: absolute;
	bottom: 0;
	left: 0;
	overflow: hidden;
	background: url(../images/scrollDragBot.gif) no-repeat; /* задаем фоновую картинку или просто цвет фона */
	height:3px; /* высота низа */
}
/* стрелка вверх (правило можно исключить, если скролл по дизайну без стрелок) */
a.jScrollArrowUp {
	display: block;
	position: absolute;
	z-index: 1;
	top: 0;
	right: 0;
	text-indent: -2000px;
	overflow: hidden;
	height: 18px; /* высота стрелки (ширина определяется шириной скролла при инициализации скрипта) */
	background: url(../images/arrow_up.gif) no-repeat; /* задаем фоновую картинку или просто цвет фона */
}
/* стрелка ввниз (правило можно исключить, если скролл по дизайну без стрелок)*/
a.jScrollArrowDown {
	display: block;
	position: absolute;
	z-index: 1;
	bottom: 0;
	right: 0;
	text-indent: -2000px;
	overflow: hidden;
	height: 18px; /* высота стрелки (ширина определяется шириной скролла при инициализации скрипта) */
	background: url(../images/arrow_down.gif) no-repeat; /* задаем фоновую картинку или просто цвет фона */
} 

Подробнее о js

Определены две функции:

jScrollPane инициализирует скролл, согласно заданным параметрам (список см. в таблице ниже).
jScrollPaneRemove «деинициализация» — удаляет стильный скролл и восстанавливает стандартный.

Прараметры jScrollPane()

Название функции Описание функции Тип данных
scrollbarWidth ширина нестандартной полосы прокрутки в пикселях. Значение по умолчанию 10 int
scrollbarMargin отступы слева от полосы прокрутки в пикселях. Значение по умолчанию 5 int
wheelSpeed указывает, как быстро колесо мыши заставит контент прокручиваться в пикселях. Значение по умолчанию 18 int
showArrows указывает, отображать ли стрелки на полосе прокрутки. Значение по умолчанию false boolean
arrowSize высота стрелок если showArrows=true (если не задана, рассчитывается из CSS) int
animateTo нужна ли анимация при вызове scrollTo и scrollBy. Значение по умолчанию false boolean
dragMinHeight минимальная высота, при которой можно будет перетащить ползунок. Значение по умолчанию 0 int
animateInterval Интервал в миллисекундах для обновления анимации scrollPane. Значение по умолчанию 100 int
animateStep Расстояние, которое проходить ползунок за один шаг анимации. Значение по умолчанию 3 int
maintainPosition Если вы хотите, чтобы полоса прокрутки сохраняла свое положение при переинициализации, тогда она не будет прокручиваться при добавлении большего количества контента. Значение по умолчанию true boolean
scrollbarOnLeft Определяет, что полоса прокрутки должна появиться слева от контента (убедитесь, что CSS также отражает этот момент) boolean
reinitialiseOnImageLoad Должен ли скрипт автоматически переинициализироваться при подгрузке картинок в контенте. Значение по умолчанию false boolean

Немного о динамике

В случае, если ширина (высота) скролла меняется динамически необходимо вызвать последовательно функции jScrollPaneRemove и jScrollPane.

Предположим, имеем такой CSS:

.scrollBox{
	width:200px;
}

.scroll-pane {
	width: 100%;
	height: 100px;
	overflow: auto;
}

Скрипт изменяет ширину scrollBox, тем самым автоматически меняя ширину .scroll-pane:

<script type="text/javascript">
jQuery('#more').click(function() {
	jQuery('.scrollBox').css('width','300px');
	jQuery('#pane').jScrollPaneRemove();
	jQuery('#pane').jScrollPane({scrollbarWidth:18, showArrows:true}); 
});
</script>

Демо пример

Проверено в:

  • IE 6-8
  • Firefox 3
  • Opera 9.5-10
  • Safari 3

Нюанс с прокруткой колесиком мыши

У jScrollPane есть одна интересная особенность. Если крутить скролл колесиком мыши, то после того, как все содержимое контейнера проскроллится, начинает крутиться основной скроллбар страницы (конечно если он имеется).

Судя по коду jScrollPane.js это сделано специально (а значит это не баг а фича). Но если эта особенность мешает, ее запросто можно отключить.

Лезем в код jScrollPane.js и находим там строки:

$container.bind(
 'mousewheel',
 function (event, delta) {
 ...тра-та-та многабукофф...
 return !dragOccured;
 }
);

Меняем return !dragOccured; на return false;

Все! Теперь колесико ведет себя более логично и не будет управлять основным скроллом страницы, пока курсор мыши не выйдет за пределы контейнера.

Прокрутка к нужной позиции (update 1.08.10 by Евгений Рыжков)

Иногда требуется сразу (или по какому-то действию) прокрутить блок с таким скроллингом до определенной позиции. Для этого плагин имеет две (почему-то плохо описанные) функции:

scrollTo
прокрутить контент до указанной позиции. Позицию можно указать в px (считаем от верхней границы этого самого блока с прокруткой) или задать id — блок прокрутится до элемента с указанным id
scrollBy
прокрутить блок на указанное число пикселей относительно текущей позиции

Функции цепляются к блоку, на который вешалась инициализация скроллинга.

<script type="text/javascript">
jQuery('#pane').jScrollPane({scrollbarWidth:18, showArrows:true}); 
jQuery('#pane')[0].scrollTo(500);
</script>

Обращу внимание, что "[0]" — это обязательно. Зачем оно — не знаю (желающим узнать копать код плагина), но без этого не работает.

Плюсы:

  • адекватно работает во всех популярных браузерах;
  • позволяет гибко настроить вид и поведение скролла;
  • скролится колесиком мыши.

Минус:

  • Не реализована горизонтальная прокрутка. В версии JScrollPane 2 этот минус убрали (дополнение от Igor Charly).

Выводы

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

Материал