От автора:
В этом учебнике мы посмотрим, чего можно добиться при помощи HTML5 и CSS3, когда речь заходит об основе современных вебсайтов: простом выпадающем навигационном меню. Также мы воспользуемся jQuery для реализации эффектов и выполнения последних штрихов.
HTML5 вносит в спецификацию выделенный элемент <nav>, который следует использовать как контейнер для любой значительной навигационной структуры, такой как основные вертикальные или горизонтальные навигационные меню сайтов, или, например, внутристраничное оглавление. IE (Internet Explorer), к сожалению, пока не поддерживает этот новый элемент, но можно использовать простое решение проблемы, о котором, я уверен, вы все знаете.
Пользуясь CSS3, можно покончить с тем, что потребовало бы использования нескольких фоновых изображений и, возможно, дополнительного упаковочного контейнера или двух, и полагаться (почти) полностью на одно из новых свойств стилей, таких, как закругленные углы и отбрасывание тени, например, которые имеются в наличии у поддерживающих браузеров. К тому же, не все браузеры (опять IE!) поддерживают эти новые правила, но мы можем очень легко обеспечить альтернативные решения для тех из них, которые не могут справиться с нашими стилями.
Перед тем, как мы приступим к практическим шагам, я Вам рекомендую просмотреть демо-результат работы.
Также скачайте исходники себе на компьютер!

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнееШаг 1. Начинаем
Нам потребуется копия последнего на момент написания этой статьи релиза jQuery, версия 1.4.2, а также копия текущей версии (1.1) превосходной библиотеки Modernizr, которые мы применим вместе с используемой CSS3, сосредоточившись на поддерживающих браузерах.
Сделайте где-нибудь в своем компе папку проекта для файлов, которые мы будем создавать, и назовите ее nav, внутри нее сделайте три новых папки; одну с названием js, одну css и одну с именем fallback. Убедитесь, что копии как jQuery, так и Modernizr сохранены в папке js.
Шаг 2. Основная страница
Начните кодирование с создания в своем любимом кодовом редакторе следующей страницы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>HTML5, CSS3 and jQuery Navigation menu</title> <link rel="stylesheet" href="css/nav.css"> <!--[if IE]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body class="no-js"> <nav id="topNav"> <ul> <li><a href="#" title="Nav Link 1">Nav Link 1</a></li> <li> <a href="#" title="Nav Link 1">Nav Link 2 <ul> <li><a href="#" title="Sub Nav Link 1">Sub Nav Link 1</a></li> <li><a href="#" title="Sub Nav Link 2">Sub Nav Link 2</a></li> <li><a href="#" title="Sub Nav Link 3">Sub Nav Link 3</a></li> <li><a href="#" title="Sub Nav Link 4">Sub Nav Link 4</a></li> <li class="last"><a href="#" title="Sub Nav Link 5">Sub Nav Link 5</a></li> </ul> </li> <li><a href="#" title="Nav Link 1">Nav Link 3</a></li> <li><a href="#" title="Nav Link 1">Nav Link 4</a></li> <li><a href="#" title="Nav Link 1">Nav Link 5</a></li> </ul> </nav> <script src="js/jquery.js"></script> <script src="js/modernizr.js"></script> </body> </html> |
Сохраните в папке nav как nav.html. Мы начинаем с минимального объявления doctype’а для HTML5, который позволяет определить тип документа в участке кода, которым мы собираемся использовать. Также устанавливаем по умолчанию язык и кодировку символов; хотя документ останется корректным и без этих вещей, включать их — хорошая привычка, и страница будет выдавать предупреждения во время валидации, если по умолчанию не установлен язык. Затем связываем таблицу стилей (следующим шагом мы ее создадим) и используем условный комментарий, для того чтобы в случае использования IE, закачать прекрасный скрипт Remy Sharp html5.js.
Внутри тега body страницы у нас находится элемент <nav> в качестве контейнера обычного списка ссылок, и еще мы вставили подменю. Этот элемент не создаст для нас навигационное меню волшебным образом и не содержит в себе каких-либо новых элементов пунктов меню (menuitem) или еще чего-нибудь подобного, так что неупорядоченный список – подходящий выбор. Элемент <nav> — всего лишь семантический контейнер нашего меню, который описывает его функцию в документе, чтобы заменить обобщенный элемент <div>, который на странице, по сути, ничего не формулирует.
В конце тега body мы связываемся со своими файлами сценариев jQuery и Modernizr. Пользоваться jQuery мы будем немного позже, когда начнем добавлять функциональность своему меню, а Modernizr начнет работать сразу же, обнаруживая используемый тип браузера и добавляя соответствующую последовательность имен классов в элемент HTML, таким образом, что мы сможем использовать возможности CSS3 только в тех браузерах, где это действительно будет работать. Мы также добавили имя класса no-js в тэг <body> страницы; позднее мы удалим его, если JavaScript даст такую возможность, так что еще используем его для добавления стилей, в случае когда JavaScript отключен.
Шаг 3. Основной дизайн
Теперь давайте добавим немного основного дизайна; создайте следующую таблицу стилей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* JS disabled styles */ .no-js nav li:hover ul { display:block; } /* base nav styles */ nav { display:block; margin:0 auto 20px; border:1px solid #222; position:relative; background-color:#6a6a6a; font:16px Tahoma, Sans-serif; } nav ul { padding:0; margin:0; } nav li { position:relative; float:left; list-style-type:none; } nav ul:after { content:"."; display:block; height:0; clear:both; visibility:hidden; } nav li a { display:block; padding:10px 20px; border-left:1px solid #999; border-right:1px solid #222; color:#eee; text-decoration:none; } nav li a:focus { outline:none; text-decoration:underline; } nav li:first-child a { border-left:none; } nav li.last a { border-right:none; } nav a span { display:block; float:right; margin-left:5px; } nav ul ul { display:none; width:100%; position:absolute; left:0; background:#6a6a6a; } nav ul ul li { float:none; } nav ul ul a { padding:5px 10px; border-left:none; border-right:none; font-size:14px; } nav ul ul a:hover { background-color:#555; } |
Сохраните этот файл в каталоге css как nav.css. Первое правило – исключительно для того, когда JavaScript отключен, оно позволяет скрытому подменю отображаться при проведении над ним мышью исключительно при помощи CSS. Остальной код определяет набор основных стилей, которые размечают меню
Шаг 4. CSS3
Далее можно добавить CSS3:
1 2 3 4 5 6 7 8 9 10 11 |
/* CSS3 */ .borderradius nav { -moz-border-radius:4px; -webkit-border-radius:4px; border-radius:4px; } .cssgradients nav { background-image:-moz-linear-gradient(0% 22px 90deg, #222, #999); background-image:-webkit-gradient(linear, 0% 0%, 0% 70%, from(#999), to(#222)); } .boxshadow.rgba nav { -moz-box-shadow:2px 2px 2px rgba(0,0,0,.75); -webkit-box-shadow:2px 2px 2px rgba(0,0,0,.75); box-shadow:2px 2px 2px rgba(0,0,0,.75); } .cssgradients nav li:hover { background-image:-moz-linear-gradient(0% 100px 90deg, #999, #222); background-image:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#222), to(#555)); } .borderradius nav ul ul { -moz-border-radius-bottomleft:4px; -moz-border-radius-bottomright:4px; -webkit-border-bottom-left-radius:4px; -webkit-border-bottom-right-radius:4px; border-bottom-left-radius:4px; border-bottom-right-radius:4px; } .boxshadow.rgba nav ul ul { background-color:rgba(0,0,0,0.8); -moz-box-shadow:2px 2px 2px rgba(0,0,0,.8); -webkit-box-shadow:2px 2px 2px rgba(0,0,0,.8); box-shadow:2px 2px 2px rgba(0,0,0,.8); } .rgba nav ul ul li { border-left:1px solid rgba(0,0,0,0.1); border-right:1px solid rgba(0,0,0,0.1); } .rgba nav ul ul a:hover { background-color:rgba(85,85,85,.9); } .borderradius.rgba nav ul ul li.last { border-left:1px solid rgba(0,0,0,0.1); border-bottom:1px solid rgba(0,0,0,0.1); -moz-border-radius-bottomleft:4px; -moz-border-radius-bottomright:4px; -webkit-border-bottom-left-radius:4px; -webkit-border-bottom-right-radius:4px; border-bottom-left-radius:4px; border-bottom-right-radius:4px; } .csstransforms ul a span { -moz-transform:rotate(-180deg);-webkit-transform:rotate(-180deg); } |
Пользуясь классами, добавленными Modernizr’ом к элементу <html>, можно легко и безопасно добавлять нужные стили CSS3. Мы применяем стиль border-radius для назначения закругленных углов элементу <nav> мы должны передать для Mozilla и Webkit название стиля с префиксом, вместо обычного border-radius, используемого, например, в Opera. Нам нужно это проделать это c большинством своих стилей CSS3.
Наряду с закруглением углов, <nav> мы также назначаем градиент и отбрасываемую тень. Стили градиентов весьма сложные и отличаются для браузеров, основанных на Mozilla и Webkit, которые являются единственными браузерами, реализующими их в настоящее время. Оба браузера используют свойство background-image. В Firefox для добавления линейного градиента мы используем -moz-linear-gradient. Он требует значений, соответствующих начальной точке градиента (0%), точке, в которой первый цвет сопрягается со вторым цветом (22px), углу оси градиента (90deg), первому цвету (#999) и второму цвету (#222).
В Safari или Chrome можно получить тот же градиент, используя -webkit-gradient и немного другой синтаксис; мы устанавливаем, что это должен быть линейный градиент, а затем предоставляем две точки, которые говорят браузеру, где градиент должен начинаться и заканчиваться. Значения в примере соответствуют левому, верхнему и правому значениям 0% и 70% для низа, что дает нам такой же стиль, как тот, что используется в Firefox. Наконец, мы устанавливаем цвета градиента.
При применении отбрасываемой тени мы сочетаем ее с классом Modernizr для RGBA (см. системы цветопередачи), а также с boxshadow, так что наша тень может быть прозрачной. Свойства для Mozilla и webkit те же, а еще мы обеспечиваем поддерживающим браузерам настоящий box-shadow. Уточненные значения для этого правила – это левое смещение (2px), верхнее смещение (2px), величина размывания границ (2px) и, наконец, цвет тени (0,0,0). RGBA мы как раз используем для цвета, что позволяет установить непрозрачность на 75% (.75).
Другой интересный используемый стиль — transform для вращения текста на 180 градусов; через мгновение мы начнем писать скрипт, и вы увидите, что мы добавляем указатель подменю в виде знака вставки (^) во все пункты списка, содержащие подменю – этот стиль будет вращать символ до тех пор, пока тот не станет показывать вниз, это означает, что для поддерживающих браузеров нам для этой детали даже не нужно использовать изображение.
Оставшиеся правила устанавливают разные градиенты, закругленные углы, непрозрачность при помощи RGBA и отбрасываемые тени для других элементов в меню <nav>, таких как красивые нижние закругленные углы и отбрасываемая тень на подменю, и с тем же успехом инвертируем градиент с целью добиться привлекательного состояния наведения (hover). Теперь наше навигационное меню в поддерживающем браузере должно выглядеть таким образом:
В поддерживающих браузерах элементы можно заставить выглядеть действительно классно, не пользуясь при этом ни единым изображением, то есть наши страницы будут загружаться гораздо быстрее, при помощи намного меньшего количества требований HTTP. Однако не все браузеры будут поддерживать дизайн CSS3, лучше всего любая версия IE, так что нам все же придется определять fallback стили (альтернативные). Добавьте в таблицу стилей следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* fallbacks */ .no-cssgradients nav, .no-js nav { padding-bottom:4px; border:none; background:url(../fallback/navBG.gif) repeat-x 0 0; } .no-borderradius nav ul, .no-js nav ul { background:url(../fallback/navRight.gif) no-repeat 100% 0; } .no-borderradius nav ul ul, .no-js nav ul ul { background:none; } .no-borderradius nav li, .no-js nav li { height:44px; } .no-cssgradients nav li:hover, .no-js nav li:hover { background:url(../fallback/navOverBG.gif) repeat-x 0 0; } .no-borderradius nav li li, .no-js nav li li { height:auto; width:98%; left:-2px; } .no-borderradius nav li:first-child, .no-js nav li:first-child { background:url(../fallback/navLeft.gif) no-repeat 0 0; } .no-borderradius nav li:first-child:hover, .no-js nav li:first-child:hover { background:url(../fallback/navOverLeft.gif) no-repeat 0 0; } .no-borderradius nav li li:first-child, .no-js nav li li:first-child { background:none; } .no-rgba nav ul ul, .no-js nav ul ul { left:1px; padding-left:2px; background:url(../fallback/subnavBG.png) no-repeat 100% 100%; } .no-rgba nav ul ul a, .no-js nav ul ul a { left:3px; } .no-rgba nav ul ul a:hover { background:url(../fallback/subOverBG.png) repeat 0 0; } .no-csstransforms ul a span { height:7px; width:12px; margin-top:8px; text-indent:-5000px; overflow:hidden; background:url(../fallback/indicator.png) no-repeat 0 0; } .no-borderradius ul ul li.last { margin-bottom:10px; } .no-cssgradients.boxshadow nav { box-shadow:none; } |

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнееModernizr к тому же добавит названия классов, показывающие, какие из характеристик CSS3 недоступны для браузера, так что мы легко можем применить альтернативные правила, основанные на использовании изображений, достигая с их помощью тех же результатов.
Вы заметите, что мы здесь также пользуемся селекторами, нацеленными на класс no-js; когда JavaScript неактивен, Modernizr не запустится и не добавит имена классов, нужные нам в документе, так что наши fallbacks не-CSS3 также становятся fallbacks для не-js.
Шаг 5. Добавляем скрипт
Теперь давайте добавим скрипты. Первое, что нам нужно сделать – это убрать класс no-js из тэга body страницы, когда JavaScript не отключен. Нам нужно это сделать как можно раньше до отрисовки страницы, чтобы избежать мерцания при смене стилей. Прямо за начальным тэгом body добавьте следующий код:
1 2 3 4 |
<script> var el = document.getElementsByTagName("body")[0]; el.className = ""; </script> |
Все, что мы делаем – это получаем элемент <body> по имени тэга и устанавливаем его свойство className в пустую строку. В обычных условиях мы бы использовали для этого jQuery, но из-за того, что jQuery еще не загружен, когда этот скрипт выполняется, мы его не можем использовать. Можно было бы, конечно, загрузить перед этим jQuery, но тогда мы рискуем создать потенциальную проблему производительности. Наш скрипт состоит всего из 2 строк кода, так что не вызовет значимой задержки, а так как он будет исполняться даже до того, как браузер обработает разметку элемента <nav>, мерцания содержимого не будет.
Теперь, когда класс удален из основы, наши подменю CSS уже не будут работать, так что можно добавить эту функциональность обратно с помощью jQuery и, в то же время, немного ее улучшить. В конце документа, сразу после ссылки скрипта на Modernizr, вставьте следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<script> (function($){ //cache nav var nav = $("#topNav"); //add indicators and hovers to submenu parents nav.find("li").each(function() { if ($(this).find("ul").length > 0) { $("<span>").text("^").appendTo($(this).children(":first")); //show subnav on hover $(this).mouseenter(function() { $(this).find("ul").stop(true, true).slideDown(); }); //hide submenus on exit $(this).mouseleave(function() { $(this).find("ul").stop(true, true).slideUp(); }); } }); })(jQuery); </script> |
Скрипт относительно прямолинеен; мы оборачиваем свой код в замыкание (closure) и передаем его объекту jQuery безопасно назначая пространство имен (jQuery) знаку доллара, на случай, если используется другая библиотека когда код попадет в продуктив. Затем кэшируем ссылку на элемент <nav>, так что можем ссылаться на него, не выбирая постоянно из документа. Затем обрабатываем каждый пункт списка в меню.
Проверяем каждый подходящий элемент, содержит ли он какие-либо вложенные элементы <ul>, и если содержит, то добавляем в пункт списка новый элемент <span>. Это будет наш указатель подменю. Когда подменю найдено, привязываем обработчики событий mouseenter() и mouseleave() к пункту списка, содержащего меню. Все, что они выполняют — это в установленном порядке показывают и скрывают подменю путем выдвижения его вниз и вверх. Обратите внимание на использование метода stop(), помогающего предотвратить анимацию открытия и закрытия по очереди в случаях, когда указатель мыши постоянно надвигается и убирается с указанных пунктов списка.
На данный момент мы должны быть спокойны относительно большинства ситуаций; в любом браузере, поддерживающем HTML5, наше меню обязано выглядеть сравнительно одинаковым, несмотря на то, поддерживается CSS3 или нет, и разрешено использование скриптов или нет. Однако IE создает для нас проблему; когда активирован JS, скрипт htmlshiv.js дает понять IE, что означает элемент <nav> и наши стили не-css3 выбираются и приводятся в исполнение – очень хорошо и чудесно (у нас все еще есть расхождения с IE7, скажем, не понимаются и не принимаются правила автоочистки :after, но чуть позже мы ими займемся).
Однако проблемы начинаются, когда используется IE с выключенными скриптами – в этом положении скрипт html5shiv.js не исполняется и IE не понимает элемента <nav>. Ни один из наших селекторов, содержащих в себе nav, не будет выполняться! Хотя это и не конец света; мы можем предусмотреть альтернативную таблицу стилей, используемую только тогда, когда браузер – IE и в нем выключен JS. Сразу после скрипта, удаляющего класс no-js из элемента <body> добавьте следующее:
1 2 3 4 5 |
<noscript> <!--[if IE]> <link rel="stylesheet" href="css/ie.css"> <![endif]--> </noscript> |
Действительно простое решение. Теперь нам нужно создать новую таблицу стилей; вставьте следующие правила в новый документ своего редактора кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* ie styles for when js disabled */ ul { display:block; padding:0; margin:0; background:url(../fallback/navRightIE.gif) no-repeat 100% 0; font:16px Tahoma, Sans-serif; } ul:after { content:"."; display:block; height:0; clear:both; visibility:hidden; } li { height:44px; position:relative; float:left; list-style-type:none; background:url(../fallback/navBG.gif) repeat-x 0 0; } li.last a { border-right:none; } li:hover { background:url(../fallback/navOverBG.gif) repeat-x 0 0; } li:first-child { background:url(../fallback/navLeftIE.gif) no-repeat 0 0; } li:first-child a { border-left:none; } li:first-child:hover { background:url(../fallback/navOverLeft.gif) no-repeat 0 0; } li a { display:block; padding:10px 20px; border-left:1px solid #999; border-right:1px solid #222; color:#eee; text-decoration:none; } li li { width:auto; clear:left; } li li:first-child { background:none; } li li:hover { background-image:none; } ul li li a:hover { border-right:none; } ul ul { display:none; padding-left:2px; position:absolute; left:2px; background:url(../fallback/subnavBG.png) no-repeat 100% 100%; } ul li:hover ul { display:block; } li li { height:auto; width:98%; left:-2px; } ul ul a:hover { background:url(../fallback/subOverBG.png) repeat 0 0; } ul a span { height:7px; width:12px; margin-top:8px; text-indent:-5000px; overflow:hidden; background:url(../fallback/indicator.png) no-repeat 0 0; } ul ul li { background:none; } ul ul li.last { margin-bottom:10px; } ul ul li a { padding:5px 10px; border-left:0; left:3px; font-size:14px; white-space:pre; } |
Сохраните все это как ie.css в папке css. Как можно видеть, в этой таблице стилей мы вовсе не нацелились на элемент <nav> некоторые из присвоенных элементу <nav> стилей ранее вместо этого были добавлены в элемент <ul>, и для этого сценария существует несколько новых стилей, которые в него специально нужно добавить. По существу таблица стилей создает тот же эффект, что и до этого, так что IE8 с неактивным JS все еще должна выглядеть как тут:
Мы вынуждены воспользоваться еще парой изображений в этом сценарии, потому что для подвешивания background-repeat на основном градиенте у нас больше нет элемента <nav>. Итак, все современные браузеры с активным и неактивным JS работают как полагается – используя CS3 где это возможно, и альтернативные изображения – где нет.
IE7 для нас все еще будет создавать проблемы, даже с включенными скриптами, но это можно довольно легко исправить, использовав другой условный комментарий специально для IE7, и обеспечив новую таблицу стилей только для IE7, которая исправляет проблемы разметки; нужно что-то вроде это:
1 2 3 4 5 |
* styles to fix IE7 */ ul { display:inline-block; } ul li a span { position:absolute; right:5px; top:10px; } ul ul li a { border-right:none; padding:5px 10px; } .content { clear:both; } |
Сохраните это в папке css как ie7.css и добавьте новый условный комментарий в <head> страницы:
1 2 3 4 |
<!--[if IE 7]> <link rel="stylesheet" href="css/ie.css"> <link rel="stylesheet" href="css/ie7.css"> <![endif]--> |
Вот так вот; навигационное меню построено и отделано новейшими элементами и стилями с fallback-ами и исправлениями для более старых браузеров.
Автор: Dan Wellman
Перевод и редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.
Источник: //net.tutsplus.com

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее
Также скачайте исходники себе на компьютер! — не качается!
К сожалению есть такое дело. Связано с тем, что на сайте, с которого делался перевод, также не скачивается исходник.
Сделал все как написанно. Но в итоге нормальный результат получается только когда открываешь страничку через мозилу. а через другие браузеры фон меню белый текст тоже белый единственое когда наводишь на выподающее меню там все более менее нормально отражается. Кто подскажет в чем проблема?
Неправильно подключил jquery и modernizr, у меня была такая же проблема
пасибки за урок))) всё прекрасно работает)
Исходники не скачиваются, жаль…
Скажите пожалуйста, как полученные nav.html, nav.css ie.css и прочие файлы интегрировать на сайт на движке joomla (версия 1.7)
Пасиб-Пастараюсь всё усвоить
Нужно подключать modernizr и shiv или хватает modernizr ??