Как передовым разработчикам, пришло время отказаться от использования CSS-плавающих элементов и погрузиться в новый и увлекательный мир flexbox. CSS float — это устаревший подход к стилю макетов; они были доступны в Internet Explorer начиная с версии 4.0, и для их исправления требуются обходные пути (в том числе взлом с clearfix и использование псевдокласса nth-child для переноса столбцов).
Основная тема этой статьи — как реализовать flexbox в нескольких браузерах с учетом его фрагментации. Если вы хотите лучше познакомиться с flexbox, есть много хороших ресурсов, и я настоятельно рекомендую следующее:
- Готовы ли мы использовать Flexbox? Ник Саллум на SitePoint
- Полное руководство по Flexbox Криса Койера по CSS-хитрости
- Гибкая компоновка («Flexbox») в Internet Explorer 10 на MSDN (необязательно)
К концу этой статьи вы сможете:
- Узнайте, какие версии flexbox предназначены для адаптивного веб-сайта.
- Используйте flexbox с помощью функции обнаружения (обрезка горчицы) и обеспечьте запасной вариант для устаревших браузеров.
- Откажитесь от использования условных комментариев IE в большинстве ситуаций.
- Продемонстрируйте практическое использование flexbox, создав базовую сетку 2 × 2 с устаревшим запасным вариантом.
Краткая история Flexbox
Гибкий модуль макета коробки (он же flexbox) — это новый способ структурирования макетов в CSS. Он подвергся множественным пересмотрам и значительно изменился за относительно короткое время. На момент написания FlexBox все еще был рабочим проектом W3C, но, как и другие стандарты, он не должен делать его непривлекательным в производственной среде.
Существует три итерации стандарта, обычно называемые старым синтаксисом , синтаксисом анимации движения и новым синтаксисом .
Ограничения flexbox хорошо документированы:
- Старый синтаксис не поддерживает
flex-wrap
. - Синтаксис анимации движения поддерживается только в IE 10 (включая мобильный).
- Новый синтаксис не полностью реализован в Firefox (22-27), так как в нем отсутствуют свойства
flex-wrap
иflex-flow
.
Обтекание ( flex-wrap
) является важной особенностью спецификации, которая требуется для создания адаптивной сетки. По этой причине лучше всего ориентироваться только на синтаксис tweener и версии браузера, которые полностью реализуют новый синтаксис.
Это оставляет нам следующие версии браузера:
- Internet Explorer 10 (синтаксис
-ms-
префиксом-ms-
) - Internet Explorer 11 и Edge (новый синтаксис)
- Firefox 28+ (новый синтаксис)
- Chrome 21-28 (новый синтаксис с префиксом
-webkit-
) - Chrome 29+ (новый синтаксис)
- Safari 6.1+ (новый синтаксис с префиксом
-webkit-
) - iOS Safari 7.0+ (новый синтаксис с префиксом
-webkit-
)
Поскольку существуют браузеры со значительной долей рынка, которые не поддерживают flexbox, они должны отступить от использования плавающих элементов CSS. Но как это можно выразить в коде? Какой лучший способ отличить версии браузера, которые должны получать CSS с плавающей точкой вместо flexbox? Какую стратегию можно использовать для обеспечения того, чтобы версии Firefox, которые поддерживают новый синтаксис, но не поддерживают перенос, были определены как устаревшие?
Представляем: режем горчицу .
Резка горчицы (функция обнаружения)
Если вы раньше не слышали его в качестве технического термина, команда разработчиков BBC News изобрела «Сокращение горчицы». Термин возник из-за того, что веб-сайт BBC должен обслуживать широкую международную аудиторию, а ориентация на версии браузера и устройства, в частности, была бы громоздким решением.
Суть концепции заключается в том, чтобы определить, какой браузер / устройство / пользовательский агент используется, и предоставить полифиллы для работы сайта. Наличие специфических функций обнаруживается на стороне клиента, и поэтому предоставляется наиболее подходящее решение для доступной технологии.
Функция обнаружения не нова. Вышеупомянутая статья BBC была опубликована в марте 2012 года, и, хотя ее популярность возросла, удивительно, что веб-сайты по-прежнему реализуют условные классы, специфичные для IE, как популяризировал Пол Ирриш в 2008 году.
Modernizr (предоставленный Полом Айришем) полностью посвящен обнаружению особенностей:
Использовать новые классные веб-технологии — это весело, пока вам не придется поддерживать отстающие браузеры. Modernizr облегчает вам написание условного JavaScript и CSS для каждой ситуации, независимо от того, поддерживает браузер функцию или нет. Он идеально подходит для быстрого прогрессивного улучшения.
Хотя у CSS теперь есть встроенная функция обнаружения , в настоящее время ему не хватает доли рынка, чтобы быть жизнеспособным для реального использования. В оставшейся части этой статьи будет обсуждаться, как отказаться от условных комментариев IE в пользу обнаружения функций в JavaScript.
Определение функций и браузеров
Каждый проект требует различного набора функций, чтобы функционировать. Существует несколько способов обнаружения функций, самый простой из которых:
- Используя простой JavaScript (как используется BBC)
- Используя Modernizr (который будет использоваться в этой статье)
Наиболее эффективным подходом является реализация ванильного JavaScript. Это быстро (так как не требует от клиента загрузки каких-либо дополнительных библиотек) и не требует дополнительной обработки. Этот подход далек от совершенства, поскольку существуют известные проблемы; Однако существуют способы преодоления общих проблем обнаружения признаков .
[B] Обнаружение гребцов стало невозможной путаницей и в значительной степени перестало использоваться, чтобы быть замененным чем-то гораздо лучшим — обнаружением функций.
[…] Обнаружение функции также не совсем надежно — бывают случаи, когда происходит сбой.
Выбор Modernizr для нарезки горчицы может быть не таким эффективным (поскольку требует загрузки и обработки клиентом), но обнаружение поддержки flex-wrap
вручную не является простой задачей. Также важно отметить, что хотя Modernizr версии 2 не обнаруживает flex-wrap
, версия 3 обнаруживает! Эта функция помечена как Flex Line Wrapping .
Хотя существует возможность использовать CSS-классы, прикрепленные к корню документа, созданного Modernizr (например, html.flexwrap
), лучше обслуживать отдельные CSS-файлы для каждого опыта, чтобы уменьшить размер загрузки сайта.
Разработчики BBC News ссылаются на два типа браузеров:
Кто-то из команды начал называть их «браузерами HTML4» и «браузерами HTML5», которые, как мы считаем, легче донести до людей, не являющихся техническими специалистами.
Это обоснование было совершенно справедливо, если учесть климат браузера в 2012 году; однако, поскольку новые функции становятся доступными, разделение не обязательно так ясно. Например, Flexbox не полностью поддерживается во всех браузерах «HTML5».
Надежный подход заключается в разграничении между «устаревшими» и «современными» версиями браузеров. Кроме того, в некоторых проектах может потребоваться несколько подразделений, в которых можно идентифицировать промежуточные (или «переходные») браузеры.
Реализация подхода
Начните с создания следующих файлов:
-
index.html
— основной файл HTML -
stylesheets/modern.css
— стили для современных браузеров (медиа-запросы, flexbox с переносом) -
stylesheets/legacy.css
— стили для устаревших браузеров (без медиазапросов, без flexbox) -
scripts/dependencies.js
— выполняет обнаружение функции
Вот как будет выглядеть наш файл index.html:
<!DOCTYPE html> <html class="no-js"> <head> <title>Cutting the mustard</title> <script src="javascripts/dependencies.js"></script> <noscript> <link rel="stylesheet" href="stylesheets/legacy.css"> </noscript> <!-- ... --> </head> <body> <div class="container"> <div class="cell cell-1">Cell 1</div> <div class="cell cell-2">Cell 2</div> <div class="cell cell-3">Cell 3</div> <div class="cell cell-4">Cell 4</div> </div> </body> </html>
Заметили, что в IE нет условных комментариев? Просто чистый и правильный код HTML. И если в браузере не включен JavaScript, он будет использовать legacy.css
независимо от уровня его поддержки.
Вы также можете заметить, что теги скрипта находятся вверху HTML-страницы. Это связано с тем, что Modernizr должен обработать и внедрить таблицы стилей до того, как браузер впервые выполнит рисование. Это уменьшает перерисовку и помогает избежать Flash Of Unstyled Content (FOUC) . Но помните, что большинство тегов сценария будет внизу страницы.
Наш файл legacy.css будет содержать следующее:
.container { } /* clearfix */ .container:after { content: ""; display: table; clear: both; } .cell { width: 50%; float: left; } /* wrapping */ .cell:nth-child(2n+1) { clear: left; } /* for visiblity */ .cell-1 { background-color: #000; color: #fff; } .cell-2 { background-color: #666; color: #fff; } .cell-3 { background-color: #ccc; color: #000; } .cell-4 { background-color: #fff; color: #000; }
Эта реализация включает в себя хак с открытым кодом и псевдокласс :nth-child
для переноса. Это работает в большинстве браузеров; однако Internet Explorer 8 требует Selectivizr или эквивалентного решения для работы селектора.
Далее наш файл modern.css:
.container { /* Internet Explorer 10 */ display: -ms-flexbox; -ms-flex-wrap: wrap; /* Chrome 21-28 * Safari 6.1+ * Opera 15-16 * iOS 7.0+ */ display: -webkit-flex; -webkit-flex-wrap: wrap; /* Chrome 29+ * Firefox 28+ * Internet Explorer 11+ * Opera 12.1 & 17+ * Android 4.4+ */ display: flex; flex-wrap: wrap; } .cell { -webkit-flex: 1 0 50%; -ms-flex: 1 0 50%; flex: 1 0 50%; } /* for visiblity */ .cell-1 { background-color: #000; color: #fff; } .cell-2 { background-color: #666; color: #fff; } .cell-3 { background-color: #ccc; color: #000; } .cell-4 { background-color: #fff; color: #000; }
Не стоит откладывать на размер этого файла. Комментарии делают его больше, но в процессе разработки легче понять, на что нацелен каждый раздел.
Далее мы напишем код для зависимости.js.
Как уже упоминалось, нам нужно сгенерировать версию Modernizr (версия 3), которая обнаруживает поддержку свойства flex-wrap . Включите код в верхней части файла JavaScript.
/* Include Modernizr v3 with 'Flex line wrapping' here */ (function() { var isModern = Modernizr.flexwrap; var link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = 'stylesheets/' + (isModern ? 'modern' : 'legacy') + '.css'; document.getElementsByTagName('head')[0].appendChild(link); })();
При желании вы можете увеличить требования к современному интерфейсу, добавив isModern
Boolean. Например:
var isModern = Modernizr.flexwrap && 'querySelector' in document;
Sass Solutions
Вы можете использовать Sass для абстрагирования вашего подхода к реализации flexbox. Это уменьшает размер вывода CSS и упрощает поддержку:
%flexbox { display: -ms-flexbox; -ms-flex-wrap: wrap; display: -webkit-flex; -webkit-flex-wrap: wrap; display: flex; flex-wrap: wrap; } .container1 { @extend %flexbox; } .container2 { @extend %flexbox; }
Прогрессивное улучшение и тестирование браузера
Важно понимать разницу между flexbox и плавающими CSS. Ваша реализация не будет выглядеть одинаково в каждом из опытов — но понятие прогрессивного улучшения означает, что оно не обязательно должно.
Например, по умолчанию flexbox растягивает все ячейки в одной строке, чтобы иметь одинаковую высоту. Следовательно, если одна ячейка имеет длину 3 строки, а соседняя строка имеет длину 10 строк, фон будет растягиваться в обеих ячейках до 10 строк. Откат для поплавков CSS не сделает этого, и обе ячейки будут иметь неравномерную высоту.
Тестирование макета в нескольких браузерах все еще является обязательным требованием, но помните, что принудительное использование значения isModern
в false в JavaScript может помочь протестировать устаревшие решения в любом браузере:
var isModern = false; // Modernizr.flexwrap;
Вывод
В этой статье я представил основы использования функции обнаружения для обслуживания двух разных таблиц стилей на одной и той же базе HTML-кода. Это чрезвычайно эффективный способ начать процесс обновления без использования CSS и уменьшить зависимость от условных комментариев IE.
Хотя особое внимание уделялось обнаружению поддержки flexbox, важно отметить, что по мере разработки новых функций для браузеров этот подход к срезанию горчицы можно адаптировать и развивать в соответствии с будущими требованиями.
Как только Internet Explorer 10 потеряет свою популярность на рынке браузеров в целевом секторе, вы сможете отказаться от синтаксиса tweener и предоставлять более компактный код исключительно за счет использования нового синтаксиса.
Итак, теперь, когда у вас есть вся теория, почему бы не познакомиться с flexbox в вашем следующем проекте?