Горизонтальная прокрутка меню и изображений на jQuery

Перевод статьи Create a Scrolling Menu with CSS and jQuery.

Существует множество прокручивающихся меню и галерей изображений, созданных на Flash, вот яркие тому примеры 1, 2. Но автор захотел создать аналог на CSS и jQuery, конечно без эффектов смазывания картинки при перемещении, но все же. Это решение хорошо работает в большинстве популярных браузеров и при этом сохраняет доступность элементов при отключенном JavaScript.

Посмотреть результат

 

Разметка

Начнем с создания HTML структуры. Используем ненумерованный список, где каждый элемент содержит изображение и заголовок, так же добавим дополнительный элемент «a».

<div class="sc_menu">
<ul class="sc_menu">
  <li><a href="#">
    <img src="img/1.jpg" alt="Menu"/><span>Menu</span>
  </a></li>
  <li><a href="#">
    <img src="img/2.jpg" alt="Navigation"/><span>Navigation</span>
  </a></li>
  <li><a href="#">
    <img src="img/3.jpg" alt="Scrolling"/><span>Scrolling</span>
  </a></li>
  <li><a href="#">
    <img src="img/4.jpg" alt="jQuery"/><span>jQuery</span>
  </a></li>
</ul>
</div>

Базовая стилизация

Добавляем необходимые стили

div.sc_menu {
  /* Set it so we could calculate the offsetLeft */
  position: relative;
  height: 145px;
  width: 500px;
  /* Add scroll-bars */
  overflow: auto;
}
ul.sc_menu {
  display: block;
  height: 110px;
  /* Max width here, for users without Javascript */
  width: 1500px;
  padding: 15px 0 0 15px;
  /* Remove default margin */
  margin: 0;
  background: url('navigation.png');
  list-style: none;
}
.sc_menu li {
  display: block;
  float: left;
  padding: 0 4px;
}
.sc_menu a {
  display: block;
  text-decoration: none;
}
.sc_menu span {
  /* We want a caption to display on the next line */
  display: block;
  margin-top: 3px;
  text-align: center;
  font-size: 12px;
  color: #fff;
}

Свойства «width» и «overflow» используются для добавления полосы прокрутки в главном div’е. Использование свойства «position» облегчает расчет позиционирования на JavaScript. Не забывайте что отступ считается от родительского элемента. Что должно получиться.

Добавление бордера и эффектов при наведении

Свойство «display: none» скрывает заголовки, и при наведении курсора мыши (:hover) меняется на «display:block».

Свойства «-webkit-border-radius» и «-moz-border-radius » добавляют скругленные углы для правильных браузеров Firefox, Safari и Chrome. Конечно IE не поддерживает ничего подобного вплоть до 8й версии, тем хуже для него :)

Так меню выглядит, когда JavaScript отключен.

.sc_menu span {
  display: none;
  margin-top: 3px;
  text-align: center;
  font-size: 12px;
  color: #fff;
}
.sc_menu a:hover span {
  display: block;
}
.sc_menu img {
  border: 3px #fff solid;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
}
.sc_menu a:hover img {
  filter:alpha(opacity=50);
  opacity: 0.5;
}

jQuery

Сначала нам нужно подключить сам jQuery. Автор использует версию доступную на Google API.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" type="text/javascript"></script>

Что нужно знать для понимания кода:
$() это сокращение для $(document).ready(). Функция в скобках вызывается после того как дерево докумена DOM будет полностью загружено.

$(function(){
  // Your code here
});

Мы используем событие «mousemove» чтоб назначить функцию, которая сработает при перемещении курсора мыши по нашему блоку.

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

Используем «lastLi[0]» чтоб получить элемент из массива jQuery и «offsetLeft» чтоб получить позицию от левого верхнего угла оберточного div’а.

Атрибут «pageX» нашего события (mousemove) возвращает координату курсора по горизонтали относительно всего документа, но нам нужна координата относительно оберточного div’а, для этого просто вычтем из нее «div.offset().left».

Список должен прокручиваться значительно быстрее чем мы передвигаем курсор, чтоб добиться этого используем пропорцию «(ulWidth-divWidth) / divWidth».

Собственно код:

$(function(){
  //Get our elements for faster access and set overlay width
  var div = $('div.sc_menu'),
               ul = $('ul.sc_menu'),
               // unordered list's left margin
               ulPadding = 15;

  //Get menu width
  var divWidth = div.width();

  //Remove scrollbars
  div.css({overflow: 'hidden'});

  //Find last image container
  var lastLi = ul.find('li:last-child');

  //When user move mouse over menu
  div.mousemove(function(e){

    //As images are loaded ul width increases,
    //so we recalculate it each time
    var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;

    var left = (e.pageX - div.offset().left) * (ulWidth-divWidth) / divWidth;
    div.scrollLeft(left);
  });
});

Все готово, результат можно посмотреть здесь.

Навигация по записям