Як створити випадаюче навігаційне меню за допомогою HTML5, CSS3 і jQuery

12

Від автора:

У цьому підручнику ми подивимося, чого можна домогтися за допомогою HTML5 і CSS3, коли мова заходить про основі сучасних вебсайтів: простому випадаючому меню закладок. Також ми скористаємося jQuery для реалізації ефектів та виконання останніх штрихів.

HTML5 вносить в специфікацію виділений елемент , який слід використовувати як контейнер для будь-якої значної навігаційної структури, такої як основні вертикальні або горизонтальні навігаційні меню сайтів, або, наприклад, внутристраничное зміст. IE (Internet Explorer), на жаль, поки що не підтримує цей новий елемент, але можна використовувати просте рішення проблеми, про яку, я впевнений, ви всі знаєте.

Користуючись CSS3, можна покінчити з тим, що вимагало б використання декількох фонових зображень і, можливо, додаткового пакувального контейнера або двох, і покладатися (майже) повністю на одне з нових властивостей стилів, таких, як закруглені кути і відкидання тіні, наприклад, які є в наявності у підтримуючих браузерів. До того ж, не всі браузери (знову IE!) підтримують ці нові правила, але ми можемо дуже легко забезпечити альтернативні рішення для тих з них, які не можуть впоратися з нашими стилями.

Перед тим, як ми приступимо до практичних кроків, я Вам рекомендую переглянути демо-результат роботи.

Також завантажте вихідні коди собі на комп’ютер!

Крок 1. Починаємо

Нам буде потрібно копія останнього на момент написання цієї статті релізу jQuery, версія 1.4.2, а також копія поточної версії (1.1) чудової бібліотеки Modernizr, які ми застосуємо разом з використовуваної CSS3, зосередившись на підтримуючих браузерах.

Зробіть де-небудь в своєму компі папку проекту для файлів, які ми будемо створювати, і назвіть її nav, всередині неї зробіть три нових папки; одну з назвою js, одну css і одну з ім’ям fallback. Переконайтеся, що копії jQuery, так і Modernizr збережені в папці js.

Крок 2. Головна сторінка

Почніть кодування зі створення в своєму улюбленому кодовому редакторі наступної сторінки:

HTML5, CSS3 and jQuery Navigation menu

  • Nav Link 1
  • Nav Link 2

    • Sub Nav Link 1
    • Sub Nav Link 2
    • Sub Nav Link 3
    • Sub Nav Link 4
    • Sub Nav Link 5
  • Nav Link 3
  • Nav Link 4
  • Nav Link 5

Збережіть у папці nav як nav.html. Ми починаємо з мінімального оголошення doctype’а для HTML5, який дозволяє визначити тип документа в ділянці коду, яким ми збираємося використовувати. Також встановлюємо за замовчуванням мова та кодування символів; хоча документ залишиться коректним і без цих речей, включати їх — хороша звичка, і сторінка буде видавати попередження під час валідації, якщо не вибрано за промовчанням мову. Потім пов’язуємо таблицю стилів (наступним кроком ми її створимо) і використовуємо умовний коментар, для того щоб у випадку використання IE, закачати прекрасний скрипт Remy Sharp html5.js.

Всередині тега body сторінки у нас знаходиться елемент в якості контейнера звичайного списку посилань, і ще ми вставили підменю. Цей елемент не створить для нас навігаційне меню чарівним чином і не містить в собі якихось нових елементів пунктів меню (menuitem) або ще чого-небудь подібного, так що ненумерованний список – відповідний вибір. Елемент — всього лише семантичний контейнер нашого меню, який описує його функцію в документі, щоб замінити узагальнений елемент

, який на сторінці, по суті, нічого не формулює.

В кінці тега body ми зв’язуємося зі своїми файлами сценаріїв jQuery і Modernizr. Користуватися jQuery ми будемо трохи пізніше, коли почнемо додавати функціональність своєму меню, а Modernizr почне працювати відразу ж, виявляючи тип браузера і додаючи відповідну послідовність імен класів елемент HTML, таким чином, що ми зможемо використовувати можливості CSS3 тільки в тих браузерах, де це дійсно буде працювати. Ми також додали ім’я класу no-js в тег сторінки; пізніше ми видалимо його, якщо JavaScript дасть таку можливість, так що ще використовуємо його для додавання стилів, у разі коли JavaScript відключений.

Крок 3. Основний дизайн

Тепер давайте додамо трохи основного дизайну; створіть наступну таблицю стилів:

/* 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:10px 5px; border-left:none; border-right:none; font-size:14px; }
nav ul ul a:hover { background-color:#555; }

Збережіть цей файл у каталозі css як nav.css. Перше правило – виключно для того, коли JavaScript відключений, воно дозволяє прихованого підменю відображатися при проведенні над ним мишею виключно за допомогою CSS. Решті код визначає набір основних стилів, які розмічають меню
так, як нам потрібно, без додавання надлишку декоративних деталей. Зверніть увагу, що ми користуємося псевдоселектором :after для установки властивості clear плаваючих пунктів списку; зазвичай цю річ реалізують, додаючи ім’я класу, до контейнерів кожного плаваючого елемента на сторінці. На цій стадії наша сторінка має виглядати так:

Як створити випадаюче навігаційне меню за допомогою HTML5, CSS3 і jQuery

Крок 4. CSS3

Далі можна додати CSS3:

/* 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’го елементу , можна легко і безпечно додавати потрібні стилі CSS3. Ми застосовуємо стиль border-radius для призначення закруглених кутів елементу ми повинні передати для Mozilla і Webkit назва стилю з префіксом, замість звичайного border-radius, що використовується, наприклад, в Opera. Нам потрібно зробити це c більшістю своїх стилів CSS3.

Поряд із заокругленням кутів, ми призначаємо градієнт і тінь. Стилі градієнтів досить складні і відрізняються для браузерів, заснованих на 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 і відкидає тіні для інших елементів у меню , таких як гарні нижні закруглені кути і отбрасываемая тінь на підменю, і з тим же успіхом інвертуємо градієнт з метою добитися привабливого стану наведення (hover). Тепер наше навігаційне меню підтримує браузері повинна виглядати таким чином:

Як створити випадаюче навігаційне меню за допомогою HTML5, CSS3 і jQuery

В браузерах що підтримують елементи можна примусити виглядати дійсно класно, не користуючись при цьому єдиним зображенням, тобто наші сторінки будуть завантажуватися набагато швидше, за допомогою набагато меншої кількості вимог HTTP. Однак не всі браузери будуть підтримувати дизайн CSS3, найкраще будь-яка версія IE, так що нам все ж доведеться визначати fallback стилі (альтернативні). Додайте в таблицю стилів наступний код:

/* 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; }

Modernizr до того ж додасть назви класів, що показують, які з характеристик CSS3 недоступні для браузера, так що ми легко можемо застосувати альтернативні правила, засновані на використанні зображень, досягаючи з їх допомогою тих же результатів.

Ви помітите, що ми тут також користуємося селекторами, націленими на клас no-js; коли JavaScript неактивний, Modernizr не запуститься і не додасть імена класів, потрібні нам в документі, так що наші fallbacks не-CSS3 також стають fallbacks для не-js.

Крок 5. Додаємо скрипт

Тепер давайте додамо скрипти. Перше, що нам потрібно зробити – це прибрати клас no-js тега body сторінки, коли JavaScript відключений. Нам це потрібно зробити якомога раніше до відтворення сторінки, щоб уникнути мерехтіння при зміні стилів. Прямо за початковим тегом body додайте наступний код:

var el = document.getElementsByTagName(«body»)[0];
el.className = «»;

Все, що ми робимо – це отримуємо елемент по імені тега і встановлюємо його властивість className в порожній рядок. У звичайних умовах ми б використовували для цього jQuery, але з-за того, що jQuery ще не завантажений, коли цей скрипт виконується, ми його не можемо використовувати. Можна було б, звичайно, завантажити перед цим jQuery, але тоді ми ризикуємо створити потенційну проблему продуктивності. Наш скрипт складається всього з 2 рядків коду, так що не викличе значущою затримки, а так як він буде виконуватися навіть до того, як браузер обробить розмітку елемента , мерехтіння вмісту не буде.

Тепер, коли клас видалений з основи, наші підменю CSS вже не будуть працювати, так що можна додати цю функціональність назад за допомогою jQuery і, в той же час, трохи її поліпшити. В кінці документа, відразу після посилання скрипта на Modernizr, вставте наступний код:

(function($){
//cache nav
var nav = $(«#topNav»);
//add indicators and hovers to submenu parents
nav.find(«li»).each(function() {
if ($(this).find(«ul»).length > 0) {
$(««).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);

Скрипт щодо прямолінійний; ми обертаємо свій код в замикання (closure) і передаємо його об’єкту jQuery безпечно призначаючи простір імен (jQuery) знаку долара, на випадок, якщо використовується інша бібліотека коли код потрапить в продуктив. Потім кешуємо посилання на елемент , так що можемо посилатися на нього, не вибираючи постійно з документа. Потім обробляємо кожен пункт списку в меню.

Перевіряємо кожен відповідний елемент, що містить які-небудь вкладені елементи

    і якщо містить, то додаємо в пункт списку новий елемент . Це буде наш покажчик підменю. Коли підменю знайдено, прив’язуємо обробники подій mouseenter() і mouseleave() до пункту списку, що містить меню. Все, що вони виконують — це у встановленому порядку показують і приховують підменю шляхом висунення його вниз і вгору. Зверніть увагу на використання методу stop(), що допомагає запобігти анімацію відкриття і закриття по черзі у випадках, коли вказівник миші постійно насувається і забирається з зазначених пунктів списку.

    На даний момент ми повинні бути спокійні щодо більшості ситуацій; в будь-якому браузері, що підтримує HTML5, наше меню зобов’язана виглядати порівняно однаковим, незважаючи на те, підтримується CSS3 чи ні, і дозволено використання скриптів чи ні. Однак IE створює для нас проблему; коли активований JS скрипт htmlshiv.js дає зрозуміти IE, що означає елемент і наші стилі не-css3 вибираються і приводяться до виконання – дуже добре і чудово (у нас все ще є розбіжності з IE7, скажімо, не розуміються і не приймаються правила автоочищення :after, але трохи пізніше ми ними займемося).

    Однак проблеми починаються, коли використовується IE з вимкненими скриптами – у цьому положенні скрипт html5shiv.js не виконується і IE не розуміє елемента . Жоден з наших селекторів, що містять в собі nav, не буде виконуватися! Хоча це і не кінець світу; ми можемо передбачити альтернативну таблицю стилів, яка використовується тільки тоді, коли браузер – IE і в ньому вимкнений JS. Відразу після скрипта, що видаляє клас no-js елемента додайте наступне:

    Дійсно просте рішення. Тепер нам потрібно створити нову таблицю стилів; вставити наступні правила в новий документ свого редактора коду:

    /* 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:10px 5px; border-left:0; left:3px; font-size:14px; white-space:pre; }

    Збережіть все це як ie.css в папці css. Як можна бачити, в цій таблиці стилів ми зовсім не націлилися на елемент деякі з присвоєних елементу стилів раніше замість цього були додані елемент

      і для цього сценарію існує кілька нових стилів, які в нього спеціально потрібно додати. По суті таблиця стилів створює той же ефект, що і до цього, так що IE8 з неактивним JS все ще повинна виглядати як тут:

      Як створити випадаюче навігаційне меню за допомогою HTML5, CSS3 і jQuery

      Ми змушені скористатися ще парою зображень в цьому сценарії, бо що для підвішування background-repeat на основному градієнті у нас більше немає елемента . Отже, всі сучасні браузери з активними та неактивними JS працюють як належить використовуючи CS3 де це можливо, і альтернативні зображення – де ні.

      IE7 для нас все ще буде створювати проблеми, навіть з включеними скриптами, але це можна досить легко виправити, використавши інший умовний коментар спеціально для IE7, і забезпечивши нову таблицю стилів тільки для IE7, яка виправляє проблеми розмітки; потрібно щось на кшталт це:

      * 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:10px 5px; }
      .content { clear:both; }

      Збережіть це в папці css як ie7.css і додайте новий умовний коментар сторінки:

      Ось так ось; навігаційне меню побудовано і оброблене новітніми елементами і стилями з fallback-ами і виправленнями для старих браузерів.

      Переклад і редакція: Ріг Віктор і Андрій Бернацький. Команда webformyself.