Приветствую. Представляю вашему вниманию перевод статьи «Native CSS Masonry Layout In CSS Grid», опубликованной 2 ноября 2020 года автором Rachel Andrew
Недавно был опубликован черновик спецификации CSS Grid 3 уровня, в котором содержится описание способа создания Masonry-раскладки с помощью чистого CSS. В этой статье Rachel Andrew объясняет данную спецификацию с примерами, которые вы можете воспроизвести в браузере Firefox Nightly. И хотя данный функционал пока что нельзя использовать в реальных проектах, ваш отзыв может помочь убедиться, что текущая реализация соответствует или не соответствует требованиям разработчиков к этому типу раскладки. Итак, приступим.
Что такое Masonry-раскладка?
При masonry-раскладке элементы располагаются один за другим в строчном направлении. При переносе на новую строку они могут смещаться вверх, заполняя пространство, оставленное коротким элементом, расположенным на предыдущей строке текщей колонки. Это похоже на Grid-разметку с автоматическим расположением элементов, но строгого выравнивания по вертикали.
Наиболее известный пример masonry-раскладки – это Pinterest, и вы могли слышать, как её порой даже называют "Pinterest-раскладкой".
Существует множество JavaScript-инструментов, помогающих добиться такого эффекта. Например, Masonry plugin от David DeSandro’s.
Разве сейчас это невозможно?
Приблизиться к Masonry можно с помощью нескольких способов. Самый простой из них – использовать Мультиколонки (раскладку в несколько столбцов). В примере ниже расположение элементов визуально напоминает Masonry. Однако, блоки располагаются в колонках один под другим. Из-за этого вверху такой раскладки будут располагаться элементы, расположенные не в начале списке. А это может быть критически важно, например, при отображении результатов поиска.
Второй способ - CSS Grid. Когда дизайнеры впервые видели Grid-раскладку, часто думали, с помощью автоматического расположения элементов в плотном (dense) режиме можно достичь вида, подобного Masonry. Но это по-прежнему сетка, следовательно не получится заставить элементы занимать свободное место по вертикали, оставленное другими короткими элементами.
Вывод – для получения Masonry всё ещё необходимо использовать JavaScript. А создание раскладки с помощью JavaScript, особенно при большом количестве элементов, не идёт на пользу производительности. Я сразу указала на то, что веб-разработчики просили этот функционал ещё в Январе 2017 года. И хотя у меня есть некоторые опасения касательно того, действительно ли следует делать Masonry частью CSS Grid, а также касательно проблем с доступностью из-за изменения порядка содержимого, я рада, что в этом направлении ведётся активная работа.
Режим Masonry в CSS Grid
Это новая спецификация, поэтому некоторые моменты могут измениться, прежде чем начнут поддерживаться большинством браузеров. Но поскольку этот функционал уже реализован в Firefox, мы можем опробовать его уже сейчас. Для этого скачайте Firefox Nightly и в разделе about:config
активируйте флаг layout.css.grid-template-masonry-value.enabled
. После этого все демонстрации будут работать корректно.
Чтобы реализовать Masonry-раскладку, одна из осей Grid-контейнера должна иметь свойство grid-template-*
со значением masonry
. Она будет называться "masonry-осью". Строки и колонки на другой оси будут определены как обычно, это будет "grid-ось". Приведённый ниже CSS создаёт четырёхколоночную сетку, в которой строки установлены в значение masonry
. Masonry-элементы будут отображаться в четырёх колонках grid-оси.
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
}
Это всё, что нужно, чтобы получить простую masonry-раскладку. С помощью Firefox Nightly можно посмотреть реальный Codepen-пример ниже.
Собственно, на этом можно было и остановиться, но так как функционал Masonry становится частью CSS Grid, мы можем использовать и другие возможности данной спецификации, даже когда находимся в режиме "Masonry". Следовательно спецификация требует определения этих моментов.
Поведение Grid-оси
Ось, на которой просто определяются треки, ведёт себя стандартно. Следовательно, можно задавать размер треков, имена линий и использовать выравнивание точно так же, как это делается в обычной сетке.
Также, с помощью линий на оси можно располагать элементы. Они будут добавлены на сетку перед добавлением masonry-элементов. Я добавила изображение с подписью "5" между линией box-start
и линией box-end
. Masonry-элементы расположились вокруг данного изображения.
Также можно изменять span - количество треков, которые охватывает элемент как на обычной grid-оси. В следующем примере нескольким элементам задан класс landscape
. При размещении в режиме masonry-раскладки, эти элементы занимают два колоночных трека.
Свойство "masonry-auto-flow"
Описание masonry в спецификации вводит дополнительные свойства в Grid-раскладку. Свойство masonry-auto-flow
ещё не добавлено в Firefox. Но когда это произойдёт, оно даст контроль над потоком элементов в Masonry-раскладке.
Если задать masonry-auto-flow: next
, каждый последующий элемент будет размещаться на следующей позиции grid-оси, а не в колонке с наибольшим количеством места, как происходит по умолчанию.
Свойство masonry-auto-flow: ordered
приведёт к тому, что masonry будет игнорировать элементы, точно спозиционированные на сетке и вместо этого будет использовать обычный порядок элементов в документе (исключение - изменение номера элемента в последовательности с помощью свойства "order").
Свойства "justify-tracks" и "align-tracks"
На момент написания статьи, данные свойства частично работают в Firefox Nightly. Это свойства дополнительного выравнивания masonry-раскладки. Если у вас masonry в блочном направлении, можно использовать align-tracks
, если в строчном - justify-tracks
.
Если в grid-контейнере остаётся дополнительное пространство в оси, в которой располагается masonry, вы можете обнаружить, что элементы выравниваются по начальной стороне контейнера. Начальным значением свойства align-tracks
(в нашем случае с masonry, создаваемой для строк) является start
.
Эти свойства работают вместе с align-content
и justify-content
. Как это происходит, продемонстрировано в следующем примере, где grid-контейнер имеет высоту, равную 200vh
. Для свойства align-track
я устанавливаю значение end
.
Если установлено значение normal
(что будет, если я не задам свойство), то masonry-треки окажутся в конце контейнера.
Если я добавлю align-content: start
, masonry-треки вернутся в начало контейнера. Однако, теперь «выступающие края» раскладки вверху, а не внизу потому что masonry-треки выровнены по конечной стороне.
Примечание: вы можете использовать любые значения, применяемые к свойствам align-content
, align-tracks
или justify-tracks
. В спецификации есть несколько хороших примеров различных комбинаций.
Если задать align-track: stretch
, любые элементы с автоматическим размером будут растянуты. Masonry-эффект сохранён, но все элементы данной оси, имеющие определённый размер, не будут растягиваться.
Свойства align-tracks
и justify-tracks
могут принимать несколько значений. По одному для каждого трека оси сетки. Это значит, что в нашей сетке с четырьмя треками, первый трек может быть растягивающимся, второй - выровненным по начальной стороне, третий - по конечной, четвёртый - по центру.
На момент написания статьи в Firefox это не работало.
В спецификации указано, что если значений меньше, чем треков, оставшиеся треки будут использовать последнее указанное значение. Если значений больше, чем треков, лишние значения будут проигнорированы.
FALLBACK-поведение
Включение этого функционала в спецификацию CSS Grid имеет определённое преимущество, когда речь идёт о создания фолбэк-раскладки. Поскольку masonry ведёт себя так же, как автоматическое размещение, если браузер её не поддерживает, вместо неё может использоваться обычное автоматическое размещение. В раскладке может возникнуть незаполненное пространство, как показано в примере выше, но это не так страшно.
Увидеть этот эффект в действии можно в любом приведённом выше демо, если использовать браузер, не поддерживающий masonry. Вы всё ещё получаете раскладку. Если же нужно было сделать что-то абсолютно другое, проверить наличие поддержки masonry можно с помощью feature queries. Например, для браузеров, не поддерживающих masonry, можно сделать раскладку с помощью мультиколонок.
@supports (grid-template-rows: masonry) {
/* код masonry */
}
Если masonry-раскладка жизненно необходима, её поддержку можно проверить с помощью CSS.support и при необходимости использовать JavaScript-библиотеку. Это означало бы, что по мере внедрения браузерами поддержки masonry, решение на JavaScript уже не использовалось, но присутствовало бы в виде полифила.
Потенциальные проблемы с совместимостью
Хотя masonry в CSS - это здорово, есть ещё одно место, где порядок содержимого в документе может отличаться от того, как оно в итоге выводится на экран. Как я указывала в недавнем issue, думаю, мы создаём потрясающием возможности для разметки, а потому должны донести до людей необходимость быть осторожными в их использовании.
Я писала об этой проблеме в статье «Grid, content re-ordering and accessibility». Надеюсь, что по мере развития спецификации, также будут возобновлены усилия по улучшению способов работы с содержимым и порядком отображения.
Ваш мнение важно
Нам очень повезло не только с этой новой спецификацией, но и с тем, что есть возможность протестировать её в браузере. Если вы где-то используете masonry-раскладку, почему бы не попробовать заменить JavaScript-решение на CSS Grid и посмотреть, как оно будет работать? Если столкнётесь с проблемами или не сможете осуществить что-то, что могли до этого, сообщите об этом в CSSWG, создав issue.
devopg
через сколько лет эта штука будет работать хотябы в хроме без танцев с бубном?