В этой публикации я хочу показать один из способов реализации адаптивного горизонтального меню с использованием Flexbox. Данный способ реализации меню используется на сайте Warface Hub , но немного с другой структурой и бо льшим количеством свистелок.

Где-то с год назад, я попал в одну компанию, в которой мне сказали замечательную фразу: «Сначала делаем все с помощью CSS, а потом только добавляем JavaScript». Совет, вроде, хороший, и я ему последовал. Но как бывает, меня понесло. Сейчас мне это аукнулось тем, что не все нужно делать с таким подходом.

И так, ближе к делу. Я приступил к изучению и реализации.

Цели

  1. получить базовые навыки работы с Flexbox свойствами;
  2. разработать горизонтальное адаптивное меню;
  3. полученное решение применить в проекте.

Инструменты и документация

  1. NPM – в качестве менеджера пакетов (теперь активно переезжаем на Yarn)
  2. Grunt – инструмент, который поможет в сборке проекта
  3. Документация по Flexbox (см. Полезные ссылки );
Вы можете использовать свой набор инструментов

Структура

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

  • layout – описывает положение компонентов и элементов на странице;
  • component – описывает отображение и поведение элементов, которые входят в компонент;
  • element – описывает отображение и поведение единичного элемента;
Таким образом мое понимание концепции привело меня к такой структуре:
  • Base - описание констант, базовых стилей (как в normalize.css)
  • Component - описание компонентов приложения. В нашем случае компонент «Menu»
  • Element - описание стилей для элементов таких как кнопка, ссылка и т.п.
  • Layout - описание расположения блоков на странице
  • style.scss - в этом файле мы соберем все вместе

CSS и HTML теги input & label

Прежде чем начать рисовать HTML разметку, я бы хотел напомнить/показать интересное поведение CSS селекторов, которое нам пригодится.


В данном примере Вы можете заметить, что при нажатии на label Вы получите выбранный input. В этом ничего особенного нет (см. ), но самое интересное происходит со стороны CSS селекторов.

Input:checked { border-color: red; }
Данный CSS селектор будет обработан только тогда, когда будет выбран input (см. :checked)

Второй момент, на который нужно обратить внимание в CSS селекторах - это выбор следующего элемента (см. Adjacent sibling selectors и General sibling selectors). То есть мы можем выбрать следующий элемент после текущего.

Input:checked + .label { color: red; }
В этом примере мы получили следующее поведение: при выбранном элементе с классом input следующий за ним элемент с классом label будет изменен в соответствии с описанными стилями.

Теперь это все можно объединить воедино.

Структура меню с одном элементом



В данном примере я добавил несколько элементов input и label, чтобы получилось следующее поведение:
  1. Каждый элемент name=menu-item-trigger, кроме первого, в состоянии:checked будет изменять видимость и позиции последующих элементов label.menu-item-close и div.menu-sub таким образом, чтобы элемент label.menu-item-close полностью перекрывал элемент label.menu-item-label, а div.menu-sub отображался под элементом label.menu-item-label. То есть мы открываем подменю и меняем поведение при клике на основное меню;
  2. Первый элемент name=menu-item-trigger будет использован только для того, чтобы отменить все примененные изменения в предыдущем пункте, то есть закрыть подменю;
Не выбран ни один пункт меню:


Выбран один пункт меню:

После таких манипуляций остается только скрыть элементы input.

Flexbox

Теперь необходимо добавить стили, чтобы данное меню хорошо отображалось при различных разрешениях и различных браузерах. На текущий момент мы сосредоточили наши усилия на поддержке тех браузеров, которые больше всего используются посетителями нашего ресурса. Получился небольшой список: Chrome, Firefox, IE Edge, IE 11 и их мобильные варианты последних версий.

Поддержка осуществляется путем добавления префиксов (postcss) и отдельного написания стилей для конкретного браузера.

Адаптивность в Flexbox достигается очень просто. Достаточно описать контейнер, но иногда будет необходимо решить проблемы с контентом внутри. Например:

  • элементы меню с длинными словами, как «knowledge base» и его немецкий перевод «Wissensdatenbank». В данном случае добавляется оборачивающий элемент для текста, к которому применяются примерно следующие стили:

    Label-text { // @link: http://htmlbook.ru/css/text-overflow overflow: hidden; text-overflow: ellipsis; width: 100%; display: inline-block; }

  • Картинки, которые нужно растянуть по ширине, но при задании width: 100%; они вылезают за пределы родительского блока. Тут поможет box-sizing: border-box; для этого элемента;
  • Так же могут возникнуть проблемы с тем, что дочерние элементы не занимают всю возможную длину или не распределяются равномерно. Тут возможно поможет flex: 1 1 auto.
В данном примере контейнер для элементов описан так:

Menu { display: flex; align-items: center; flex-wrap: wrap; }
Для каждого элемента в контейнере необходимо задать стили так, чтобы он заполнял все возможное пространство и выравнивали контент внутри себя в центре по вертикали:

Menu-item { flex: 1 1 auto; display: flex; flex-direction: column; align-items: stretch; }

Более красивого отображения меню можно достичь с помощью

В данном выпуске сделаем горизонтальное меню с эффектом при наведении. Подключим с шрифтовые иконки, задействуем режим наложения слоев при помощи mix-blend-mode: multiply , используем псевдоклассы :hover , и познакомимся с desplay:flax , все сделаем на чистом CSS3 .

Каркас меню в HTML

Скачивайте архив к себе на компьютер и разархивируйте. В нем находятся три папки, css где расположены файлы стилей, fonts папка с иконками, img в ней картинка на задний фон.

Перенесите все в свою среду разработки, в которой вы работаете. Я весь код буду писать в phpstorm . Копирую все папки и файлы в него, открываю index.html и приступим к описанию каркаса меню.

Прописываем body , тег

, в нем пишем div с классом .dws-menu , далее ul с классом .dws-ul ,затем списки li с классом .dws-li в количестве пяти штук. В списки вложим ссылку, затем I с классом .fa и классом fa- куда пропишем название иконок, далее атрибут aria-hidden=”true” , жмем применить.

Div.dws-menu>ul.dws-ul>li.dws-li*5>a>i.fa.fa-

Название иконок:

  • shopping-cart
  • server
  • folder-open
  • newspaper-o


Оформление CSS стилей

После того как сделали разметку, приступаем к оформлению стилей. Открываем style.css в body задаем задний фон и шрифт Verdana .

Body{ background-image: url("../img/escheresque_ste.png"); font-family: Verdana; }

Блоку с меню задаем фон, с верху делаем отступы в 100 пик. и ширину на весь экран.

Dws-menu{ background-color: white; margin-top: 100px; width: 100%; }

В блоки Ul выстраиваем списки горизонтально с помощью desplay:flax , убираем отступы, и центруем наши элементы при помощи justify-content:center .

Ul.dws-ul{ display: flex; padding: 0; justify-content: center; }

У списков LI убираем маркер и делаем отступ со всех сторон в 10 пик.

Li.dws-li { list-style: none; padding: 10px; }

У ссылок убираем подчеркивание, увеличим текст до 18 пик. и сделаем его черным цветом.

Li.dws-li a{ text-decoration: none; font-size: 18px; color: #000; }

Иконку немного сдвинем правее при помощи margin-right:10px .

Li.dws-li a i{ margin-right: 10px; }

Анимация при наведении

После того как сделали основное оформление приступим к анимированию при наведении.

Создадим дополнительные псевдо элементы, которые будут при наведении подчеркивать название элемента.

Опишем левую часть, отбираем ссылки и присвоим им псевдоэлемент li.dws-li a::before , пишем пустой content:’’; , шириной в 20 пик. и высоту в 3 пик. достаточно. Зададим цвет и для того что бы блок у нас появился присвоим ссылкам position: relative; , и с позиционируем абсолютно ссылкам, спустим его в самый низ, прижмем к левому краю.

Li.dws-li a{ ... position: relative; } li.dws-li a::before{ ... position: absolute; top: 100%; left: 0; }

Дублируем этот блок и присваиваем ему псевдоэлемент ::after . Меняем параметр left на right , цвет выбираем другой #ff2117 .

Li.dws-li a::after{ content: ""; width: 20px; height: 3px; background-color: #ff2117; position: absolute; top: 100%; right: 0; }

Затем делаем анимацию при наведении. Отбираем li и задаем им background чуть темнее.

Li.dws-li:hover{ background-color: #e5eae8; }

Для этого отбираем списки при наведении и добавляем к ним псевдоэлемент с шириной в 50% и задаем трансформацию по оси Х с лева на право. Это предаст ей движение.

Li.dws-li:hover a:before{ width: 50%; transform: translateX(100%); }

Тоже самое повторим для псевдоэлементом ::after , только теперь движение зададим с права на лево.

Li.dws-li:hover a:after{ width: 50%; transform: translateX(-100%); }

Li.dws-li a::before{ ... transition: .5s; mix-blend-mode: multiply; } li.dws-li a::after{ ... transition: .5s; mix-blend-mode: multiply; }

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

Li.dws-li a:hover{ color: #e62117; }

Li.dws-li a{ ... padding: 5px; } li.dws-li a::before{ ... top: 90%; } li.dws-li a::after{ ... top: 90%; }

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



Урок подготовил Горелов Денис.

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

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

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

Что такое Flexbox?

Flexbox – это режим разметки, созданный для упорядочения элементов на странице таким образом, чтобы они вели себя предсказуемо для случаев адаптивности страницы под различные размеры экрана и для различных устройств.

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

На данный момент flexbox поддерживается практически всеми современными браузерами, включая Android и iOS.

Когда использовать Flexbox при верстке макета

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

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

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

Контейнеры, дочерние элементы и Flex

Прежде чем мы начнем писать код CSS с использованием flexbox, есть некоторые важные концепции, с которыми в первую очередь нужно ознакомиться:

  • flexbox – контейнер становится flexbox после того, как подключается свойство display со значением flex или inline-flex
  • flex item – дочерний элемент в flexbox
  • главная ось (main axis) – это основная ось, вдоль которой выравниваются элементы
  • перекрестная ось (cross axis) – ось, перпендикулярная главной оси. Также называется поперечной осью
  • главное начало/главный конец (main-start/main-end) – флекс элементы помещаются в контейнер, который начинается со стороны главного начала, и заканчивается к главному концу
  • перекрестное начало и конец (cross start/end) – флекс линии заполняются items (элементами) и помещаются в контейнер, который начинается со стороны перекрестного начала флекс контейнера и идет к перекрестному концу
  • свойство основного размера (main size) – ширина или высота флекс элемента, в зависимости от того, что находится в основном измерении главной оси, является основным размером элемента. Свойство основного размера элемента flex – это свойство ширины или высоты, в зависимости от того, что находится в основном измерении
  • свойство перекрестного размера (cross size) – ширина или высота флекс элемента, в зависимости от того, что находится в поперечной оси измерении, является перекрестным размером элемента. Свойство перекрестного размера зависит от ширины или высоты, которое находится в поперечном измерении

В CSS есть определенные свойства, на которые не влияет свойство flexbox, поскольку они фактически не делают контейнеры блоками:

Column-* float clear vertical-align::first-line и::first-letter

Создание HTML5 контейнера

Теперь мы можем начать строить макет, используя flexbox. Для этого создайте костяк html-страницы (или же в php, если вы используете CMS).

Заголовок страницы

Создайте родительский контейнер div внутри body:

Внутри этого контейнера вы можете добавить любой контент.

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

Блок информации №1
Блок информации №2
Блок информации №3
Здесь основной контент.

Теперь, чтобы придать этому костяку некоторых красок, добавим несколько основных стилей CSS (вы можете это сделать с помощью отдельного подключаемого файла css стилей, или же включить эти стили в тег в разделе head).

Создание и стилизация Flexbox

Чтобы создать flexbox , нам нужно определить свойство display для нужного контейнера. В нашем примере это свойство для родительского элемента:

Content { display: flex; }

Этот шаг создаст flexbox на уровне блока. В качестве альтернативы (если вы хотите применить inline стили) вы можете использовать inline-flex вместо flex .

Теперь добавим немного CSS стилей, чтобы протестировать работу нашего созданного flexbox.

Стили для респонсивности

Есть много свойств, которые мы можем включить для flexbox, чтобы создать отзывчивый макет.

Чтобы разместить флекс элементы в нужном порядке, достаточно добавить свойство order и короткую запись свойства flex .

Blok { order: 1; flex: 1 1 30%; } article { order: 2; flex: 1 1 auto; }

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

Свойству order передается номер, чтобы сообщить браузеру, какой флекс элемент отображать перед другими. Для order с номером 1 – флекс элемент будет показываться первым. Для 2 – вторым, для 3 – третьим, и так далее.

Вы также можете использовать отрицательные числа. Если вы вдруг поймете при верстке, что вам нужно добавить флекс элемент перед первым, который уже размещен, вы можете установить новому флекс элементу свойство order -1; .

Короткая запись flex состоит из трех свойств:

  • flex-grow – определяет, какую часть свободного пространства может занять контейнер, в соотношении с другими контейнерами. Это может быть только положительное число
  • flex-shrink – свойство, которое определяет фактор сжатия flex элемента. Flex элементы будут заполнять контейнер по значению flex-shrink , когда стандартная ширина flex элементов шире, чем flex контейнер. Отрицательные числа не имеют влияния
  • flex-basis – начальный размер флекс элемента до применения любых флекс размеров и перед тем, как будет занято свободное пространство, или при нехватке места. Может быть задано в пикселях или процентах

Некоторые пояснения по короткой записи свойства:

  • flex: initial или flex: 0 1 auto – этот параметр делает размер флекс элемента относительным содержимому, которое находится внутри него. Он увеличивается, если много контента и сжимается, если контента немного.
  • flex: auto или flex: 1 1 auto – любой из этих параметров позволяет флекс элементу сжиматься и увеличиваться по мере необходимости, чтобы подстраиваться под любой размер экрана.
  • flex: none или flex: 0 0 auto – это отключает гибкость размера и устанавливает размер флекс элемента фиксированным и не регулируемым для пользователя при любом размере экрана.
  • Относительный гибкий размер с flex: 1 % px . Положительное число сначала устанавливает часть свободного места, которое флекс элемент занимает относительно других флекс элементов. Второй номер позволяет уменьшить размер элемента на меньших экранах. Третье значение в пикселях (или процентах) устанавливает начальный размер элемента flex, но имейте в виду, что это значение также отключает свойство flex-basis , что означает, что этот начальный размер не гарантируется. Если для отображения этого начального размера есть достаточно места, то он показывается, но если места недостаточно, то он не отображается. Это особенно верно, если порядок показа элемента находится ниже в списке, а другие предыдущие элементы выше в порядке занимают большую часть пространства. Примером этого параметра будет flex: 2 1 0% .

Чтобы любой из этих параметров сработал, вам нужно сначала установить размер flexbox`а с указанием высоты и ширины.

Основываясь на примере CSS-стилей выше, вот как могут выглядеть стили CSS для flexbox с добавлением размера:

Content { display: flex; width: 75%; height: 450px; }

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

Чтобы выполнить эту настройку, мне нужно добавить это свойство для flexbox контейнера:

Content { display: flex; flex-flow: row wrap; /* флекс элементы заполняют собой строку (row) */ width: 75%; height: 450px; }

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

Теперь, чтобы более-менее понимать, где какой блок, и какие он имеет размеры, добавим несколько дополнительных стилей. Также, весь текстовый контент мы заключили в тег p и добавили этому тегу несколько стилей:

Блок информации №1

Блок информации №2

Блок информации №3

Здесь основной контент.

Стили CSS:

Content { display: flex; flex-flow: row wrap; /* флекс элементы заполняют собой строку (row) */ width: 75%; height: 450px; margin: auto; background-color: #333; } .blok { order: 1; flex: 1 1 30%; background-color: #ccc; margin: 5px; } article { order: 2; flex: 1 1 auto; background-color: #bbb; border: 5px solid #333; padding: 7px; } p { color: #fff; padding: 15px; font-size: 22px; }

И не забывайте, что если вы решите добавить свойство min-width flexbox`у или флекс элементам, это может привести к тому, что flexbox не будет работать должным образом. Также, для адаптивности дизайна, лучше использовать ширину основного контейнера с использованием процентов. Если задать жесткие значения в пикселях, для маленьких экранов адаптивность не сработает.

Ниже представлено демо финального результата:

Попробуйте поиграться с разными стилями, чтобы лучше понять на практике работу flexbox.

В данном выпуске сделаем горизонтальное меню с эффектом при наведении. Подключим с шрифтовые иконки, задействуем режим наложения слоев при помощи mix-blend-mode: multiply , используем псевдоклассы :hover , и познакомимся с desplay:flax , все сделаем на чистом CSS3 .

Каркас меню в HTML

Скачивайте архив к себе на компьютер и разархивируйте. В нем находятся три папки, css где расположены файлы стилей, fonts папка с иконками, img в ней картинка на задний фон.

Перенесите все в свою среду разработки, в которой вы работаете. Я весь код буду писать в phpstorm . Копирую все папки и файлы в него, открываю index.html и приступим к описанию каркаса меню.

Прописываем body , тег

, в нем пишем div с классом .dws-menu , далее ul с классом .dws-ul ,затем списки li с классом .dws-li в количестве пяти штук. В списки вложим ссылку, затем I с классом .fa и классом fa- куда пропишем название иконок, далее атрибут aria-hidden=”true” , жмем применить.

Div.dws-menu>ul.dws-ul>li.dws-li*5>a>i.fa.fa-

Название иконок:

  • shopping-cart
  • server
  • folder-open
  • newspaper-o
  • Главная
  • Магазин
  • Услуги
  • Портфолио
  • Новости


Оформление CSS стилей

После того как сделали разметку, приступаем к оформлению стилей. Открываем style.css в body задаем задний фон и шрифт Verdana .

Body{ background-image: url("../img/escheresque_ste.png"); font-family: Verdana; }

Блоку с меню задаем фон, с верху делаем отступы в 100 пик. и ширину на весь экран.

Dws-menu{ background-color: white; margin-top: 100px; width: 100%; }

В блоки Ul выстраиваем списки горизонтально с помощью desplay:flax , убираем отступы, и центруем наши элементы при помощи justify-content:center .

Ul.dws-ul{ display: flex; padding: 0; justify-content: center; }

У списков LI убираем маркер и делаем отступ со всех сторон в 10 пик.

Li.dws-li { list-style: none; padding: 10px; }

У ссылок убираем подчеркивание, увеличим текст до 18 пик. и сделаем его черным цветом.

Li.dws-li a{ text-decoration: none; font-size: 18px; color: #000; }

Иконку немного сдвинем правее при помощи margin-right:10px .

Li.dws-li a i{ margin-right: 10px; }

Анимация при наведении

После того как сделали основное оформление приступим к анимированию при наведении.

Создадим дополнительные псевдо элементы, которые будут при наведении подчеркивать название элемента.

Опишем левую часть, отбираем ссылки и присвоим им псевдоэлемент li.dws-li a::before , пишем пустой content:’’; , шириной в 20 пик. и высоту в 3 пик. достаточно. Зададим цвет и для того что бы блок у нас появился присвоим ссылкам position: relative; , и с позиционируем абсолютно ссылкам, спустим его в самый низ, прижмем к левому краю.

Li.dws-li a{ ... position: relative; } li.dws-li a::before{ ... position: absolute; top: 100%; left: 0; }

Дублируем этот блок и присваиваем ему псевдоэлемент ::after . Меняем параметр left на right , цвет выбираем другой #ff2117 .

Li.dws-li a::after{ content: ""; width: 20px; height: 3px; background-color: #ff2117; position: absolute; top: 100%; right: 0; }

Затем делаем анимацию при наведении. Отбираем li и задаем им background чуть темнее.

Li.dws-li:hover{ background-color: #e5eae8; }

Для этого отбираем списки при наведении и добавляем к ним псевдоэлемент с шириной в 50% и задаем трансформацию по оси Х с лева на право. Это предаст ей движение.

Li.dws-li:hover a:before{ width: 50%; transform: translateX(100%); }

Тоже самое повторим для псевдоэлементом ::after , только теперь движение зададим с права на лево.

Li.dws-li:hover a:after{ width: 50%; transform: translateX(-100%); }

Li.dws-li a::before{ ... transition: .5s; mix-blend-mode: multiply; } li.dws-li a::after{ ... transition: .5s; mix-blend-mode: multiply; }

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

Li.dws-li a:hover{ color: #e62117; }

Li.dws-li a{ ... padding: 5px; } li.dws-li a::before{ ... top: 90%; } li.dws-li a::after{ ... top: 90%; }

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



Урок подготовил Горелов Денис.




Close