CSS-live.ru

Как грид-раскладка (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>

8

Пример с 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>

8

Пример множественных полос для 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>

8

Пример множественных полос для нотации 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>

8

Пример с функцией 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>

8

Пример с процентными интервалами

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>

8

Пример короткой записи 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>

8

Пример перпендикулярных потоков

Новое значение 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 в большинстве основных браузеров.

8

Igalia и Bloomberg вместе работают над тем, чтобы сделать веб лучше.

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

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

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

  1. Есть какое-то различие между

    grid-template-columns: fit-content(100px) 1fr;

    и

    grid-template-columns: auto 1fr;
    у вложенного
    max-width: 100px;

    В каком случае fit-content() лучше max-width?

    1. Я пока смог найти разницу только при использовании overflow: https://jsfiddle.net/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; как раз это поведение переопределяет. Но могу заблуждаться…

          1. Я толком не разбиралась и специфику не читала :( Предположение на уровне «метода тыка и так логичнее».

            Вначале 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.

  2. Приветствую!

    Есть 3 вложенных грид контейнера в одной грид сроке, в каждом контейнере по 3 грид строки с содержимым, заголовок, картинка и подпись снизу. Если на одной из таких областей сверху заголовок перенесется на 2 строку, то картинка опустится чуть ниже. Можно ли как-то сделать так, что бы все строки этих вложенных контейнеров расположенных в одной строке внешнего контейнера расширялись до максимальной высоты в одной строке вложенных контейнеров?

    grid 1               grid 2               grid 3

    ========  ========= =========

    | заголовок | Заголовок | Заголовок  |

    | в 2 строки |                      |                       |

    =========  ========= ========

    Нужно что бы высота строки подбиралась по максимальной высоте содержимого ячейки.

    Спасибо!

    1. Насколько я понимаю, для такого случая напрашиваются подсетки (subgrids), которых пока нет:(. Если контейнеров всего три и это фиксированно, можно попробовать задать контейнерам display:contents и «раскидать» их потомков по ячейкам внешнего грида. Может быть, для конкретного случая можно обойтись имитацией решения, напр. через выравнивание по последней базовой линии заголовков…

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

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

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