На главную

Item Flow: объединяем флексы, гриды и Masonry в единый инструмент


Сегодня я хочу поделиться идеей, которая объединяет флексы и гриды в нечто совершенно новое и, возможно, приведёт нас к полноценной нативной Masonry‑раскладке в CSS. Ниже я расскажу об этой задумке, которую сейчас обсуждает Apple, Google, W3C и многие другие команды, и объясню, почему это важно.

Зачем нам Item Flow

Флексы и гриды уже подарили нам мощные инструменты для построения сложных макетов. Но, увы, до сих пор невозможно из коробки реализовать популярный «masonry» (или «waterfall») — ту самую «каскадную» раскладку, когда блоки с разной высотой (или шириной) складываются подобно кирпичикам без ровных строк и столбцов.

Фотографии разной высоты, но одинаковой ширины идут друг за другом и формируют сетку Раскладка Masonry

Обычно для такого эффекта приходится подключать JavaScript‑библиотеки.

Несколько лет назад разные команды браузеров попытались внедрить Masonry в движок, и в итоге появились две основные конкурирующие концепции:

  1. Just Use Grid. Предлагалось добавить в гриды специальную «обрушенную» стратегию для строк/столбцов.
  2. New Masonry Layout. Идея сделать отдельное значение у display (например, display: masonry).

Однако Техническая Рабочая Группа (W3C TAG) высказала мысль: почему бы не объединить Masonry, флексы и гриды в единый набор свойств, чтобы вёрстка стала более универсальной, а мы получили гибкий инструмент для всех трёх задач разом?

Так родилась идея Item Flow.

Что такое Item Flow

Сегодня у нас есть два свойства для управления «потоком» элементов:

  • flex-flow (для флексов)
  • grid-auto-flow (для гридов)

Item Flow хочет заменить и расширить их с помощью новых свойств и значений, чтобы разработчик мог одинаково управлять направлением, переносом, «упаковкой» и другими нюансами — и в гридах, и во флексах, и в будущем Masonry.

Три кита нового подхода

  1. Универсальное направление

    Вместо flex-direction и части grid-auto-flow (row, column) появится единое свойство:

    item-direction: row | column | row-reverse | column-reverse;

    Оно определяет, будет ли всё располагаться в строку или в столбец, в прямом или в обратном порядке.

  2. Гибкий перенос

    Флексы давно умеет переносить элементы (flex-wrap), а гриды по умолчанию уже создаёт новые ряды. Но теперь всё это становится единым механизмом:

    item-wrap: auto | nowrap | wrap | normal | reverse;
    • auto — поведение по умолчанию (как сегодня: флексы не переносит, гриды переносит).
    • nowrap — отключение переноса (но теперь и для гридов; это позволит сделать, например, одну строку с фиксированным количеством колонок 1fr).
    • wrap или normal — обычный перенос.
    • reverse — перенос в обратном направлении (аналог wrap-reverse для флексов).
  3. Способы «упаковки» Сегодня у гридов есть «плотный» режим (dense), а у флексов только стандартный. item-pack может это объединить:

    item-pack: normal | dense | balance | collapse ...;
    • normal — стандартная «неплотная» раскладка.
    • dense — попытки уплотнять и заполнить пустые места (в гридах уже есть, для флексов обсуждается, как именно это лучше работать).
    • balance — потенциальный новый режим, когда элементы распределяются по строкам более равномерно (чтобы не было ситуации «5 элементов в первой строке и 1 во второй»).
    • collapse (или похожее значение) — возможный триггер для Masonry‑раскладки. Вместо жёстких рядов и столбцов элементы «обрушаются» так, чтобы минимизировать пустоты.

Таким образом, Masonry может быть не grid-template-rows: collapse; и не display: masonry;, а, например, item-pack: collapse;. И при этом мы используем единый подход как для гридов, так и для флексов.

А что за item-slack?

Ещё одна новая идея — свойство item-slack, которое задаёт «толерантность» при решении, помещать ли элемент в текущую строку/колонку или переносить. Оно особенно важно для Masonry, когда браузер «ищет» колонку с минимальным остатком по высоте. Но и в флексам это может пригодиться: скажем, item-slack: 1em даёт команду «если элемент чуть-чуть не влезает, всё равно постарайся его вместить, чуть ужав остальное».

Название пока обсуждается. Возможно, появятся другие варианты: threshold, tolerance и т.д.

Пример общего синтаксиса

.container {
  display: flex; /* или grid */
  item-flow: row wrap dense;
}

Или подробно:

.container {
  display: flex;
  item-direction: row;
  item-wrap: wrap;
  item-pack: dense;
}

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

Почему это может изменить всё

  • Grid без переноса. Наконец-то можно легко собрать всё содержимое в одну строку, распределив элементы равномерно на 1fr.
  • Плотная упаковка во флексах. Теперь не нужно городить костыли, когда хочется «впихнуть» ещё один элемент в строку, если там остаётся чуть-чуть места.
  • Сбалансированная укладка. Никто не любит, когда в последней строке остаётся один блок, а все остальные загружают первую строку. Новый режим balance может это исправить.
  • Masonry без ухищрений. Настоящее «обрушение» строк или столбцов, без подключения внешних JS‑плагинов.

Мы стоим на пороге больших перемен в мире CSS: объединение флексов, гридов и Masonry в рамках Item Flow может сильно упростить нам жизнь и дать новые инструменты для креативной вёрстки.

Источники