Адаптивное меню на флекс бокс пошаговая инструкция. Флексбокс для интерфейсов: основные паттерны

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

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

Гибкие атомарные компоненты

В интерфейсе Tracks реализован подход, рассматривающий каждый фрагмент изолированно на основе принципов Брэда Фроста .

Философию атомарного дизайна можно рассматривать как аналог ЛЕГО-блоков для веб-дизайна. Научные термины такие как организм, молекула, атом используются для того, чтобы дать разработчикам классификацию элементов интерфейса и, соответственно, более глубокое понимание каждого фрагмента как части целого. Этот способ категоризации создает возможность для идентификации этих паттернов и предотвращает влияние на этот процесс внешних факторов, таких как сетки, цвета и расстояния. Построение интерфейса с микроуровня дает возможность более широкого многократного использования его базовых микроэлементов.

Иллюстрация 1. Эти элементы приложения используются для вывода данных на основе принципов атомарного дизайна. Можете ли вы угадать, в каких из них используется Флексбокс? (увеличенная версия)

Иллюстрация 2. Основной интерфейс приложения Tracks, использующий преимущества флексбокса и атомарного дизайна. (увеличенная версия)

Дизайн интерфейса был передан как набор прототипов InVision , с документацией потока и пользовательского интерфейса. В течение первоначального аудита интерфейса, я начал выявлять области, где имеет смысл внедрить флексбокс. Я также решил использовать флексбокс для раскладки страницы, используя традиционные паттерны “боковая колонка слева, основной контент справа”, обычно реализуемые на плавающих блоках.

Html.flexbox ul.flexbox-target, html.no-js ul.flexbox-target { display: flex; flex-direction: row; } html.no-flexbox ul.flexbox-target li, html.no-js ul.flexbox-target li { display: inline-block; /* Could also use a float-positioned-layout system instead */ }

Там где поддержка флексбокса отсутствует, мы будем использовать display: inline-block . К этой же декларации мы добавим класс no-js , на случай отключения в браузере JavaScript. Каскад CSS будет работать даже там, где нет ни флексбокса, ни JavaScript, а также при проблемах с загрузкой. Флексбокс может сосуществовать с float , display: table и position: relative ; браузеры, поддерживающие флексбокс использует его в приоритетном порядке, а браузеры его не поддерживающие ограничатся традиционными механизмами раскладки CSS.

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

Строчные паттерны

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

Иллюстрация 3. Эта навигация административной панели использует строчный паттерн с вертикальным центрированием элементов навигации. (увеличенная версия)

Разметка паттерна навигации административной панели состоит из тега nav , оборачивающего ссылки. Вот HTML этого паттерна:

И соответствующие стили:

Nav { display: flex; align-items: center; /* Center navigation items vertically */ } nav a { display: inline-block; /* To avoid layout issues for inline elements with the order property in IE 10 */ } nav a { flex: 1; }

CSS получился такой же минималистичный, как и разметка. Обратите внимание на inline-block , заданный для навигационных ссылок. Эта декларация решает любые возможные будущие проблемы в IE10, в случае, если вы решите поменять последовательность элементов со свойством order . Также мы знаем, что все внешние и внутренние отступы, заданные прямым потомкам флекс-контейнера вызывают проблемы с раскладкой в IE10, во избежание таких вещей имеет смысл всегда кроссбраузерно проверять верстку.

Иллюстрация 4. Паттерн навигации в шапке сайта с центрированным лого часто встречается в вебе и легко адаптируется к флексбоксу. (увеличенная версия)

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

Раскладка состоит из коллекции элементов меню, размещенных по левую и правую сторону от логотипа в центре. Разметка для этого паттерна следующая:

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

До появления флексбокса разработчики использовали подходы display: inline-block и даже float: left , чтобы организовать строчную раскладку. Теперь флексбокс стал жизнеспособным вариантом и разработчиков ничто не вынуждает использовать плохие практики ради красивого дизайна. Требуемый CSS не столь краток, как в предыдущем примере с паттерном на иллюстрации 3, но он проще в реализации, чем старые методы.

Pipeline-header { display: flex; align-items: center; justify-content: space-between; } .pipeline-header > a { display: inline-block; /* IE 10 doesn"t recognize order, so we do this to avoid odd layouts there. */ } .pipeline-logo { flex: 1; order: 2; text-align: center; } .pipeline-nav { flex: 1.25; order: 1; } .pipeline-search { flex: 1; order: 3; } a { order: 4; }

При использования флексбокса в паттерне с иллюстрации 3, помните, что последовательность в разметке может быть изменена. Если логотип требуется сдвинуть, это легко делается с помощью свойства order . Учитывайте, что порядок в разметке важен для доступности и это вызывает противоречия, когда дело доходит до флексбокса, особенно с учетом различной реализации доступности в браузерах . Браузеры (кроме Firefox) и скринридеры используют для навигации с клавиатуры порядок разметки, а не визуальный порядок, созданный средствами CSS.

Иллюстрация 5. Поток, представленный в разметке и его рендеринг в браузере, изменение последовательности с помощью флексбокса без изменений разметки. (увеличенная версия)

Ниже представлен код для такой раскладки. Разметка не используется для изменения порядка вывода элементов.

Здесь CSS используется для изменения порядка вывода элементов диаграмме справа иллюстрации 5.

Container { display: flex; flex-direction: columns; /* row is the default value */ } header { order: 2; } main { order: 3; } footer { order: 1; }

Этот тип раскладки используется не только для навигации. Вы могли видеть его в футере.

Иллюстрация 6. Тот же паттерн, который мы применяли для навигации, используется в футере. (увеличенная версия)

При использовании этого паттерна учитывайте, что контенту может не хватить пространства в контейнере. Должен ли контент распространяться от центра к краям? Как это повлияет на остальные элементы раскладки? Думайте об этих вопросах до того, как к приступать к реализации проекта. И учитывайте, что навигация с клавиатуры важна для пользователей.

Строчные поля ввода

Формы могут быть кошмаром для разработчиков, особенно когда они тесно связаны с замысловатой структурой сетки, сделанной в Photoshop. Паттерн “inline label”, как я его называю, также важен для нашей индустрии как Fender Stratocaster для рок-музыки.

Иллюстрация 7. Строчные лейблы и поля ввода это еще одна область использования флексбокса. Но будьте осторожны с тем, как текст лейбла отталкивает поле ввода в зависимости от количества текста. (увеличенная версия)

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

Иллюстрация 8. Решайте, как ваш контент будет расширяться. Слева display:table с вертикальным выравниванием по середине, справа флексбокс с выравниванием по центру. (увеличенная версия)

Эти скриншоты четко показывают ошибки флексбокса с динамическим или большим содержимым. Эффект на правом изображении я называю “выталкивание от центра”, это означает, что новое содержимое стремится от центра к краям.

Вот разметка для паттерна строчного лейбла на иллюстрации 8.

Решением проблемы будет использование display: table; для длинного текста. Это позволяет контенту идти сверху вниз, а не от центра к краям.

Form-group { display: flex; } .form-group label { display: table; vertical-align: middle; } .form-group input { flex: 1; }

Сочетание флексбокса и display: table это отличная техника, которую имеет смысл изучить глубже. Но при ее использовании важно всегда проверять раскладку в тестовом окружении, чтобы своевременно выявлять баги.

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

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

Необходимый HTML типичен и включает див-обертку для структуры флексбокса.

А вот и стили:

Form-group { display: flex; } .form-group input { flex: 1; }

Выпадающее меню

Иллюстрация 10. Участок страницы с выпадающим меню выделен при помощи возможностей флексбокс для быстрого позиционирования. (увеличенная версия)

Выпадающее меню состоит из колонки слева, содержащей вертикально центрированные строчные элементы, и списка элементов справа, в котором каждый элемент расположен на своей строке.

Иллюстрация 11. Меню основного интерфейса построено с использованием флексбокса для раскладки. (увеличенная версия)

Разметка для этой навигационного меню использует следующий HTML в качестве основы.

Соответствующий ему CSS прост и понятен, все, как любят разработчики.

Menu { display: flex; } .menu__options { display: flex; align-items: center; } .menu__items { display: flex; flex-direction: column; }

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

Медиа-объекты

Иллюстрация 12. В паттерне медиа-объект используется флексбокс, SVG фиксированной ширины располагается слева, а все остальное содержимое флексбокса располагается рядом. (увеличенная версия)

В этом универсальном паттерне, известном как “медиа-объект”, изображение или видео располагается на одной стороне, а остальное содержимое рядом.

Medi-obj { display: flex; align-items: flex-start; } .media-obj__body { flex: 1; }

Иллюстрация 13. Это крайний случай изменения размера окна браузера, изображению задана максимальная ширина и правой части задан флекс равный 1. Будьте осторожны, когда смешиваете элементы фиксированной ширины и элементы с флексом

Флексбокс отлично работает с этим паттерном, но будьте осторожны, ведь медийное содержимое может взаимодействовать с остальным содержимым так, как показано выше. В примере вы видите, как графическое пространство схлопывается, а текст выталкивается сверху. Это может показаться глупым примером, потому как, кто сделает свой браузер настолько узким? Но важно не это - просто мы должны понимать как содержимое соотносится со своим окружением перед тем, как использовать флексбокс.

Решением для этого паттерна будет задание изображениям max-width: 100% для медиа внутри флексбокса или использование фиксированной ширины изображений и медиа-запросов для их регулировки при необходимости.

Календарь на флексбоксе

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

В данном выпуске сделаем горизонтальное меню с эффектом при наведении. Подключим с шрифтовые иконки, задействуем режим наложения слоев при помощи 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%; }

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



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

В данном выпуске сделаем горизонтальное меню с эффектом при наведении. Подключим с шрифтовые иконки, задействуем режим наложения слоев при помощи 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%; }

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



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

Всем привет! На начало 2018 года, по данным сайта Can I Use , верстка на flexbox-ах , поддерживается браузерами на 97.8%. Это отличные показатели для этой уже далеко не новой технологии по верстки сайтов. Теперь уже нет причин, почему не пользоваться этим удобным способом верстки. Чем мы сейчас и займемся.

Сверстав несколько макетов на CSS flexbox-ах , уже не хочется возвращаться к устаревшим float-ам и даже к такому любимому среди верстальщиков фреймворку, как Bootstrap . Хотя, Bootstrap ещё рано списывать со счетов, ведь используя его знаменитую сетку, можно "не париться" по поводу медиа запросов.

На этом уроке мы сверстаем шапку сайта с типичным адаптивным меню с применением flexbox CSS метода.

Шапка состоит из трех логичных блоков:

  1. Блок с логотипом
  2. Блок с меню, сделанное на списках
  3. Блок с иконкой и номером телефона

Эти три блока будут помещены в общий внешний блок-обертку header , который внутри себя будет делать display: flex; для трех блоков.

Внутри блока nav , еще раз пропишем display: flex; для пунктов меню. Таким образом мы добьёмся гибкости, при уменьшении размеров экрана, пункты меню могут выстраиваться друг под другом.

Для наглядной демонстрации сделаем всю HTML разметку для шапки сайта.







+380973457685



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

А сейчас внимание! Достаточно указать двум блокам display: flex; и всё содержимое шапки вытянется в строчку.

Header {
display: flex;
}

Header .menu ul {
display: flex;
}

Вот так работает flexbox .

*{
margin: 0;
padding: 0;
}

Body {
background-color: #fff;
font-family: "Open Sans", sans serif;
line-height: 1.5;
}

Header {
border: 2px solid #ccc;
display: flex;
flex-wrap: wrap; /*перенос строки */
justify-content: space-between; /*прижимает содержимое к краям */
align-items: center; /*выравнивает элементы по центру на вертикальной */
}

Header .logo {
padding-left: 30px;
}

Header .menu ul {
display: flex;
list-style: none;
}

Header .menu ul li {
margin: 20px 10px;
}

Header .menu ul a {
text-transform: uppercase;
text-decoration: none;
font-weight: bold;
color: #06a327;
}

Phone {
font-size: 110%;
color: #333;
padding-right: 40px;
}

Работаем над адаптивностью шапки

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

Например, на ширине экрана 900 пикселей, блок с телефон прижался к левому краю шапки.

В этой публикации я хочу показать один из способов реализации адаптивного горизонтального меню с использованием 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; }

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