CSS-live.ru

Простая сетка на гридах с фолбэками с помощью @supports

Перевод статьи Basic grid layout with fallbacks using feature queries с сайта chenhuijing.com для CSS-live.ru, автор — Чэнь Хуэй Цзин

Верстка простой сетки с фолбэками, использующими директиву @supports (feature queries)

Я уже довольно долго использую CSS-гриды (будем называть их просто гридами). И, хотя я много говорю об их применении для создания всевозможных креативных макетов, мне хорошо известна востребованность простой сетки.

Беседуя с другими разработчиками на тему использования гридов, я часто слышу осторожные высказывания «Но…», наподобие такого: «Но как насчет старых браузеров? Я должен поддерживать *ВСТАВЬТЕ_СЮДА_ЛЮБОЙ_СТАРЫЙ_БРАУЗЕР*». Это опасение вполне понятно! Поскольку, как я вижу, пока далеко не все осведомлены о магии директивы @supports.

Я привожу содержание для быстрого перехода к самому интересному вам месту этой огромной статьи. Исходный код примера доступен на GitHub.

Содержание (скучные разделы пропускаем :)

Изящные фолбэки

Правило @supports (или feature queries) представляет собой условное правило для группы стилей. Его условие проверяет, поддерживает ли пользовательская программа пары CSS «свойство: значение». Проще говоря, это оператор if, который смотрит, поддерживает ли браузер определенное CSS-свойство.

Так сейчас выглядит поддержка браузерами директивы @support:

Знаю, что ваши глаза залипли на красной колонке с Internet Explorer. Но не стоит разочаровываться в директиве @support, продолжайте читать! Она работает так: если браузер ее не поддерживает, то все стили внутри блока кода @support игнорируются.

Исследуем простейший пример:

main {
  background-color: red;
}

@supports (display:grid) {
  main {
    background-color: green;
  }
}

В браузерах с поддержкой гридов цвет фона элемента main будет зеленым (поскольку условие выполняется), в то время как в браузерах без их поддержки фон будет красным.

Из такого поведения вытекает, что можно добавлять продвинутые стили отдельным «слоем», в зависимости от нужных свойств, и их применят только браузеры с поддержкой этих свойств. А браузеры без их поддержки получат оформление попроще, которое будет работать в любом случае. Вот такой подход мы будем использовать далее.

Сайты НЕ должны выглядеть одинаково во всех браузерах.

Основные принципы CSS: спецификации

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

Степень разделения между «холстом» и нашим кодом очень высока. Поэтому необходимо знать, как именно работает браузер для визуализации кода на экране, и четко представлять, как он интерпретирует код.

Немногим более года назад я задалась вопросом «Насколько хорошо мы знаем CSS-свойство display?» Тогда я впервые села и внимательно прочитала спецификацию «CSS-модуль Display 3-го уровня» (CSS Display Module Level 3). (На нашем сайте тоже была статья об этом модуле, когда он только появился — прим. переводчика.) Раскладка макета — огромная тема и затрагивает множество спецификаций, включая «CSS-модуль выравнивания 3-го уровня», «CSS-модуль внешних и внутренних размеров 3-го уровня» и так далее. Вы представляете себе картину.

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

Что это за display, о котором вы говорите?

В случае, если вы не разделяете мой интерес к чтению спецификаций, давайте бегло пройдемся по наиболее значимым пунктам спецификации CSS-свойства display.

  1. Браузеры отображают боксы.
  2. CSS генерирует дерево боксов.
  3. Каждый бокс представляет соответствующий ему элемент на холсте.
  4. Для каждого элемента CSS генерирует от нуля и более боксов на основании CSS-свойства display элемента.

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

Внутренний тип отображения определяет раскладку для дочерних боксов.

Внешний тип отображения определяет то, как сам бокс ведет себя в макете.

Есть еще дополнительные значения вроде <display-listitem></display-listitem>, <display-internal></display-internal>, <display-box></display-box> и <display-legacy></display-legacy>.

Контекст форматирования — это среда, в которой происходит раскладка набора связанных между собой боксов. Различные контексты форматирования расположат боксы по-разному, в зависимости от различных наборов правил.

Начало было положено в 1998 году в рабочем черновике CSS2, где были описаны блочный и строчный контексты форматирования. Но со временем добавились другие варианты раскладки. Теперь мы имеем еще табличный (table), флекс- (flex-), грид- (grid-) и ruby- контексты форматирования.

Элементы блочного уровня (block-level) генерируют основной бокс блочного уровня, который участвует в блочном контексте форматирования.

Элементы строчного уровня (inline-level) не образуют новые блоки с контентом, и их контент располагается в строку. Они генерируют боксы строчного уровня, которые участвуют в строчном контексте форматирования.

Однако, строчно-блочный элемент (inline-block) — не строчный бокс. Он — что-то промежуточное, потому что участвует в строчном контексте форматирования как отдельный монолитный бокс.

Достаточно пока о спецификации, я хочу рассказать и о других вещах. Постараюсь давать информацию небольшими кусочками для лучшего восприятия.

Простая, по-настоящему простая сетка

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

(в твите автор спрашивает: «Вы знаете, что происходит, когда CSS-свойства, относящиеся к раскладке, переопределяют предыдущие свойства?» — прим. переводчика)

В примере я использую раскладку с 25 карточками. У каждой из них есть изображение, заголовок и подзаголовок (длина которых непредсказуема, когда мы ставим реальный контент). Разметка, которая будет использоваться для демонстрации всех реализаций раскладок в статье, выглядит так:

<main class="grid"><div class="grid__item">
      <img class="card__img" src="images/image1.jpg" /><h2>Card title</h2>
<p>Because the card pattern is soooo popular right now...</p></div>
<div class="grid__item">
      <img class="card__img" src="images/image2.jpg" /><h2>Card title</h2>
<p>Because the card pattern is soooo popular right now, but not all text are made the same</p></div>
    <!-- Повторите карточку .grid__item еще 25 раз -->
</main>

Итак, давайте начнем с простейшей раскладки, созданную посредством inline-block.

Раскладка на inline-block

Я знаю толк в наказаниях, поэтому сделала эту раскладку рабочей в IE8 (но не в более ранних версиях IE, потому что я всё-таки не мазохист). Этот вариант предполагает, что у каждой карточки фиксированный размер (20em), и вся раскладка центрирована по горизонтали.

Макет довольно отзывчивый (начиная с IE8, но не ниже)

Код для нее элементарный: контейнер раскладки имеет свойство display: inline-block, и центрирование происходит за счет свойства text-align: center у его родителя (в нашем случае, у элемента body).

body {
  text-align: center;
}

.grid {
  display: inline-block;
}

.grid__item {
  width: 20em;
  display: inline-block;
  vertical-align: top;
  margin: 1em 0.5em;
  text-align: left;
}

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

Кому-то вот это может не понравиться

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

Давайте рассмотрим следующий метод из категории простых.

Раскладка на float

О, старый добрый float. Такой надежный. Этот метод был преобладающим довольно долго. Я уверена, что многие сайты до сих пор используют эту технику. Тем не менее, всё не так гладко с отзывчивыми сайтами, основанных на float.

Начнем с того, что CSS-свойство float изначально не было предназначено для создания раскладки страницы. Отсюда и все сложности со сбросом обтекания, особенно при решении проблем с элементами разной высоты.

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

Отзывчивая раскладка на float

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

Итак, последующий код будет оооочень длинным…

.clearfix::after {
  content: '';
  display: table;
  clear: both;
}

.grid__item {
  float: left;
  padding: 0.5em;
  width: 100%;
}

@media screen and (min-width: 480px) {
  .grid__item {
    width: 50%;
  }

  .grid__item:nth-child(2n+1) {
    clear: left;
  }
}
 
@media screen and (min-width: 768px) {
  .grid__item {
    width: 33.333%;
  }

  .grid__item:nth-child(2n+1) {
    clear: none;
  }

  .grid__item:nth-child(3n+1) {
    clear: left;
  }
}
 
@media screen and (min-width: 1024px) {
  .grid__item {
    width: 25%;  
  }

  .grid__item:nth-child(3n+1) {
    clear: none;
  }

  .grid__item:nth-child(4n+1) {
    clear: left;
  }
}

@media screen and (min-width: 1280px) {
  .grid__item {
    width: 20%;  
  }

  .grid__item:nth-child(4n+1) {
    clear: none;
  }

  .grid__item:nth-child(5n+1) {
    clear: left;
  } 
}

Я схитрила и сделала сброс, добавив класс .clearfix к контейнеру раскладки. Потому что нельзя сделать раскладку на float, не сбрасывая обтекания. Нельзя и всё. Уж извините. Но вне зависимости от того, ширина раскладки фиксированная или отзывчивая, селекторы nth-child всё же необходимы для добавления и удаления сброса.

Здесь кроется причина того, что этот конкретный код с float не работает в IE8. Только в IE9 и выше. Чтобы решить вопрос с поддержкой nth-child, нам бы потребовались дополнительные обертки вокруг нескольких карточек, в зависимости от вьюпорта. Признаюсь, из-за этого в прошлом я отказалась от нескольких заказов на верстку с отзывчивым макетом, где количество колонок менялось от 4 до 1, в зависимости от ширины окна.

Победитель среди методов для фолбэка: раскладка на inline-block

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

Сайты НЕ должны выглядеть одинаково во всех браузерах.

Флексбоксы — простые, мощные, но не всесильные

Итак, первым в директиве @support будет «слой» с флексбоксом. Идея флексбоксов обсуждалась еще до 2008 года, а первый рабочий черновик спецификации был опубликован в 2009 году. Но их внедрение прошло довольно сумбурно.

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

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

Горизонтальные строки

 

Горизонтальные строки

Вертикальные строки

 

Вертикальные строки

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

.grid {
  display: flex;
  flex-wrap: wrap;
  margin: -1em 0 1em -0.5em;
}

.grid__item {
  padding: 1em 0 0 0.5em;
  flex: 1 0 20em;
}

Так что имейте ввиду, что флексбоксы не так уж и хороши для построения правильной сетки. У них нет встроенного инструмента управления промежутками между элементами раскладки, отсюда и использование отрицательных отступов (margin) для создания этих промежутков (с недавних пор такой инструмент уже есть и описан в статье — прим. переводчика). Вообще говоря, флексы справляются довольно хорошо. До тех пор, пока мы не доберемся до последней строки раскладки. Только если не случится чудо, и количество элементов последней строки будет точно таким же, как в остальных. Иначе один или несколько элементов остается висеть в одиночестве.

Отзывчивая раскладка на flex

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

.grid__item {
  padding: 1em 0 0 0.5em;
}

@media screen and (min-width: 480px) {
  .grid__item {
    width: 50%;
  }
}
 
@media screen and (min-width: 768px) {
  .grid__item {
    width: 33.333%;
  }
}
 
@media screen and (min-width: 1024px) {
  .grid__item {
    width: 25%;  
  }
}

@media screen and (min-width: 1280px) {
  .grid__item {
    width: 20%;  
  } 
}

Другой вариант — установить максимальную ширину каждому элементу раскладки, так что оставшиеся в последней строке элементы не раздуются до абсурдных размеров. Однако по умолчанию все элементы выравниваются по левому краю. Поэтому в некоторых случаях справа может образоваться слишком много белого пространства.

Одинокие четыре элемента в последней строке

Если вас это устраивает, отлично. Но, судя по опыту, большинство захочет центрировать элементы.

Немного о выравнивании боксов

Поговорим о выравнивании боксов.

Я говорила, что не буду углубляться в сложные подробности. Поэтому я раскрою лишь небольшую часть этой важной темы. В частности, речь пойдет о распределении контента — т.е. его выравнивании внутри бокса.

Существует два свойства для распределения контента: align-content и justify-content, также как и сокращенное place-content (работу этих свойств мы подробно рассмотрели в статье — прим. переводчика). На момент написания place-content поддерживалось в Chrome 59 и выше, а также в Firefox (правда, я не уверена, с какой именно версии).

Эти свойства ведут себя немного по-разному, в зависимости от бокса, к которому применяются. Мы пока рассмотрим только поведение флекс-контейнера. Свойство justify-content влияет на флекс-элементы в каждой строке и применяется вдоль главной оси. Свойство align-content влияет на сами строки и применяется вдоль поперечной оси.

Почему здесь не используются понятия горизонтальной и вертикальной осей? Потому что эти физические направления могут быть разными, в зависимости от значения свойства flex-direction у флекс-контейнера. Так же как и направление текста (CSS-свойство writing-mode) на странице при различных конфигурациях. Диаграммы ниже — всего лишь варианты перестановок.

flex-direction: row

flex-direction: row

horizontal-tb (ltr)

horizontal-tb (ltr)

horizontal-tb (rtl)

horizontal-tb (rtl)

flex-direction: column

flex-direction: column

vertical-rl

vertical-rl

Вертикальные строки

vertical-lr

В примере будем придерживаться самого используемого сочетания: направление главной оси flex-direction: row и направление текста writing mode: horizontal-tb. В итоге мы хотим центрировать контент вдоль горизонтального уровня, то есть по главной оси. Нам потребуется свойство justify-content.

Ему доступно множество значений: те, которые распределяют контент, и те, которые его позиционируют. Для позиционирования у нас есть center, flex-start, flex-end, start и end. Для распределения — stretch, space-around, space-between и space-evenly.

Значения с приставкой flex- применяются только ко флекс-контейнерам. Но, не считая этого нюанса, все эти значения делают то, о чем говорят их названия, то есть элементы будут выровнены по началу/центру/концу контейнера. К сожалению, в IE11 есть баг у свойства justify-content: center, так что нам стоит использовать значение space-around вместо center.

Для распределения контента значение stretch ведет себя так же, как flex-start (здесь идет речь именно о флексбоксах — прим. переводчика). Разница между остальными тремя значениями состоит в размере отступа между флекс-элементами. При значении space-between края первого и последнего флекс-элементов строки прижмутся к краям флекс-контейнера:

Работа значения space-between

Значение space-around задает одинаковые отступы вокруг всех флекс-элементов:

Работа значения space-around

Значение space-evenly, которое поддерживает только Firefox на момент написания, распределяет все флекс-элементы равномерно по оси, так что отступ от первого и последнего до краёв флекс-контейнера такой же, как и отступ между флекс-элементами. (По нашим тестам, это значение работает уже с 60-го Хрома. Еще обращаем внимание, что здесь речь идет только о работе space-evenly для флексбоксов. Для гридов в Хроме оно работало с самого начала, с 57-й версии — прим. переводчика.)

Работа значения space-evenly

Сейчас я буду использовать свойство justify-content: space-around. Итоговый код для флексов:

@supports (display:flex) {
  .grid {
    display: flex;
    flex-wrap: wrap;
    margin: -1em 0 1em -0.5em;
    justify-content: space-around;
  }

  .grid__item {
    padding: 1em 0 0 0.5em;
    flex: 1 0 20em;
    max-width: 20em;
    width: auto;
    margin: initial;
  }
}

Свойства width:auto и margin: initial здесь нужны для сброса значений этих свойств у карточек в той простой фолбечной раскладке на inline-block. Поскольку директива @support не поддерживается в IE11 и ниже, весь этот кусок кода в них не сработает. Это как раз еще один проблемный момент — отсутствие поддержки значения initial для свойств в этих браузерах.

Так получилось, что браузеры с поддержкой директивы @support также поддерживают значение initial, то есть здесь нам повезло. Исключение составляет Opera Mini. Но я проверила раскладку в ней тоже, и вы знаете, не так всё плохо! Так что я просто смирюсь с лишним отступом (margin) у карточек. Или вы можете установить явное значение этого отступа для флекс-раскладки.

Опять же, вам решать, оставлять ли как есть последнюю строку с неполным количеством карточек. Если нет изображений, которые занимают всю ширину карточки, то такой вариант может подойти. А может и не подойти — всё зависит от контекста.

Сайты НЕ должны выглядеть одинаково во всех браузерах.

Встречаем гриды, новейшую революцию в верстке

Я так много хочу рассказать про гриды! Но я возьму себя в руки и раскрою только необходимые моменты для создания простой сетки, чтобы не уходить от темы статьи.

CSS-гриды — самый впечатляющий старт новинки CSS, который я видела (в марте 2017 г. сразу четыре браузера реализовали поддержку гридов, подняв ее с нуля до более чем 60% — прим. переводчика). Во многом из-за ее развития за флагом. Это означало, что разработчики могли тестировать гриды и давать обратную связь разработчикам браузеров, при этом удерживаясь от использования этого кода в продакшне, поскольку он еще не был к этому готов.

Единственной проблемой этого подхода, которую Рейчел Эндрю осветила уже довольно давно, заключается в том, что обратная связь от разработчиков приходит без достаточного энтузиазма.

(Рейчел Эндру говорит в твите: «Если вы не тестируете и не даете обратную связь на нововведения в CSS наподобие CSS-гридов, то вы доверяете свои будущие инструменты тем немногим, которые всё же тестируют и принимают участие.» — прим. переводчика)

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

Гриды принципиально отличаются от всех остальных техник раскладки, которыми мы пользовались раньше. Это единственное решение, в котором контейнер управляет содержимым, а не наоборот (идея этой концепции принадлежит Рейчел Эндрю). Они используют цельное видение сетки у вас в голове, в отличие от задания размеров каждому элементу в отдельности, что может иногда приводить к ситуации, когда мы «за деревьями не видим леса» (имеется в виду, что мы упускаем главное из-за излишнего внимания к мелочам — прим. переводчика).

Огромным преимуществом здесь является то, что элементы сетки не зависят друг от друга при размещении. Мы можем задать им позицию относительно осей X и Y независимо от того, что находится вокруг них.
— Бренда Сторер

Вот оно — правильное поведение раскладки

Другая фантастическая особенность, пока свойственная только гридам — это свойство grid-gap. Мы сообщаем браузеру, что хотим интервалы между элементами, и браузер сам их вычисляет. У нас есть эта возможность, потому что Рейчел Эндрю настояла на ней на конференции CSS Day. Автор спецификации, Элика Дж. Этемад (более известная как Fantasai) там присутствовала и добавила свойство в спецификацию. Вот подробная история.

В общем, с гридами у нас наконец-то есть полноценная техника раскладки элементов по сетке. Это как Пиноккио наконец-то стал настоящим мальчиком :) Больше не будет этих сложных вычислений для определения ширины каждого элемента. Закончилась возня с отрицательными отступами для создания интервалов между ними. Просто хорошие, понятные сетки на CSS.

@supports (display:grid) {
  .grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
    grid-gap: 0.5em;
    margin: initial;
  }

  .grid__item {
    padding: initial;
    max-width: none;
  }
}

Работа гридов основана главным образом на задании сетки при помощи CSS-свойств grid-template-columns и grid-template-rows. Эти свойства позволяют задавать размеры колонок и рядов соответственно. Мы можем поместить элементы в сетку самим явно или позволив браузеру сделать это самому.

Для обычной простой сетки браузер справится с этим гораздо лучше нас, поскольку он лучше нас в вычислениях, разве не так? Серьезно, алгоритм автоматического размещения грид-элементов работает очень здорово.

В этой базовой сетке мы используем CSS-функции repeat() и minmax(). Функция repeat() позволяет избавиться от повторения кода с одним и тем же набором колонок и строк. Она также принимает аргументы auto-fill и auto-fit, которые означают, что браузер сам определит, сколько колонок или строк должно быть у сетки, в зависимости от доступного пространства.

Функция minmax() принимает два аргумента — это диапазон размеров между минимальным <min></min> и максимальным <max></max> значениями. Она позволяет нам установить минимальную ширину элемента сетки фиксированным значением ширины width (<min></min>). У максимальной ширины элемента — значения <max></max> — может быть три варианта: фиксированное, заданное в единицах fr или зависимое от размера контента (используя min-content или max-content).

grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));

Эта строка говорит браузеру, что мы хотим столько колонок в сетке, насколько позволит нам пространство, и при этом минимальная ширина колонки должна быть 20em-ов. Если есть еще доступное пространство, то мы хотим распределить его равномерно среди всех колонок. Здесь нет дополнительных вычислений, нет множества медиавыражений.

grid-gap: 0.5em;

Вместо использования padding и margin для интервалов между элементами сетки я просто должна задать свойству grid-gap значение с размером этого интервала, какой мне хочется. grid-gap — это на самом деле сокращение свойств <‘grid-row-gap’> <‘grid-column-gap’> и принимает два аргумента.

Собираем все части вместе

Итоговый код раскладки получается вот таким, основанный на моих решениях использовать технику на inline-block для старых браузеров, технику space-around для уже поддерживающих флексбоксы (но без поддержки гридов) и технику с гридами для новых.

body {
  text-align: center;
}

.grid {
  display: inline-block;
}

.grid__item {
  width: 20em;
  display: inline-block;
  vertical-align: top;
  margin: 1em 0.5em;
  text-align: left;
}

@supports (display:flex) {
  .grid {
    display: flex;
    flex-wrap: wrap;
    margin: -1em 0 1em -0.5em;
    justify-content: space-around;
  }

  .grid__item {
    padding: 1em 0 0 0.5em;
    flex: 1 0 20em;
    max-width: 20em;
    width: auto;
    margin: initial;
  }
}

@supports (display:grid) {
  .grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
    grid-gap: 0.5em;
    margin: initial;
  }

  .grid__item {
    padding: initial;
    max-width: none;
  }
}

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

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

И, в последний раз, повторяйте за мной…

Сайты НЕ должны выглядеть одинаково во всех браузерах.

До встречи!

Полезные ссылки

(ресурсы на английском языке — прим. переводчика)

P.S. Это тоже может быть интересно:

17 комментариев

  1. На цитате «Сайты не должны выглядеть одинаково в разных браузерах» читать заканчиваем.

    1. Надо полагать, вы верстаете страницы как картинки с кликабельными <area>? :) Во всех других случаях разница будет, как минимум в отрисовке браузерами/платформами шрифта. Как бы вам ни мечталось об обратном…

      И да — разный вид сайта как минимум в десктопных и мобильных браузерах уже лет 6 как норма. А большинство браузеров без поддержки гридов, с которых на сегодня могут заходить платежеспособные клиенты — мобильные (UC Browser, Samsung Internet 5-, Opera Mini и т.п.).

      1. Ясен перец, что разница всегда есть. Не нужно прилеплять к цитате мобильные браузеры — для этого существует адаптивная верстка. Но на десктопе посетитель с разных, как минимум не устаревших браузеров, должен видеть сайт одинаково. А не устаревшими заказчики считают обычно последние версии нормальных браузеров и IE11.
        Но встречаются же и такие, кто хочет еще и IE9.

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

          Вот этого двоемыслия я не понимаю и с ним не согласен. Кому «должен» и по какому праву? Я считаю, что в любом окружении пользователь должен взаимодействовать с сайтом самым удобным образом, который это окружение позволяет, и адаптивная верстка, прогрессивное улучшение и т.п. — инструменты для этого. И пользователи современных браузеров не должны страдать «за компанию» с отстающими (а IE11, что бы ни говорили заказчики — браузер устаревший, его уже не поддерживает сам Microsoft). Но на вкус, на цвет, конечно..:)

          1. Должен заказчику =) Заказчик хочет чтобы Вася Пупкин открыл Edge, IE11, Safari, Chrome и везде у него был одинаковый опыт взаимодействия с сайтом. И его мало волнует окружение, прогрессивное улучшение и прочее.
            Кстати, насколько я понимаю термин прогрессивное улучшение — это изменение отображение сайта без вреда для функционала и пользовательского опыта.

            1. Профессионал должен уметь объяснить заказчику, что Вася Пупкин не будет открывать сайт во всем перечисленном и скрупулезно сравнивать, не разошлась ли где-то картинка на пару-тройку пикселей:). Он откроет сайт в чем-то одном и будет искать заветную кнопку «Сделать заказ». Или не будет — если сайт ему не понравится, неважно чем (медленной загрузкой, глюками, общей «старомодностью» дизайна..:).

              И если Вася привык заходить на сайты с IE11, то не будет беды, если карточки у него будут выровнены по левому краю — на IE так выглядят почти все сайты, он привык к такому поведению, ему важно, чтобы страница открылась быстро и не упала раньше, чем он дотянется до заветной кнопки:). Но если Вася зашел с новейшего Хрома, он вполне заслуживает того, чтобы увидеть аккуратно выровненную по всему экрану равномерную сетку карточек — круче, чем у любого из конкурентов! — причем увидеть ее быстро (это нативная браузерная возможность, а не скрипт, поэтому неплохо оптимизировано) и быть уверенным, что она не «глюканет» и не слипнется в кашу при ресайзе, например.

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

              1. Согласен с Вами.
                Но я бы сформулировал мягче: «Сайты НЕ обязаны выглядеть одинаково во всех браузерах». То есть, именно, что не большие различия (в десктопных браузерах на одинаковых разрешениях), возможны, и, как говорят в этих Ваших интернетах, это не баг, а фича :-))

                1. ‘Websites do NOT need to look the same on every browser.’ (c) то есть, «вебсайты НЕ нуждаются в том, чтоб выглядеть одинаковым образом в каждом браузере», ну это вот почти дословно, то есть, смысл не в том, что «не должны выглядеть одинаково»(тут не далеко от того, что «должны выглядеть по-разному»), а скорее, в том, что в цели «выглядеть идентично» нет необходимости.

  2. Как заводчик того самого бага «у свойства justify-content» должен заметить, что баг имеет очень опосредованное значение к свойству.

    Баг возникает при сочетании условий роста элемента (flex grow), когда элемент имеет размер больше базового, заданного flex-basis (по умолчанию равно минимальной ширине по содержимому), и когда есть свободное пространство для распределения (так бывает когда, несмотря на рост, размер элемента ограничен свойством вроде max-width).

    Тогда свободное пространство неправильно считается в IE11 (и только в нём), в него добавляется тот самый размер, добавленный элементу (flex grow). Любой элемент с нестартовой позицией (будь то margin: auto или justify-content) смещается из-за неправильного расчёта свободного места.

  3. Сегодня как-раз столкнулся с проблемой последнего элемента на флексе. В итоге решил добавлением невидимых псевдоэлементов. У меня правда элементов может быть строго 2 или 3 в строке, поэтому такой способ более-менее подошел

  4. Спасибо за перевод, но у меня возникла путаница с flex + gap в середине статьи вы говорите, что сейчас решен вопрос с хаком в виде отрицательных отступов, путем унификации правил отступов gap / grid-*-gap для Flex-элементов, проверив это работает только в FireFox, а на MDN вообще говориться что это свойство deprecated, подскажите как сейчас обстоят дела с gap-ми во Flex& ?
    https://developer.mozilla.org/ru/docs/Web/CSS/grid-gap

    1. К сожалению, вопрос решен пока только в теории. Да, у свойств gap/row-gap/column-gap убрали префикс grid- и перенесли их в спецификацию свойств выравнивания, общую для разных схем раскладки. Но в гридах браузеры еще очень долго будут поддерживать старый синтаксис (с grid-) ради совместимости, так что пока приходится использовать именно его (охват шире). Хром вроде как поддерживает gap без grid- c 66-й версии, но пока только в гридах. Во флексбоксах, да, пока оно работает только в Firefox (с 63-й версии), браузеры (вроде как) работают над этим, но на практике пока без хаков с margin-ами не обойтись.

  5. Спасибо за статью. Но, как бы с определением IE 10-11, есть хак, поэтому флексы можно уже использовать для этих браузеров.

    @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {}

    Хотя не только флексы, они же и CSS Grid частично поддерживают, вот было бы интересно почитать статью как на с помощью фолбеков и префиксов верстать на гридах для IE и современных браузеров.

    1. Вкратце — IE поддерживает (со своим синтаксисом) практически всё, кроме автоматического размещения, *-gap и auto-fit/auto-fill. Вместо repeat у него свой синтаксис со скобками, fit-content() эмулируется более длинной записью, minmax() вполне себе работает как есть. Большую часть всего необходимого умеет автоматически генерировать новый Autoprefixer. Была хорошая серия статей про это на css-tricks: https://css-tricks.com/css-grid-in-ie-debunking-common-ie-grid-misconceptions/ (и дальше по ссылкам).

      1. Понятно одно — IE чисто под статическую сетку, но и на том отлично. Могло быть и хуже )

        P.S. Ваш сайт очень таки полезен — по гридам куча материала, где все разжевано до мелочей, спасибо.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

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