Открыть меню    

Отзывчивая навигация на CSS, число пунктов неизвестно

отзывчивая навигация на CSS Несколько месяцев назад меня попросили разработать простую навигационную панель, которая должна содержать разное количество пунктов меню, а ширина должна быть резиновой и быть равной ширине контейнера-родителя. Количество навигационных элементов неизвестно, задается на стороне и, вероятно, поменяется в будущем.

Размышляя наперед, я пришел к выводу, что было бы непрактично изменять CSS каждый раз, когда потребуется добавить или удалить пункт меню. Также в идеале решение должно быть без javascript.

Используем проценты для ширины

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

Итак, чтобы растянуть пункты на всю ширину нам потребуются проценты.

Проценты являются распространенным методом, чтобы создать резиновую сетку в отзывчивом дизайне.

Например, рассмотрим следующую HTML-разметку:

HTML

<nav>
  <ul>
    <li><a href="/home.html">Home</a></li>
    <li><a href="/about.html">About</a></li>
    <li><a href="/services.html">Services</a></li>
    <li><a href="/products.html">Products</a></li>
    <li><a href="/jobs.html">Jobs</a></li>
    <li><a href="/contact.html">Contact</a></li>
  </ul>
</nav>

И следующий CSS:

CSS

nav {
    width: 100%;
    background: #f0f0f0;
    border: 1px solid #ccc;
    border-right: none;
}

nav ul {
    overflow: hidden;
    margin: 0;
    padding: 0;
}

nav ul li {
    list-style: none;
    float: left;
    text-align: center;
    border-left: 1px solid #fff;
    border-right: 1px solid #ccc;
    width: 16.6667%; /* fallback for non-calc() browsers */
    width: calc(100% / 6);
    box-sizing: border-box;
}

nav ul li:first-child {
    border-left: none;
}

nav ul li a {
    display: block;
    text-decoration: none;
    color: #616161;
    padding: 10px 0;
}
  • Элементу nav задана 100% ширина, чтобы заполнить все возможное пространство элемента-родителя.
  • У элемента li задано два свойства с шириной - width: calc(100% / 6); и width: 16.6667%;. Этим мы размещаем пункты меню в элементе nav, как шесть равных блоков. Свойства width важно установить в правильном порядке, чтобы те браузеры, которые поддерживают calc() могли его использовать. Я предпочитаю использовать calc() с процентами это повышает читаемость кода и позволяет браузеру использовать оптимальный вариант.
  • box-sizing: border-box; задана у элементов li. В этом случае в ширину включаются border-left и border-right. Без использования этого объявления, элементы li не впишутся внутри элемента nav и последний li сместится на новую строку вниз.

Результат от используемых стилей можно увидеть ниже:

See the Pen Резиновая навигация by dnzl ( @dnzl ) on CodePen .

Откройте код в новом окне и протестируйте его на отзывчивость. Желаемый вид достигнут плюс меню отзывчиво.

Что если мы удалим или добавим пункты в меню?

Во что будет, если мы удалим один пункт меню из навигации:

See the Pen Резиновая навигация, удаляем 1 пункт (число пунктов фиксированно) by dnzl ( @dnzl ) on CodePen .

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

Что будет, если добавить один пункт меню?

See the Pen Резиновая навигация, добавляем 1 пункт (число пунктов фиксированно) by dnzl ( @dnzl ) on CodePen .

Сейчас последний пункт меню переместился на вторую строку.

Без паники, я не собираюсь возвращаться в 90-е, чтобы использовать таблицу для макета, это семантически неверно, конечно. Однако, есть значения у свойства display, позволяющие элементу вести себя и выглядеть наподобие таблицы.

Это означает, что вышеприведенный html-код может быть использован со следующим CSS:

CSS

nav {
    display: table;
    table-layout: fixed;
    width: 100%;
}

nav ul {
    display: table-row;
    margin: 0;
    padding: 0;
}

nav ul li {
    list-style: none;
    display: table-cell;
    text-align: center;
}

nav ul li a {
    display: block;
}

Настройки свойства display позволяют элементу na vбыть таблицей, элементу ul - строкой, li – ячейкой таблицы. Отметьте включение объявления table-layout: fixed, благодаря которому пункты меню принимают равную ширину. Его можно удалить, но колебания длины текста может нарушить внешний вид таблицы, поэтому подойдите к этому с осторожностью.

Взгляните на demo, с помощью кнопок добавьте или удалите элементы у навигационной панели.

See the Pen Резиновая навигация с использованием display: table by dnzl ( @dnzl ) on CodePen .

Будущее: flexbox

Flexbox является основным кандидатом на замену вышеприведенного метода. Особенно с учетом вывода из обращения старых версий браузера IE и всевозрастающей поддержкой flexbox в современных браузерах. Если вы не знакомы с flexbox, то можете почитать следующие материалы:

  • (Полное руководство по Flexbox)
  • www.sitepoint.com/are-we-ready-to-use-flexbox/
  • www.w3.org/TR/css3-flexbox/

Главная задумка flex-вёрстки в наделении контейнера способностью изменять ширину/высоту (и порядок) своих элементов для наилучшего заполнения пространства (в большинстве случаев — для поддержки всех видов дисплеев и размеров экранов).

Звучит идеально для решения моей проблемы.

Снова воспользуемся нашим HTML и создадим CSS-стили на основе flexbox.

CSS

nav {
    width: 100%;
}

nav ul {
    display: flex;
    flex-direction: row;
    margin: 0;
    padding: 0;
}

nav ul li {
    list-style: none;
    flex-grow: 1;
    text-align: center;
}

nav ul li a {
    display: block;
}
  • display: flex; применяется к элементу ul и позволяет подключить гибкую среду для его детей.
  • flex-direction: row; применяется к элементу ul и тем самым позиционирует его детей в формате слева направо (определяя направление для flex-элементов). Это значение по умолчанию, так что обозначать его явно необходимости нет.
  • flex-grow: 1; это магия, которая делает дочерние элементы тега ul равными по ширине. Если вы укажете конкретному li значение 2, то этот элемент будет увеличен ровно в 2 раза относительно других элементов.

Flexbox имеет множество интересных особенностей, которые могут быть уместны в зависимости от ситуаций.

Ниже финальный пример построенный на использовании flexbox.

See the Pen Резиновая навигация с использованием Flexbox by dnzl ( @dnzl ) on CodePen .

Как вы можете видеть, достигается тот же результат, что и с табличным макетом. Снова протестируйте пример, добавляя или удаляя новые пункты, используя соответствующие кнопки. Поменяйте размеры окна браузера и обратите внимание на отзывчивость.

Если у вас есть свое решение для создания отзывчивой навигации оставляйте комментарии.

Источник

Комментарии к статье

аватарка пользователя
2016-09-25
Вася

Спасибо, не мог понять что всё дело во "flex-grow: 1;"