Пользователь
0,0
рейтинг
23 мая 2013 в 21:01

Разработка → Справочник фронт-энд девелопера: виды горизонтальных панелей навигации

HTML*, CSS*

Предисловие: работая верстальщиком, ваш покорный слуга заметил, что существует несколько типов меню; при этом для верстки каждого из них следует использовать свои приемы.
Подробности — под катом.

Данная статья нацелена скорее на начинающих верстальщиков, но, может быть, матерые профессионалы тоже найдут в ней что-то новое или будут обращаться к ней как к справочнику.
Топик структурирован следующим образом: сначала ставится задача — описывается вид требуемого навигационного блока, затем рассматриваются приемы, позволяющие создать именно такую навигацию.
Подразумевается, что написание стилей ведется под семантически корректную структуру меню, которая выглядит примерно так:


  
    Домой

    Сделать заказ
    Обратная связь
  



При верстке под doctype, отличный от html5, элемент nav опускаем или заменяем на соответствующий div.

Что ж, начнем!..

Пункты меню, расположенные по правой/левой стороне


В данном разделе рассмотрены навигационные блоки, в которых элементы размещены по правой/левой стороне. Для верстки таких блоков, в зависимости от ситуации, можно использовать несколько способов:
  1. display: inline;
  2. float: left/right;
  3. display: inline-block.


Display: inline

Когда применяем
Данный способ целесообразно применять при верстке меню простого вида, в котором элементы представлены в виде отдельных слов, не имея padding'ов и разделены лишь пробелами между ними:


Живой пример


Как делается
У элементов li в CSS нужно установить свойство display: inline. Кстати, это уберет и ненужные в большинстве меню такого вида маркеры, так как они находятся в дополнительных блоках, которые содержатся у элементов с display: list-item, а у inline'ов отсутствуют.
У ul устанавливаем свойство text-align в значение right или left соответсвенно.

Примечания
  • При использовании этого варианта стоит помнить, что у inline элементов вертикальные margin'ы не учитываются, но горизонтальные работают;
  • при необходимости верстки pixel perfect, есть вероятность столкновения с проблемой: в разных браузерах ширина пробела между элементами разная. Для решения проблемы расстояние между элементами выставляют margin'ами, а пробелы убирают;
  • если подчеркивание в ссылках элементов меню сделать нижним border'ом, в современных браузерах можно получить красивое анимированное на :hover меню (JSFiddle).


Float: left/right

Когда применяем
Когда необходимо сделать меню с элементами, имеющими padding'и и/или фиксированную высоту/ширину:


Живой пример
Таким способом сверстано верхнее меню Themeforest:



Как делается
Устанавливаем float: left или float:right элементам li. Если нужно убрать маркеры, нужно добавить display: block или list-style: none.

Примечания
  • Необходимо «очистить» ul, задав ему класс .clearfix или поместив в его конец элемент с clear: both, иначе у ul высота будет равна нулю; о других способах «очистки» float'ов можно прочитать здесь;
  • пример интересного меню, сверстанного float'ами: html5guy.


Display: inline-block

Когда применяем
Задачи те же, что и при верстке с float. И да, при решении такой задачи inline-block пал в неравном бою. Во-первых, кроссбраузерность такого решения ниже, чем у float'a, а во-вторых, между inline-block'ами, как и между inline-элементами, появляются пробелы, зачастую ненужные. Эти проблемы решаемы, но зачем их создавать?

Как делается
Устанавливаем display: inline-block элементам li. Ну, а для IE7 (если вы его поддерживаете) прописываем *display:inline; *zoom: 1.

Симметричные относительно левой и правой сторон блоки навигации


В данном разделе рассмотрены навигационные блоки, расположенные симметрично. Существует несколько видов таких меню; каждому из них соответствует свой способ верстки:
  1. пункты меню выровнены по центру;
  2. пункты меню равномерно распределены по всей ширине, между элементами имеется промежуток;
  3. пункты меню равномерно распределены по всей ширине, элементы заполняют всю ширину ul.


Пункты меню выровнены по центру

Когда применяем
Меню расположено по центру:




Живой пример


Как делается
В зависимости от вида пунктов меню, устанавливаем display: inline или display: inline-block (если для пунктов меню предусмотрены padding'и задана ширина и/или высота) элементам li. Родителю (ul) устанавливаем text-align: center.

Примечания
Позволю себе повториться: иногда появляется необходимость в том, чтобы убрать пробелы между inline- и inline-block- элементами; несколько способов решения этой задачи можно найти здесь.

Пункты меню равномерно распределены по всей ширине, между элементами имеется промежуток

Когда применяем
Пункты меню равномерно распределены по всей ширине, между отдельными пунктами имеются промежутки:




Живой пример
К сожалению, меню такого типа найти не удалось, поэтому здесь — пример с JSFiddle.



Как делается
В зависимости от вида пунктов меню, устанавливаем display: inline или display: inline-block элементам li. Родителю (ul) устанавливаем text-align: justify. Но сразу justify не заработает — нужно переполнить первую строку (если непонятно почему так — запускаем ворд и пытаемся растянуть несколько слов на всю ширину при помощи justify). Поэтому в конец элемента ul добавляем дополнительный элемент с display: inline-block и width: 100%, или, что лучше, псевдо-элемент ::after с такими же характеристиками.

Примечания
Помните, в предыдущих типах меню мы убирали пробелы между элементами со свойством display, установленным в inline и inline-block? Так вот, в этом случае так делать категорически нельзя — браузеру нужны промежутки между пунктами меню. Кстати, если убрать пробелы между некоторыми элементами, можно группировать кнопки (JSFiddle):


Пункты меню равномерно распределены по всей ширине, элементы заполняют всю ширину ul.

Когда применяем
Между пунктами меню нет промежутков, любое количество пунктов меню занимает всю ширину:


Живой пример
Apple.com:


Пример подобного меню на JSFiddle можно потрогать здесь.


Как делается
При решении данной задачи есть соблазн сверстать меню таблицами; но мы же не собираемся нарушать семантику документа, правда? Поэтому используем display: table-cell для li и display: table для ul; потом задаем ширину для ul
Если нужна поддержка старых браузеров, используем скрипт-полифилл, подменяющий такие блоки на таблицы для IE6 и IE7 или организуем fallback другими способами.

Примечания
При верстке меню данным способом нужно помнить, что нельзя размещать элементы с position: absolute относительно table-cell.
Почему?
Дело в том, что в спецификации w3c действие position: relative на table-cell не определено, поэтому в каждом браузере могут наблюдаться свои особенности.
Посмотрите этот пример в разных браузерах (особо пристально смотрим на поведение Mozilla Firefox!).

Для решения этой проблемы в ячейку нужно помещать div, относительно которого производить позиционирование.


Итог


В статье перечислены основные виды меню и особенности их верстки. Надеюсь, этот материал пригодится вам, спасибо за внимание.
@everyonesdesign
карма
29,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (16)

  • –5
    1 и 3 — остальные не нужны.
  • +1
    мой стандарт:

    .menu ul li{
    position:relative;
    display:inline-block;
    vertical-align:top; /*FIX IE*/
    //float:left; /*FIX IE*/
    }

    и в IE можно не проверять)
    • 0
      Беглый тест в IE6-7 показал:
      1. position:relative; не влияет на раскладку
      2. не ведет себя как inline-block, а ведет себя как float
      3. vertical-align:top; делает ul высотой равной высоте строки внутри .menu (что поначалу сбило с толку)

      Вывод:
      Решение не рабочее, избыточное, запутывающее(коммент про vertical-align и хак с 2 слешами вместо звездочки).

      Решение давно известно:
      display: inline-block;
      *display: inline;
      zoom: 1;
      


      З. Ы. Если нужна поддержка IE — надо проверять, особенно в вашем случае.
  • +1
    Для html5 есть flexbox umaar.github.io/css-flexbox-demo/, но жаль что пока не все браузеры это умеют.
  • 0
    Не совсем понятно зачем в примере на :hover дополнительно прописаны transition-duration

    li a:hover {
        padding-bottom: 3px;
        -webkit-transition-duration: .3s;
        -moz-transition-duration: .3s;
        transition-duration: .3s;
        border-bottom: 1px solid #dd9999;
    }
    

    • 0
      Да и border повторяется
      li a:hover {
          padding-bottom: 3px;
      }
      
    • 0
      Для того, чтобы вернуть исходное состояние с заданным эффектом, без него это был бы просто скачок.
      • 0
        Ничего подобного, не будет никакого скачка. Все данные анимации задаются один раз, как правило главному классу. А дальше всем манипуляциям типа :hover или просто через добавление класса, добавляются только свойства которые нужно поменять — jsfiddle.net/kjCL7/20/
  • –7
    Мне одному показалось, что это крутой материал?
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Пустую строку после justify-style меню как-то можно сделать нулевой высоты?
    • 0
      Нет, так как она имеет высоту line-height, и она, емнип, не может быть нулевой в Вебките.
      • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          Старых вебкитов всё равно ещё дофига, особенно в андроидах.
          • НЛО прилетело и опубликовало эту надпись здесь

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