Дайджесты новостей
Изометрическая визуализация алгоритма CSS Grid Lanes с разновысокими карточками в трёх вертикальных дорожках на рабочем столе дизайнера.

CSS Grid Lanes: как устроена нативная masonry-раскладка без JavaScript

Если ты верстал витрину товаров или фотогалерею в духе Pinterest, то знаешь эту классическую боль. Карточки имеют разную высоту: где-то снимок вертикальный, где-то заголовок длиннее. Нам хочется прижать их друг к другу по вертикали в плотные колонки без пустот — в вебе это называют раскладкой masonry (плиточной кладкой).

Обычный двухмерный CSS Grid для этого не подходил: его сетка создает жесткие пересечения строк и колонок. Если в первой строке один элемент вытянулся на 500 пикселей, вся строка послушно раздувается, а под соседними блоками зияют дыры. Многоколоночный column-count тоже не спасал: он заполняет колонки сверху вниз, ломая порядок чтения слева направо.

В итоге разработчики годами подключали скрипты вроде Masonry.js. Библиотека в рантайме вычисляла координаты через getBoundingClientRect() и расставляла инлайновые стили top и left. Я не раз видел, как это приводило к сдвигам макета (CLS), дерганой прокрутке и жору батареи. Но костылям пришел конец: браузеры согласовали нативный режим display: grid-lanes.

Битва гигантов: почему согласования ждали почти десять лет

Спор о синтаксисе masonry в рабочей группе CSSWG тянулся с 2017 года:

  1. Команды Mozilla и WebKit (Apple Safari) настаивали, что плиточная кладка должна расширять CSS Grid через значение grid-template-rows: masonry. Главный плюс — переиспользование привычного аппарата Grid: отступов gap, функций repeat() и minmax(), субгридов и именованных линий.
  2. Команда Google Chromium считала, что Grid по своей сути строго двухмерен, а плитка управляет лишь одной осью. Гугл предлагал изолированный контекст display: masonry с собственными свойствами.

В конце 2025 года консорциум W3C утвердил компромисс. Спецификация вошла в черновик W3C CSS Grid Layout Module Level 3 под именем display: grid-lanes (дорожки сетки). Движок WebKit уже реализовал синтаксис в Safari Technology Preview 234 и Safari 26.4+, а авторы выпустили интерактивный справочник Field Guide to CSS Grid Lanes. Ранее мы разбирали черновые подходы в статье о том, как display: grid-lanes становится нативной альтернативой JS-сеткам, а свежие детали раскрыли портал Piccalilli и канал Библиотека фронтендера.

Анатомия механизма: как браузер упаковывает карточки в дорожки

Слово «lanes» (дорожки) точно описывает суть. Представь кассы в супермаркете: колонки — это очереди. Покупатель с тележкой (карточка контента) подходит к кассовой зоне и встает туда, где очередь сейчас короче всего.

В стандартном Grid браузер выравнивает блоки одновременно по строкам и колонкам. В Grid Lanes жесткая сетка задается только по оси треков (обычно колонкам), а вдоль оси упаковки элементы укладываются независимо по алгоритму заполнения (fill algorithm):

  1. Разметка дорожек: браузер вычисляет ширину колонок через привычный синтаксис:
.masonry-gallery {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 1.5rem;
}
  1. Счетчики высоты: движок отслеживает накопленную высоту каждой колонки с учетом отступов gap.
  2. Приоритет явных позиций: элементы со span 2 или жестко заданными координатами размещаются первыми, бронируя место.
  3. Авторазмещение: для каждого следующего элемента браузер находит дорожку с наименьшей текущей высотой, помещает карточку туда и обновляет высоту дорожки.

Вся математика выполняется на C++ прямо в конвейере компоновки браузера, обеспечивая стабильные 60 кадров в секунду.

Укрощение хаоса: зачем браузерам свойство fit-tolerance

Жадный алгоритм упаковки таит неприятный баг. Допустим, колонка №1 имеет высоту 400px, а соседняя колонка №2 — 398px. Разница всего в два пикселя незаметна глазу, но алгоритм считает колонку №2 строго короче. Браузер бросает следующую карточку во второй столбец, ломая естественный порядок чтения слева направо.

Для решения этой проблемы рабочая группа ввела свойство fit-tolerance (допуск подгонки):

  • fit-tolerance: 0 — абсолютная плотность. Браузер всегда выбирает самую низкую колонку, игнорируя порядок элементов в HTML.
  • fit-tolerance: 1em (значение normal по умолчанию) — разумный баланс. Дорожки с разницей высот в пределах 1em считаются равными. Среди них браузер выбирает ту, которая сохраняет порядок чтения слева направо.
  • fit-tolerance: infinite — строгий приоритет порядка разметки. Карточки идут строго по очереди, даже если внизу остаются пустоты.
.masonry-gallery {
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: 1.25rem;
  fit-tolerance: 1em;
}

.card-featured {
  grid-column: span 2;
}

Субгриды и кирпичная кладка: скрытые суперсилы синтаксиса

Интеграция с CSS Grid дает нативную поддержку CSS Subgrid. Внутри карточки могут быть картинка, заголовок, текст и кнопка. Благодаря субгридам внутренние элементы выравниваются по общим линиям:

.recipe-card {
  display: grid;
  grid-template-columns: subgrid;
}

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

.horizontal-brick {
  display: grid-lanes;
  grid-template-rows: repeat(3, 200px);
  gap: 1rem;
}

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

Грабли доступности и безопасный запуск в продакшене

У нативной плитки есть уязвимое место — доступность (a11y). Когда элементы раскладываются по кратчайшим колонкам, визуальный порядок на экране расходится с физическим порядком в DOM.

Пользователь с клавиатурой (Tab) или скринридером идет строго по HTML-дереву. Мы подробно разбирали, как автоматическая раскладка CSS Grid Lanes нарушает доступность интерфейсов по стандарту WCAG 2.4.3: если фокус прыгает между колонками хаотично, ориентироваться невозможно.

Совет по сохранению логики чтения

Если карточки образуют связанную хронологическую цепочку, задавай fit-tolerance: infinite либо верстай каждую карточку как автономный смысловой блок <article>.

Для безопасного продакшена используй прогрессивное улучшение через @supports:

/* Базовый фоллбек для всех браузеров */
.cards-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: 1.5rem;
  align-items: start;
}

/* Нативные дорожки для поддерживающих браузеров */
@supports (display: grid-lanes) {
  .cards-container {
    display: grid-lanes;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: 1.5rem;
    fit-tolerance: 1em;
  }
}

Старые браузеры покажут классическую сетку с выравниванием по верхнему краю, а современные пользователи получат монолитную плитку без единой строчки JS.