CSS Grid Layout и позиционированные элементы

Перевод статьи CSS Grid Layout and positioned items с сайта blogs.igalia.com, опубликовано на css-live.ru с разрешения автора — Мануэля Рего Касановаса.

В этой статье мы рассмотрим некоторые особенные возможности позиционированных грид-элементов.

В рамках работы Igalia над CSS Grid Layout в Chromium/Blink и Safari/WebKit, мы реализовали поддержку позиционированных элементов. Да, абсолютное позиционирование в гриде :)

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

В общем-то, они мало чем отличаются от обычных грид-элементов. Когда грид-контейнер выступает в роли содержащего блока для позиционированных элементов,  (например, при использовании position: relative; для грид-контейнера), тогда они размещаются почти так же, как и обычные грид-элементы. Но с некоторыми оговорками:

  • Позиционированные элементы по умолчанию не растягиваются.
  • Они не используют неявный грид. Они не создают неявные полосы.
  • Они не занимают ячейки с учётом функции автоматического размещения.
  • При обращении к линиям у auto есть специальное значение

Разберём подробно каждый из пунктов.

Позиционированные элементы ужимаются по содержимому

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

Простой пример это легко пояснит:

<div style="display: grid; position: relative;
grid-template-columns: 300px 200px; grid-template-rows: 200px 100px;">
    <div style="grid-column: 1 / 3; grid-row: 1 / 3;"></div>
    <div style="position: absolute; grid-column: 1 / 3; grid-row: 1 / 3;"></div>
</div>

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

Позиционированные элементы ужимаются по содержимому

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

Но в следующих пунктах я не учитываю эту разницу, поскольку моя задача — показать область, занимаемую каждым позиционированным элементом. Чтобы получить результат как на изображении, пришлось бы установить позиционированным элементам ширину и высоту по 100%.

Позиционированные элементы и неявный грид

Позиционированные элементы не участвуют в раскладке грида и не влияют на размещение элементов.

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

Следующий пример пояснит это:

<div style="display: grid; position: relative;
grid-template-columns: 200px 100px; grid-template-rows: 100px 100px;
grid-auto-columns: 100px; grid-auto-rows: 100px;
width: 300px; height: 200px;">
    <div style="position: absolute; grid-area: 4 / 4;"></div>
</div>

В примере определяется сетка 2х2, но позиционированный элемент использует grid-area: 4 / 4;, пытаясь растянуться до 4-го ряда и 4-й колонки. Однако, позиционированные элементы не могут создать эти неявные полосы. Поэтому он позиционируется, как если бы у него стояло auto, занимая весь явный грид. В позиционированных элементах auto ведет себя по-особому, но это мы как следует разберем позже.

Позиционированные элементы не создают неявные полосы

А теперь представьте пример, где обычные элементы создают неявные полосы:

<div style="display: grid; position: relative;
grid-template-columns: 200px 100px; grid-template-rows: 100px 100px;
grid-auto-columns: 100px; grid-auto-rows: 100px;
width: 500px; height: 400px;">
    <div style="grid-area: 1 / 4;"></div>
    <div style="grid-area: 4 / 1;"></div>
    <div style="position: absolute; grid-area: 4 / 4;"></div>
</div>

В этом случае обычные элементы создают неявные полосы, образуя в итоге сетку 4х4. Теперь позиционированный элемент может разместиться в 4-м ряду и 4-й колонке, даже если эти колонки находятся в явном гриде.

Позиционированные элементы не могут размещаться в неявном гриде

Как видите, эта часть статьи была изменена. Спасибо @fantasai за указания на ошибки.

Позиционированные элементы и алгоритм размещения

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

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

Рассмотрим это поведение на простом примере:

<div style="display: grid; position: relative;
grid-template-columns: 300px 300px; grid-template-rows: 200px 200px;">
    <div style="grid-column: auto; grid-row: auto;"></div>
    <div style="grid-column: auto; grid-row: auto;"></div>
    <div style="grid-column: auto; grid-row: auto;"></div>
    <div style="position: absolute;
grid-column: 2 / 3; grid-row: 1 / 2;"></div>
</div>

И снова перед нами сетка 2х2 с тремя автоматически размещёнными обычными элементами и одним абсолютно позиционированным элементом. Как видите, позиционированный элемент размещается в 1-м ряду и 2-й колонке, но в этой же ячейке есть еще и и автоматически размещённый элемент, находящийся под позиционированным. Это показывает, что грид-контейнер не учитывает позиционированные элементы, игнорируя их во время размещения обычных элементов.

Позиционированные элементы и алгортим размещения

Если дочерние элементы вообще не позиционировать, то последний разместится в заданной позиции (1-й ряд и 2-я колонка), а остальные (автоматически размещённые) займут другие ячейки без перекрытия.

Позиционированные элементы и линии auto

Видимо, это наибольшая разница по сравнению с обычными грид-элементами. Если линия не указана, считается, что используется auto, но auto не рассчитывается, как span 1, как в обычных элементах. Для позиционированных элементов за auto принимается внешняя граница padding-а.

Спецификация вводит понятия линий 0 и -0, что кажется странным, но на самом деле это вполне разумно. Линиями auto будут считаться линии 0 и -0, представляющие внешние границы padding-а грид-контейнера.

И снова, возьмём наглядный пример:

<div style="display: grid; position: relative;
grid-template-columns: 300px 200px; grid-template-rows: 200px 200px;
padding: 50px 100px; width: 500px; height: 400px;">
    <div style="position: absolute;
grid-column: 1 / auto; grid-row: 2 / auto;"></div>
</div>

У нас есть грид-контейнер 2х2 с небольшим padding-ом. Позиционированный элемент размещается во 2-м ряду и 1-й колонке, но его область простирается вплоть до внешних границ padding-а (поскольку конечная линия — auto по обеим осям).

Позиционированные элементы и линии auto

Можно даже размещать позиционированные грид-элементы поверх самого padding. Например, с grid-column: auto / 1; элемент находился бы на левом padding-е.

Позиционированные элементы с помощью линии auto размещаются на левом padding-е.

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

<div style="display: grid; position: relative;
grid-template-columns: 300px 200px; grid-template-rows: 200px 200px;
padding: 50px 100px; width: 600px; height: 400px;">
    <div style="position: absolute;
grid-column: 3 / auto; grid-row: 2 / 3;"></div>
</div>

В этом коде ширина колонок равна 500px, а ширина грид-контейнера — 600px. А значит для содержимого грида осталось лишних 100px свободного места. Из примера видно, что позиционированный элемент занимает и эту область, простираясь вплоть до внешних границ padding-а.

Позиционированные элементы занимают свободную область и правый padding

Смещения

И конечно же, для размещения позиционированных элементов можно использовать смещение (свойства left, right, top и bottom)

Эти смещения применяются внутри грид-области, определённой для позиционированных элементов, следуя вышеописанным правилам

Возьмём другой пример:

<div style="display: grid; position: relative;
grid-template-columns: 300px 200px; grid-template-rows: 200px 200px;
padding: 50px 100px; width: 500px; height: 400px;">
    <div style="position: absolute;
grid-column: 1 / auto; grid-row: 2 / auto;
left: 90px; right: 70px; top: 80px; bottom: 60px;"></div>
</div>

И снова грид-контейнер 2х2 с padding-ом. У позиционированного элемента есть смещение, отсчитываемое от его грид-области.

Позиционированные элементы и смещение

Итого

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

Здорово ещё то, что можно протестировать это в большинстве последних версиях современных браузеров: Chrome Canary, Safari Technology Preview и Firefox. Надеемся, что эти реализации совместимы, но если заметите проблемы, не забудьте сообщить.

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

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

Наконец, мы хотим снова поблагодарить Bloomberg за поддержку Igalia в реализации CSS Grid Layout в Blink и WebKit.

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

3 Комментарии

  1. Nazar

    Grid Layout? http://caniuse.com/#search=Grid%20Layout — где его применять, если такая поддержка у браузеров?

    1. SelenIT

      Включить флаг (в Firefox Beta/Nightly и последнем Safari TP включено по умолчанию) — и во всех актуальных браузерах можно использовать для быстрых прототипов. А то и для админок, где можно включить опред. браузер с опред. настройками в требования. Зато, когда осенью-зимой (если бы не начали суету с подсетками — могло бы быть уже…) браузеры внезапно откроют эту фичу для всех, у вас уже будет опыт работы с ней.

      1. Nazar

        Понял. Спасибо!

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

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

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

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