Kodokon kodokon.com

Экспертные сетки: subgrid, auto-fit и minmax

Строй самонастраивающиеся сетки без медиазапросов и выравнивай вложенные компоненты по трекам родителя с помощью subgrid.

10 мин · 3 вопросов

Открыть этот урок в Kodokon

repeat(auto-fill, ...) и repeat(auto-fit, ...) создают столько треков, сколько позволяет ширина контейнера. Разница видна только тогда, когда элементов меньше, чем возможных треков: auto-fill сохраняет пустые треки (твои две карточки остаются минимального размера, а справа зияет пустота), тогда как auto-fit схлопывает пустые треки в ноль - занятые треки, у которых максимум задан как 1fr, затем впитывают всё освободившееся место, и твои две карточки растягиваются на всю ширину.

CSS
.gallery-fill {
  display: grid;
  grid-template-columns: repeat(
    auto-fill, minmax(150px, 1fr)
  );
}
.gallery-fit {
  display: grid;
  grid-template-columns: repeat(
    auto-fit, minmax(150px, 1fr)
  );
}
С 2 элементами в 900px: fill сохраняет 6 треков (2 заполненных, 4 пустых), fit схлопывает пустые и растягивает 2 элемента.

Две ловушки minmax(), в которые попадают даже опытные разработчики. Первая: minmax(240px, 1fr) вылезает за границы, когда контейнер уже 240px - минимум это жёсткий пол. Идиоматичное решение вкладывает функцию сравнения: minmax(min(100%, 240px), 1fr). Вторая: один 1fr эквивалентен minmax(auto, 1fr); минимум auto позволяет неразрывному содержимому (длинный URL, блок <pre>) раздуть трек сверх его доли. minmax(0, 1fr) фиксирует распределение.

CSS
.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 240px), 1fr)
  );
}
Каноническая адаптивная сетка без единого медиазапроса: никогда не переполняется, даже при ширине меньше 240px.

subgrid решает старую проблему выравнивания между вложенными компонентами. С grid-template-rows: subgrid внутренняя сетка не выдумывает свои треки: она перенимает треки родителя на той области, которую занимает. Она также наследует имена линий родителя (и может добавить свои), а вместе с ними и gap, который может переопределить локально. Классический случай: карточки, у которых заголовок, описание и подвал выравниваются по горизонтали от карточки к карточке, какой бы длины ни было их содержимое - до subgrid сделать это чисто было невозможно, потому что каждая карточка считала свои высоты изолированно.

CSS
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
.card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0.5rem;
}
Каждая карточка занимает 3 строки родителя и перенимает их: заголовки, тексты и подвалы выравниваются между карточками.

Проверка знаний

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

  1. Контейнер вмещает 6 треков, но содержит только 2 элемента. В чём разница между auto-fill и auto-fit?
    • Никакой, это два псевдонима одного значения
    • auto-fill сохраняет 4 пустых трека; auto-fit схлопывает их, и 2 элемента растягиваются
    • auto-fit всегда создаёт больше треков, чем auto-fill
  2. Что именно перенимает элемент, объявленный с grid-template-rows: subgrid?
    • Только количество строк родителя
    • Размеры треков и имена линий родителя на занимаемой области, с наследуемым, но переопределяемым gap
    • Все свойства сетки родителя, включая его именованные области
  3. Зачем писать minmax(min(100%, 240px), 1fr), а не minmax(240px, 1fr)?
    • Чтобы гарантировать 240px на любом экране
    • Чтобы избежать переполнения, когда контейнер уже 240px
    • Потому что min() обязателен внутри repeat() начиная с Grid Level 2