От автора: дни костылей на свойствах float и margin канули в небытие, и в CSS появились новые замечательные свойства, отлично подходящие на эту роль. Такие трюки, как вертикальное выравнивание внутри блока, равномерное распределение места, контроль за сортировкой элементов и прилипающий футер, почти невозможны без flexbox.
В этой статье мы рассмотрим некоторые flexbox примеры, обсудим шаблоны, отлично работающие с flexbox, воспользуемся интерфейсом приложения Tracks, которое вобрало в себя все преимущества атомарного дизайна. Я расскажу про полезные свойства flexbox, а также заострю внимание на подводных камнях, встречающихся в некоторых конкретных шаблонах. Рассмотрим именно те шаблоны, которые могут вызвать вопросы, не забудем о старых браузерах. В общем, сделаем все, что бы после статьи вы сразу могли начать пользоваться данными CSS свойствами.
Гибкие атомарные компоненты
Основная идея интерфейса сайта Tracks заключается в изолированности каждой части дизайна. Эта идея была изложена Brad Frost.
Вся философия атомарного дизайна заключается в том, что каждый элемент, как отдельная часть лего, и когда они собираются вместе, образуется неповторимый интерфейс. В атомарном дизайне используются физические термины организма, молекулы и атома для более глубокого понимания роли каждого элемента. Такой способ разграничения на категории защищает данный шаблон проектирования от нападок со стороны grid шаблона. Так как проектирование начинается с самых малых составляющих, это позволяет легко внедрять эти составляющие по всему дизайну.
Рисунок 1. Карточки отображаются по принципу атомарного веб-дизайна. Можете угадать, какие из них сделаны на flexbox?
Если хотите углубиться в теорию атомарного дизайна, прочитайте статью Brad’s post. Также стоит прочитать его книгу.
Рисунок 2. Изначальный интерфейс Tracks, вобравший все преимущества как flexbox, так и атомарного дизайна.
Интерфейс представляет из себя набор компонентов InVision. Во время первой проверки интерфейса я начал искать подходящие места для flexbox. Я решил применять flexbox на страницах с известными шаблонами типа «сайдбар слева, основной контент справа», которые зачастую выполнены на устаревшем свойстве float.
Одним из положительных моментов в редизайне Tracks был тот, что сайт должен был хорошо работать в Internet Explorer (IE) 10+, Android 4.1+ и iOS 7+. Это была просто замечательная новость, так как все они отлично поддерживают flexbox с соответствующими префиксами. Даже несмотря на стабильную поддержку в наши дни, скажем, для Android 4.1 требуется на всякий случай сделать фолбэк. А как будет выглядеть тот же фолбэк, если свойство вообще не поддерживается браузером? С помощью Modernizr и класса .no-flexbox разработчики могут определить эти самые браузеры и найти стабильные шаблоны (в противном случае можно воспользоваться CSS запросами @supports). К примеру:
1 2 3 4 5 |
<ul class="flexbox-target"> <li>...</li> <li>...</li> <li>...</li> </ul> |
1 2 3 4 5 6 7 8 9 10 |
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 */ } |
Там, где не совсем ясно, поддерживается ли flexbox, мы будем использовать на всякий случай display: inline-block. Также, чтобы элемент не использовался в JS, добавим к нему класс no-js. Наследование в CSS не нарушится в случае, если flexbox не поддерживается или не загрузился JS. Flexbox прекрасно сосуществует с такими свойствами, как float и display: table, относительным позиционированием. Браузер всегда будет позиционировать flexbox выше остальных свойств, если он поддерживается. А если не поддерживается, будут применены обычные свойства.
Как и везде, наш выбор зависит от аудитории браузеров, аналитики и бюджета. У меня есть золотое правило – всегда делать выбор в пользу самого важного условия.
Инлайновые шаблоны
Компоненты меню оказались крайне полезны в flexbox, не только из-за легкости создания, но и из-за ускорения процесса разработки. Благодаря flexbox инлайновые шаблоны, которые раньше отнимали у разработчиков массу времени, теперь занимают всего лишь минуты. Если вы имели честь применять данный шаблон в версиях IE до 9, вы знаете про это чувство разочарования.
Рисунок 3. Панель администратора использует инлайновый шаблон, кнопки меню вертикально центрированы.
Разметка этой панели выглядит так: элемент nav, внутри которого расположена серия ссылок. Пример в HTML:
1 2 3 4 5 6 7 8 |
<header role="banner"> <nav role="navigation"> <a href="pipeline.html">Back to pipeline</a> <a href="account.html">Account</a> <a href="users.html">Users</a> <a href="export.html">Export</a> </nav> </header> |
И соответствующие стили:
1 2 3 4 5 6 7 8 9 10 11 12 |
nav[role="navigation"] { display: flex; align-items: center; /* вертикальное центрирование */ } nav[role="navigation"] a { display: inline-block; /* во избежание проблем с линейным отображением в IE 10 */ } nav[role="navigation"] a[href="pipeline.html"] { flex: 1; } |
Это самый минимум, как разметки, так и стилей. Обратите внимание на значение inline-block, заданное ссылкам. Это значение решает проблему с сортировкой элементов с помощью свойства order в IE10. Также были выявлены проблемы с дочерними элементами контейнера flexbox, если задать им любой padding или margin. Лучше всего постоянно проверять работу свойств во всех браузерах и платформах.
Рисунок 4. В сети часто можно встретить такой шаблон. Шаблон меню хедера с центрированным логотипом с помощью flexbox.
Инлайновый шаблон выше обычно реализуется с помощью несемантической разметки. С появлением flexbox подход немного изменился. Шаблон состоит из ссылок меню по левому краю, центрированного логотипа и дополнительных элементов по правому краю. Разметка выглядит так:
1 2 3 4 5 6 7 8 9 |
<header class="pipeline-header" role="banner"> <a href="pipeline.html" class="pipeline-logo">...</a> <nav class="pipeline-nav" role="navigation">...</nav> <form class="pipeline-search" role="form">...</form> <a href="#menu">...</a> </header> |
Flexbox снижает потребность в создании HTML костылей и создает семантику. Семантика в коде крайне важна. Семантический код с большей степенью вероятности можно будет использовать повторно.
Для выстраивания элементов в ряд до появления flexbox раньше разработчики использовали display: inline-block и даже float: left. Теперь flexbox самый лучший вариант, разработчикам больше не нужно использовать костыли, чтобы создать красивый интерфейс. Стили для этого шаблона немного длиннее, чем для шаблона меню на рисунке 3. Но эти стили легче писать, чем те, о которых мы говорили раньше.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
.pipeline-header { display: flex; align-items: center; justify-content: space-between; } .pipeline-header > a { display: inline-block; /* IE 10 не знает свойства order, с помощью этого свойства мы избежим лишних проблем. */ } .pipeline-logo { flex: 1; order: 2; text-align: center; } .pipeline-nav { flex: 1.25; order: 1; } .pipeline-search { flex: 1; order: 3; } a[href="#menu"] { order: 4; } |
В шаблоне на рисунке 4 можно с легкостью изменять последовательность элементов. Если потребуется сместить логотип, просто воспользуйтесь свойством order. Помните, что последовательность элементов в коде очень важна для поисковиков; особенно в случае с разными браузерами. Все браузеры и скрин ридеры используют код для определения последовательности элементов, а не визуальный порядок в CSS. Это нужно при использовании стрелок на клавиатуре.
Рисунок 5. Правильное расположение элементов в разметке (слева) и измененное с помощью flexbox визуальное расположение объектов (справа).
Ниже код для рисунка 5. Разметка никогда не изменяет порядок отображения элементов.
1 2 3 4 5 |
<div class="container"> <header role="banner"></header> <main role="main"></main> <footer role="contentinfo"></footer> </div> |
А это стили, с помощью которых получается правая часть изображения 5.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.container { display: flex; flex-direction: columns; /* по умолчанию row */ } header { order: 2; } main { order: 3; } footer { order: 1; } |
Этот шаблон используется не только для меню, но и для футера.
Рисунок 6. Точно такой же шаблон, только теперь он применен для футера.
Определитесь, как контент должен располагаться внутри контейнера и сколько места он будет занимать. Расположить основной контент в центре или сдвинуть его вниз? Как это повлияет на остальные элементы дизайна? Составляйте такие вопросы для каждого проекта, прежде чем начать. Для конечных пользователей также крайне важна правильная навигация с помощью кнопок на клавиатуре.
Инлайновые input’ы
Формы могут быть сущим адом, особенно если они были заточены под шаблон сетки в форошопе. «Инлайновые лейблы» укоренились в веб-дизайне так же, как и легендарная гитара Fender Stratocaster в рок музыке.
Рисунок 7. Еще один прекрасный способ применить flexbox – инлайновые лейблы и инпуты. Но внимательно следите за длиной текста в лейбле, чтобы он не сдвигал инпут на новую строку.
Как я сказал в предыдущей главе, вам необходимо решить, где будет располагаться основной контент, как он будет занимать отведенное для него пространство при изменении размера окна браузера или появлении динамического контента.
Рисунок 8. Необходимо решить, как будет расположен контент. Слева таблица с вертикальным выравниванием посередине. Справа flexbox с выравниванием элементов по центру.
Этот скриншот явно указывает на недостатки flexbox при работе с динамическим или очень длинном контентом. Эффект на правом изображении я называю «центральный сдвиг», контент движется от центра к краям вдоль осей X и Y. Разметка рисунка 8.
1 2 3 4 |
<div class="form-group"> <label>...</label> <select>...</select> </div> |
Чтобы контролировать длинный текст в это случае лучше воспользоваться свойством display: table. В таком случае контент будет просто идти вниз, а не из центра к краям.
1 2 3 4 5 6 7 8 9 10 11 12 |
.form-group { display: flex; } .form-group label { display: table; vertical-align: middle; } .form-group input { flex: 1; } |
Совместное использование display table и flexbox это отличная методика. Я рекомендую вам ее изучить. При использовании обоих свойств постоянно смотрите на появление багов.
Рисунок 9. Инлайновые инпут и кнопка. Одинаковая высота балансирует дизайн.
Я повидал множество похожих шаблонов поля поиска. Данный шаблон настолько универсален, что его можно применить на совершенно любом макете. Конечно, существуют отдельные CSS свойства, связанные с контекстом, но они хранятся отдельно. HTML разметка типична: DIV оболочка с элементами, создающие структуру flexbox:
1 2 3 4 |
<div class="form-group"> <input type="text" placeholder="Add a note..."> <button>Add</button> </div> |
1 2 3 4 5 6 7 |
.form-group { display: flex; } .form-group input { flex: 1; } |
Выпадающее меню
Рисунок 10. С помощью парочки flexbox способов область выпадающего меню слегка подсвечена.
Меню содержит колонку слева, содержащую линейные элементы с вертикальным позиционированием по центру, и список элементов справа, где каждый элемент находится на своей строке.
Рисунок 11. Для первичного меню при создании меню использовался исключительно flexbox.
Разметка меню:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<nav class="menu"> <div class="menu__options"> <a href="export-data.html">Export</a> <a href="help.html">Get Help</a> </div> <div class="menu__items"> <a href="account.html">Account</a> <a href="preferences.html">Preferences</a> <a href="users.html">Users</a> <a href="payment.html">Payments</a> <a href="logout.html">Logout</a> </div> </nav> |
CSS стилей очень мало и их легко читать. Все как любят разработчики.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.menu { display: flex; } .menu__options { display: flex; align-items: center; } .menu__items { display: flex; flex-direction: column; } |
Пара строк кода и получается идеальная верстка. Кроме всего прочего, данное меню автономно, а стили и разметка полностью семантичны. Вот и еще один пример преимущества flexbox перед замысловатым позиционированием и костылями в разметке.
Рисунок 12. Шаблон с медиа объектом. SVG фиксированной ширины расположен слева, а справа примыкает контент.
В этом универсальном шаблоне, известном как «медиа объект», такие элементы как изображения или видео располагаются по одну сторону, а контент прилегает к ним по другую.
1 2 3 4 |
<div class="media-obj"> <div class="media-obj__fig">...</div> <div class="media-obj__body">...</div> </div> |
1 2 3 4 5 6 7 8 |
.medi-obj { display: flex; align-items: flex-start; } .media-obj__body { flex: 1; } |
Я рекомендую прочитать всем статью Solved by Flexbox Philip Walton на его сайте. Филипп дает полезные советы применения конкретных шаблонов вместе с flexbox, а также он постоянно обновляет все шаблоны в своем репозитории.
С этим шаблоном flexbox работает идеально, однако следите за тем, как прилегающий контент будет вести себя при изменении размера окна браузера. На видео выше видно, как уменьшается расстояние между изображением и тексом, и текст, в конце концов, накладывается поверх изображения. Быть может это глуповатый пример. Кто из здравомыслящих людей будет так сильно сжимать окно браузера? Но перед использованием flexbox очень важно понять, как контент взаимодействует с окружением. Решением будет установить для изображения max-width: 100%.
Календарь.
Было бы очень глупо не вспомнить про календарь. Вы можете задаться вопросом «А почему не воспользоваться таблицей?». Календарь построен по методике date-picker, и я решил разграничить кнопки дней, месяцев и года (каждый недельный ряд находится в отдельном DIV). Такой подход облегчит разметку. Большое спасибо Shane Hudson за объяснение методики. Разметка календаря на самом деле крайне проста.
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="datepicker"> <header class="datepicker__header flex-container"> <button>Left Arrow</button> <span>2015</span> <button>Right Arrow</button> </header> <div class="datepicker__view flex-container"> <button>Jan</button> <button>Feb</button> </div> </div> |
Код CSS очень короткий, короче просто быть не может. И тем не менее он понятен.
1 2 3 4 5 6 7 8 9 10 11 12 |
.flex-container { display: flex; } .datepicker__header { justify-content: space-between; } .datepicker__view { align-items: center; justify-content: flex-start; } |
Рисунок 14.Слева используется justify-content: space-between. Справа justify-content: flex-start.
Эти два примера наглядно показывают, почему лучше все планировать заранее. Как контент будет вести себя в блоке-обертке? Как контент будет вести себя при изменении окна браузера? А нужно ли вообще создавать контейнер? Все эти вопросы очень важны на начальном этапе разработки.
Макет
Flexbox не только отлично подходит для элементов интерфейса, но и для определенных шаблонов. Типичная картина это первый контейнер в одну сторону, а дополнительный в другую.
Рисунок 15. Сайдбар слева и основной контент справа – идеальный сценарий для flexbox. Это напомнило мне о технике имитации колонок.
Код также очень маленький, как и код для старых браузеров. Разметка панели администратора построена на нескольких DIV’ах.
1 2 3 4 5 6 7 8 |
<div class="admin-ui"> <div class="admin-ui__nav">...</div> <div class="admin-ui__body"> <nav>...</nav> <main>...</main> </div> </div> |
1 2 3 4 5 6 7 8 9 10 11 |
.admin-ui__body { display: flex; } .admin-ui__body nav { flex: 30%; } .admin-ui__body main { flex: 70%; } |
Такой подход отлично подходит для случая со старыми браузерами, как на рисунке 14. Шаблон крайне прост. В любой момент можно добавить display: table.
В этом примере CSS 2 свойство display: table-cell это отличный фолбэк под старые браузеры. Элементы ведут себя, как ячейки таблицы. А нам именно такое поведение и нужно, ведь оно полностью имитирует работу flexbox. С помощью display: table-header-group и display: table-footer-group даже можно изменить порядок отображения элементов.
Sticky футер
Sticky футер одна из основных проблемы для начинающих разработчиков. Основная задача приклеить футер к низу страницы. При добавлении контента, футер просто сдвигается чуть ниже, но все равно остается в самом низу страницы.
Рисунок 16. Стики футер в правом сайдбаре.
1 2 3 4 5 6 7 8 9 |
<div class="admin-edit"> <button class="admin-edit__save">Save Deal</button> <div class="admin-edit__footer"> <p>...</p> <button>Copy</button> <button>Delete</button> </div> </div> |
1 2 3 4 5 |
.admin-edit { display: flex; flex-direction: column; justify-content: space-between; } |
Футер отлично работает во всех браузерах вплоть до IE6.
Демо. Flexbox прилипающий футер с фолбэком display table. Работает вплоть до IE6!
Другой частью макета, где я рискнул применить flexbox, оказался основной вид сайта, или как мы его назвали «пайплайн». Каждая карточка имеет определенную ширину. Такой подход позволяет воспользоваться всеми преимуществами flexbox.
Пайплайн.
С помощью flexbox мне удалось красиво расположить весь контент внутри карточек. Весь сайт, как фильм «Начало» — Flexbox содержит внутри себя flexbox и т.д. Все это поражает воображение, особенно если учесть, что раньше разработчики писали тонны кода для простого центрирования элемента. А сейчас это можно сделать всего парой строк.
Будьте осторожны
Во время тестов мы обнаружили, что свойство flex в тандеме с padding или margin полностью ломает макет в IE10.
1 2 3 4 5 6 7 |
.parent { display: flex; } .parent .child { flex: 1; padding: 20px; /* Ломает макет в IE 10 */ } |
У родителя стоит свойство display: flex. А дочерние элементы со свойствами flex и padding ломают макет. Запрос типа @supports (display: flex) {} должен работать наподобие Modernizr, только тут чистый CSS. Но к сожалению, поддержка данного запроса не велика на сегодняшний день. Вместо него можно использовать:
Используйте класс no-flexbox библиотеки Modernizr
Для центрирования используйте трансформации или display table
Используйте table display
Порядок элементов можно настроить с помощью table-caption, table-header-group и table-footer-group
Для фолбэка основной структуры макета используйте свойство float
Для фолбэка инлайновых шаблонов используйте свойство display: inline или inline-block
Используйте условные комментарии для IE9 и ниже
У Ian Devlin есть отличная статья Объяснение техники стека. В ней он объясняет, как контролировать порядок элементов с помощью table-caption, table-header-group и table-footer-group.
Заключение
Flexbox’ом на сегодня очень даже можно пользоваться. После стольких лет разработки, спецификация, наконец, стала более менее стабильной, позволяя достичь высот, которые раньше были только в мечтах. Также советую посмотреть статью Wes Bos Что такое Flexbox?. Простой ускоренный курс из 20 видеороликов поможет вам овладеть flexbox бесплатно! Первые 13 видео рассказывают об основах; 7 оставшихся роликов это сплошной кодинг. Wes создает все, от меню до полных мобильных версий сайтов. И все на чистом flexbox! После этого курса вы просто не сможете не использовать flexbox в своих проектах.
Автор: Dennis Gaebel Jr
Источник: //www.smashingmagazine.com/
Редакция: Команда webformyself.