Статьи

Миграция на Flexbox путем разрезания горчицы

Как передовым разработчикам, пришло время отказаться от использования CSS-плавающих элементов и погрузиться в новый и увлекательный мир flexbox. CSS float — это устаревший подход к стилю макетов; они были доступны в Internet Explorer начиная с версии 4.0, и для их исправления требуются обходные пути (в том числе взлом с clearfix и использование псевдокласса nth-child для переноса столбцов).

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

К концу этой статьи вы сможете:

  • Узнайте, какие версии 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», которые, как мы считаем, легче донести до людей, не являющихся техническими специалистами.

Адаптивные новости BBC

Это обоснование было совершенно справедливо, если учесть климат браузера в 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 в вашем следующем проекте?