Статьи

Адаптивная, плавная навигация по переменным элементам с помощью CSS

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

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

Использование ширины в процентах

Фиксированная ширина не может постоянно заполнять отзывчивый контейнер, как показано на рисунке ниже.

Пример навигации с фиксированной шириной

Поэтому нам нужно использовать проценты для достижения этой цели. Проценты являются распространенным методом для достижения плавного расположения сетки в адаптивных проектах и ​​пригодятся здесь.

Например, примите во внимание приведенный ниже знакомый 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:

 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>width: 100%
  • Элементы <li>width: calc(100% / 6); и width: 16.6667%; , Здесь пункты меню разделены по элементу <nav> Порядок, в котором перечислены эти свойства, важен для того, чтобы браузеры, поддерживающие calc() Браузеры без поддержки calc() Я склонен использовать calc() Таким образом, мне не нужно беспокоиться о том, включать ли повторяющиеся десятичные разряды.
  • box-sizing: border-box; объявлен на элементах <li> Это заставляет свойство widthborder-leftborder-right Без использования этого свойства элементы <li><nav><li> Многие предпочитают устанавливать box-sizing: border-box; ко всем элементам, чтобы легко управлять шириной, как полагает Пол Айриш .

Результат добавления этих стилей показан в демонстрации CodePen ниже:

Откройте его в новом окне и проверьте его на отзывчивость. Желаемый вид достигается, и это гибкий.

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

Вот что произойдет, если мы удалим один элемент из навигации с нашим текущим CSS на месте:

Как видите, справа есть пустое место, где находился последний элемент навигации.

Как насчет того, чтобы добавить дополнительный элемент навигации?

Теперь последний элемент навигации переносится на второй ряд.

Понятно, что это не удовлетворяет всем нашим требованиям. JavaScript можно использовать для подсчета количества пунктов меню, определения процента и применения значений ширины с помощью циклического перемещения по элементам <li> Тем не менее, я всегда неохотно использую JavaScript для определения макета, если нет других вариантов. Плюс, это не была бы статья CSS, если бы я собирался описать, как это сделать! Вернуться к чертежной доске, это …

(Пере) введение макета таблицы

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

Это означает, что более раннюю структуру HTML все еще можно использовать со следующим 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<nav><ul><li> Обратите внимание на включение table-layout: fixed Это может быть удалено, но колебания длины текста могут привести к тому, что таблица выйдет из равновесия, поэтому подходите осторожно.

Вот демонстрация с кнопками, позволяющими вам добавлять / удалять элементы:

Это может быть не самый чистый подход (извинения за ненавистники таблицы), но это работает, и это просто. Поддержка браузера тоже хороша .

Будущее: Flexbox

Flexbox является выдающимся кандидатом на замену этого метода в будущем, поскольку более старые версии Internet Explorer постепенно сокращаются , а поддержка flexbox в браузерах продолжает улучшаться. Если вы не знакомы с flexbox, вы можете проверить эту недавнюю статью на SitePoint или посетить спецификацию , которая объясняет это следующим образом:

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

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

Опять же, используя более ранний HTML, вот CSS для построения подхода flexbox к решению этой проблемы:

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

Следует отметить следующие свойства flexbox:

  • display: flex; Это применяется к элементу <ul>
  • flex-direction: row; присваивается <ul> Это значение по умолчанию, поэтому оно явно не требуется.
  • flex-grow: 1; это магия, которая равномерно распределяет элементы <li> Если бы вы указали конкретное значение <li>

У Flexbox есть некоторые интересные функции, которые могут быть уместны в других случаях использования, такие как возможность переупорядочивать пункты меню путем объявления свойства order

Вот наша последняя демонстрация с использованием Flexbox:

Как вы можете видеть в приведенной выше демонстрации CodePen, тот же результат достигается. Опять же, вы можете использовать кнопки для проверки добавления или удаления одного элемента. Вы также можете добавить больше элементов, отредактировав HTML. И, изменив размер окна вашего браузера, вы сможете увидеть его плавность.

Если вам когда-либо приходилось решать эту проблему, сообщите нам, как вы ее достигли и какую технику вы использовали.