Как грид-раскладка (Grid Layout) провела лето
Перевод статьи Grid Layout Summertime с сайта blogs.igalia.com, опубликовано на css-live.ru с разрешения автора — Мануэля Рего Касановаса.
Краткое описание изменений в реализации CSS Grid Layout за прошедшее лето
Лето закончилось, и команда Igalia успела не только хорошо отдохнуть, но и продуктивно поработать над CSS Grid Layout в Chromium/Blink и Safari/WebKit в рамках нашего постоянного сотрудничества с Bloomberg.
К концу сентября спецификация перешла в статус «Кандидат в рекомендации (CR)», Рэйчел Эндрю объяснила, что это значит, в своей статье. Однако, за прошедшие месяцы кое-где произошло несколько изменений, требующих обновления реализации.
Если не забыли моё выступление на последнем BlinkOn, мы рассматривали статус реализации. К тому времени накопилось куча вещей, помеченные как WIP (сокращение от Work In Progress, т.е. «Мы работаем над этим» — прим. перев.) или TODO («надо сделать», напоминания на будущее — прим. перев.), но теперь большинство из них уже реализованы, как я поясню в статье.
Автоматическое повторение
Мой приятель Серхио Вильяр уже полностью раскрыл эту фичу в своей статье, так что я не хочу повторяться.
Изменилось лишь то, что ключевое свойство auto-fit
уже реализовано в браузерах, поэтому можете смело его использовать. аuto-fit
позволяет скрывать полосы, которые не содержат элементов.
Так что теперь можно делать так:
<div style="display: grid; width: 700px; grid-template-columns: repeat(auto-fit, 150px); grid-template-rows: 100px;"> <div style="grid-column: 1 / span 2;">grid-column: 1 / span 2</div> <div style="grid-column: 4;">grid-column: 4</div> </div>
Пример с auto-fit
В примере хватает места для четырёх колонок по 150px в ширину, но поскольку третья колонка не содержит никаких элементов, она схлопывается в 0px, и в итоге в грид-контейнере остаётся только три колонки. Если применить ключевое слово auto-fill
, то третья колонка не схлопнулась бы и оставалась бы пустой.
Множественные полосы
Одно из изменений спецификации — то, что стало можно указывать более одной полосы в некоторых свойствах: grid-auto-columns
, grid-auto-rows
и нотации repeat()
.
К примеру, теперь можно передавать список полос в свойство auto-columns
:
<div style="display: grid; grid-auto-columns: 200px 50px; grid-template-rows: 100px;"> <div style="grid-row: 1;">A</div> <div style="grid-row: 1;">B</div> <div style="grid-row: 1;">C</div> <div style="grid-row: 1;">D</div> </div>
Пример множественных полос для grid-auto-columns
Как видно, ширина первой и третьей колонки 200px, а второй — 50px.
Кроме того, можно также использовать список полос для нотации repeat()
:
<div style="display: grid; grid-template-columns: repeat(3, 200px 50px); grid-template-rows: 100px;"> <div style="grid-row: 1;">A</div> <div style="grid-row: 1;">B</div> <div style="grid-row: 1;">C</div> <div style="grid-row: 1;">D</div> <div style="grid-row: 1;">E</div> <div style="grid-row: 1;">F</div> </div>
Пример множественных полос для нотации repeat()
Но чтобы заставить это работать как следует вместе с автоматическим повторением, понадобилось чуть больше изменений, чем планировалось.
Ограничитель для fit-content()
Ключевое слово fit-content
обновилось, и теперь в него можно передавать аргумент, используемый в качестве максимального размера. В качестве аргумента для функции fit-content()
можно указывать либо длину, либо проценты (которые высчитываются, как для процентных полос).
Поэтому теперь в Grid Layout можно использовать fit-content(argument)
, а размер полосы будет ограничиваться argument:
<div style="display: inline-grid; grid-template-columns: repeat(2, fit-content(200px)); grid-template-rows: 100px;"> <div>элемент</div> <div> Очень длинный грид-элемент </div> </div>
Пример с функцией fit-content()
Можно видеть, что первая колонка использует fit-content, поэтому её размер адаптируется под находящийся в ней элемент. Однако, чтобы весь элемент уместился, второй колонке потребовалось бы больше 200px, так что её размер ограничен 200px.
Поддержка процентов для грид-интервалов
Некоторое время назад грид-интервалы уже были добавлены в разные реализации, но нам не хватало поддержки для процентных интервалов.
Мы обновили реализацию, так что теперь можно использовать и проценты (опять же, проценты для них рассчитываются так же, как и для полос):
<div style="display: grid; width: 400px; grid-column-gap: 10%; grid-auto-columns: 1fr; grid-auto-rows: 100px;"> <div style="grid-row: 1;">A</div> <div style="grid-row: 1;">B</div> <div style="grid-row: 1;">C</div> <div style="grid-row: 1;">D</div> </div>
Пример с процентными интервалами
10%-й интервал между колонками рассчитывается относительно ширины контейнера, составляя 40px. Затем полосы 1fr
занимают доступную область, которая в данном случае составляет 70px для каждой колонки.
Поддержка процентов для грид-интервалов помечена в спецификации как «находится под риском удаления», но она уже реализована в Gecko и Blink, так что вряд ли ее уберут из этого уровня спецификации.
Новый синтаксис для сокращённой записи grid
Изменился и синтаксис сокращённой записи grid
, и теперь в одном-единственном свойстве можно указывать явный грид по одной оси и режим алгоритма авторазмещения — по другой.
К примеру, если нужен грид с двумя колонками заданного размера, а ряды будут создаваться по мере необходимости, то можно использовать следующий синтаксис:
<div style="display: grid; grid: auto-flow 100px / 200px 100px;"> <div>A</div> <div>B</div> <div>C</div> <div>D</div> <div>E</div> </div>
Пример короткой записи grid
Перпендикулярные потоки
Перпендикулярными потоками называются ситуации, когда весь грид и некоторые из его элементов используют разные направления письма. Например, если у вас есть горизонтальный грид-контейнер с несколькими вертикальными элементами внутри.
Над этим пришлось долго поработать, но уже сейчас в грид-раскладке можно использовать перпендикулярные потоки. Была реализована базовая поддержка, включая выравнивание перпендикулярных элементов.
Поэтому теперь можете использовать вертикальные элементы внутри горизонтальной грид-раскладки:
<div style="display: inline-grid;"> <div style="grid-row: 1;">Test</div> <div style="grid-row: 1; writing-mode: vertical-lr;">Chrome</div> <div style="grid-row: 1; writing-mode: vertical-lr;">Firefox</div> <div style="grid-row: 1; writing-mode: vertical-lr;">Safari</div> <div>test-1.html</div><div>✖</div><div>✔</div><div>✔</div> <div>test-2.html</div><div>✔</div><div>✖</div><div>✖</div> </div>
Пример перпендикулярных потоков
Новое значение normal
для свойств выравнивания
С точки зрения спецификации и реализации это довольно сложная проблема (как видно из пояснения к этому патчу, заслуживающего отдельного места в истории), но вероятно не особо важная для конечных пользователей, поскольку дефолтное поведение Grid Layout не изменилось. Теперь есть новое значение normal для свойств выравнивания: justify-content
, align-content
, justify-items
, align-items
, justify-self
и align-self
.
Самое интересное в normal
то, что он ведёт себя по-разному в зависимости от модели раскладки. В общем, в случае с Grid Layout поведение такое же, как и при использовании ключевого слова stretch
.
Заключение
Это лишь общий взгляд на то, что произошло за лето в реализациях гридов в Blink и Webkit, над которыми работает Igalia. Конечно, я опустил кучу всего, вроде исправления кучи багов и даже оптимизации (например, вложенные гриды стали на 350% быстрее).
Возможно для кого-то из вас эти изменения действительно важны, а для других не особо актуальны. Здесь главное, что дело движется, и что реализации всё ближе к спецификации. А значит мы на правильном пути, чтобы вскоре включить CSS Grid Layout в большинстве основных браузеров.
Igalia и Bloomberg вместе работают над тем, чтобы сделать веб лучше.
Ну и напоследок кое-что важное, как всегда, мы хотели бы поблагодарить наших друзей в Bloomberg за их потрясающую поддержку, благодаря которой наша работа над Grid Layout не прерывается.
P.S. Это тоже может быть интересно:
Есть какое-то различие между
grid-template-columns: fit-content(100px) 1fr;
и
grid-template-columns: auto 1fr;
у вложенного
max-width: 100px;
В каком случае fit-content() лучше max-width?
Я пока смог найти разницу только при использовании overflow: https://jsfiddle.net/86dart1L/. Причем опять Хром и Файрфокс ведут себя по-разному, и на этот раз правильным мне кажется поведение Хрома. Но могу заблуждаться, надо будет доразбираться…
Файрфокс правильнее показывает. Поведение такое же как у флексбокс. Нужно добавить min-width: 0; https://jsfiddle.net/NMitra/86dart1L/1/
Удивительно, но у меня Хром отображает первый пример по-разному на разных ОС: на Windows 7 и OS X Sierra обе строчки одинаковы, но вчера, когда тестировал на Windows 10, в первой строчке первый элемент был размером по контенту, и второй элемент начинался после него. Сейчас у меня так показывает только Safari TP 25. Вот как так может быть? Мистика какая-то.
Я ориентировался на спеку CSS Box Sizing (на которую ведет ссылка из статьи), где для fit-content() дается формула
min(max-content size, max(min-content size, <length-percentage>))
. Насколько я могу судить, по ней в данном случае должен «победить» min-content, определенный как «наименьший размер бокса, при котором еще не происходит переполнения». Насколько хватает моих знаний, в этом случае это должен быть размер длинного слова. А min-width: 0; как раз это поведение переопределяет. Но могу заблуждаться…Я толком не разбиралась и специфику не читала :( Предположение на уровне «метода тыка и так логичнее».
Вначале min-width есть у каждого элемента и имеет по-умолчанию значение 0 https://www.w3.org/wiki/CSS/Properties/min-width С флексбоксами появляется значение auto и становиться начальным https://www.w3.org/TR/css-flexbox-1/#min-size-auto
min-width не игнорируется у гридов и влияет на конечное отображение, так же как и max-width.
Приветствую!
Есть 3 вложенных грид контейнера в одной грид сроке, в каждом контейнере по 3 грид строки с содержимым, заголовок, картинка и подпись снизу. Если на одной из таких областей сверху заголовок перенесется на 2 строку, то картинка опустится чуть ниже. Можно ли как-то сделать так, что бы все строки этих вложенных контейнеров расположенных в одной строке внешнего контейнера расширялись до максимальной высоты в одной строке вложенных контейнеров?
grid 1 grid 2 grid 3
======== ========= =========
| заголовок | Заголовок | Заголовок |
| в 2 строки | | |
========= ========= ========
Нужно что бы высота строки подбиралась по максимальной высоте содержимого ячейки.
Спасибо!
Насколько я понимаю, для такого случая напрашиваются подсетки (subgrids), которых пока нет:(. Если контейнеров всего три и это фиксированно, можно попробовать задать контейнерам display:contents и «раскидать» их потомков по ячейкам внешнего грида. Может быть, для конкретного случая можно обойтись имитацией решения, напр. через выравнивание по последней базовой линии заголовков…