Заметки программиста

Каждый будний день, ровно в 9, я пишу о себе, о своей работе и о технологиях web программирования123

Перевод статьи 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);
  });
});

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

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

Comments

There are 25 comments for this post.

  1. Linkdump #9 | CTAPbIu_MABP's BLOG on Март 9, 2009 4:34 пп

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

  2. toni on Март 16, 2009 3:08 пп

    что то делаю и никак не выходит

  3. andrey on Март 31, 2009 6:19 пп

    если делать без скриптов, только средствами html и css
    как бороться с произвольной шириной в step1.htm?

  4. andrey on Март 31, 2009 6:34 пп

    Сам допер
    с помощью замечательного тега table, просто навтыкать сколько надо ячеек в одну строку и всего делов – и за ширину голова не болит
    помешались все просто на этих дивах

  5. Mihalytch on Май 8, 2009 8:47 дп

    Спасибо!!! Очень помогла ваша статья)

  6. Andyre on Май 19, 2009 4:26 пп

    Почему скрипт не вставляется в table? помогите разобраться???

  7. andrey on Май 19, 2009 9:02 пп

    table я использовал только для того чтобы обойтись вообще без скриптов
    зачем его в table вставлять??
    это очень хорошая и понятная статья – перечитайте ее еще раз

  8. Sergey on Июнь 24, 2009 3:57 пп

    А можно выложить весь код примера от начала <java> до конца </java> (с описанием, типа… выделеный текст меняем на свой и т. д.)?
    Чтоб в дальнейшем просто подредактировать код под свои нужды.

  9. Антонов Андрей on Июнь 24, 2009 6:28 пп

    Просто откройте исходный код примера http://valums.com/wp-content/uploads/2009/02/menu...

  10. Антонов Андрей on Июнь 24, 2009 6:28 пп

    Просто откройте исходный код примера http://valums.com/wp-content/uploads/2009/02/menu...

  11. Flame on Июль 16, 2009 7:16 дп

    а как с неё можно сделать вертикальную прокрутку?

  12. толерантный негр on Июль 26, 2009 10:03 дп

    <style type="text/css">
    body {
    padding: 50px 0 0 50px;
    }
    div.sc_menu {
    /* Set it so we could calculate the offsetLeft */
    position: relative;
    height: 300px;
    width: 170px;
    overflow: auto;
    }
    ul.sc_menu {
    display: block;
    height: 110px;
    /* max width here, for users without javascript */
    width: 1500px;
    padding: 15px 0 0 15px;
    /* removing default styling */
    margin: 0;
    background: url('navigation.png');
    list-style: none;
    }
    .sc_menu li {
    display: block;
    padding: 0 4px;
    }
    .sc_menu a {
    display: block;
    text-decoration: none;
    }
    .sc_menu span {
    display: block;
    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;
    }

    /* Here are styles for the back button, don't look at them */
    #back {
    display: block;
    width: 500px;
    text-align: center;
    color: #003469;
    font-size: 16px;
    }
    </style>
    <script type= "text/javascript">/*<![CDATA[*/
    $(function(){
    //Get our elements for faster access and set overlay width
    var div = $('div.sc_menu'),
    ul = $('ul.sc_menu'),
    ulPadding = 15;

    //Get menu width
    var divHeight = div.height();

    //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 ulHeight = lastLi[0].offsetTop + lastLi.outerHeight() + ulPadding;
    var top = (e.pageY – div.offset().top) * (ulHeight-divHeight) / divHeight;
    div.scrollTop(top);
    });
    });
    /*]]>*/</script>

  13. Endreu on Июль 29, 2009 1:57 пп

    Все ясно, не подскажите, как выровнять картинки по ценрту(т.е. чтоб они были на одно центральной оси) чтоб не выравнивались на одну линию вверху

  14. Сергей on Август 8, 2009 7:33 пп

    Спасибо большое за скрипт. Так как я первый раз использую jQuery после прочтения данной статьи, прошу подсказать , можно ли сделать так, чтобы при загрузке списка выделять текущую картинку, и размещать её например в центре списка.
    Признак того, что какая то картинка текущая можно использовать любой, я потом программно сформирую это участок кода.

  15. Иосиф on Октябрь 7, 2009 5:50 пп

    Спасибо за скрипт, но не подскажите почему он не работает при подключении скрипта lightbox?

  16. Иосиф on Октябрь 7, 2009 6:12 пп

    Спасибо за скрипт, но такая проблема: при подключении скрипта lightbox, отключается прокрутка .

  17. Леха on Октябрь 17, 2009 8:53 дп

    Вместо lightbox используйте highslide.js, все работает отлично, пример в подписи
    Но тоже заметил, что подключение различных скриптов может пагубно сказаться на работоспособности этого скрипта

  18. Алексей on Октябрь 27, 2009 7:54 пп

    Скрипт супер, то что искал, огромное спасибо!!!

  19. vlad76 on Ноябрь 2, 2009 7:42 дп

    Помогите разобратся..
    Я когда поставил этот скрипт, то фото у меня почемуто скачат при перемещении вправо влево.. Подскажите как исправить эту ошибку…
    http://korzina.kiev.ua/hodor.index.html

  20. vlad76 on Ноябрь 2, 2009 8:05 дп

    Спасибо я уже сам разобрался… Классный скрипчик…Давно мечтал..

  21. Cooper on Ноябрь 2, 2009 2:30 пп

    НЕ работает в ИЕ8

  22. Dgikar on Июнь 8, 2010 12:11 дп

    Можете подсказать, почему, когда изменяешь высоту и /или ширину, прокрутка перестает работать?
    P. S.
    Браузеры Mozilla и IE6

  23. johnyy on Июль 10, 2010 7:27 пп

    Подскажите как сделать такой скролл: http://emfire.ru/

  24. Salt on Август 8, 2010 12:35 дп

    Добрый вечер, подскажите, возможно ли реализовать на CSS 2 пропорциональный авто-ресайз фоновой картинки, как на этом сайте? http://www.alexandergusev.com/

  25. bodun on Август 17, 2010 4:05 пп

    в IE 8 все прекрасно работает, не вноси смуту в народ, Cooper !

Write a Comment

Let me know what you think?