Subgrid
subgrid— значение дляgrid-template-columnsилиgrid-template-rows, которое позволяет вложенному grid-контейнеру использовать линии родительского grid.
Зачем нужно
Без subgrid вложенные grid-контейнеры создают независимые сетки. Элементы внутри карточек не выравниваются друг с другом. Subgrid решает эту проблему: дочерний грид «наследует» линии родителя, и все вложенные элементы выстраиваются в единую сетку.
Где используется
- Карточки с заголовком, описанием и кнопкой — все на одной высоте
- Формы, где labels и inputs выровнены по колонкам родителя
- Таблицы-гриды с ячейками, занимающими несколько строк
- Любая ситуация, где вложенные элементы должны следовать сетке родителя
Предпосылки
- Основы Grid — grid-контейнер, линии, треки
- Grid template —
grid-template-columns/rows
Проблема без subgrid
<div class="cards">
<div class="card">
<h3>Короткий</h3>
<p>Описание</p>
<button>Купить</button>
</div>
<div class="card">
<h3>Очень длинный заголовок карточки</h3>
<p>Более длинное описание товара с подробностями</p>
<button>Купить</button>
</div>
</div>
/* Без subgrid — кнопки на разной высоте */
.cards {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.card {
display: grid;
grid-template-rows: auto 1fr auto; /* Своя независимая сетка */
}
/* Строки каждой карточки рассчитываются отдельно.
Заголовки и кнопки НЕ выровнены между карточками */
Решение с subgrid
.cards {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr auto; /* Общие строки */
gap: 20px;
}
.card {
display: grid;
grid-row: span 3; /* Занимает 3 строки родителя */
grid-template-rows: subgrid; /* Использует строки родителя */
gap: 8px;
}
/* Теперь заголовки, описания и кнопки ВСЕХ карточек
выровнены по общим строкам */
Синтаксис
Subgrid по строкам
.child {
display: grid;
grid-row: span 3; /* Важно: должен занимать нужное число строк */
grid-template-rows: subgrid;
/* Столбцы — свои собственные */
grid-template-columns: 1fr 1fr;
}
Subgrid по столбцам
.child {
display: grid;
grid-column: span 4; /* Занимает 4 столбца родителя */
grid-template-columns: subgrid;
/* Строки — свои собственные */
grid-template-rows: auto auto;
}
Subgrid по обеим осям
.child {
display: grid;
grid-row: span 3;
grid-column: span 2;
grid-template-rows: subgrid;
grid-template-columns: subgrid;
}
Подробный пример: карточки товаров
<div class="products">
<article class="product">
<img src="phone.jpg" alt="Телефон">
<h3>Смартфон XYZ</h3>
<p>Флагман 2026 года с камерой 200 МП</p>
<span class="price">79 990 Р</span>
<button>В корзину</button>
</article>
<article class="product">
<img src="laptop.jpg" alt="Ноутбук">
<h3>Ноутбук Pro</h3>
<p>Для работы и учёбы</p>
<span class="price">129 990 Р</span>
<button>В корзину</button>
</article>
<article class="product">
<img src="headphones.jpg" alt="Наушники">
<h3>Беспроводные наушники с шумоподавлением и длинным названием</h3>
<p>Время работы — 40 часов, активное шумоподавление, прозрачный режим</p>
<span class="price">14 990 Р</span>
<button>В корзину</button>
</article>
</div>
.products {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto auto 1fr auto auto; /* 5 строк на карточку */
gap: 20px;
}
.product {
display: grid;
grid-row: span 5;
grid-template-rows: subgrid;
gap: 8px;
padding: 16px;
border: 1px solid #e0e0e0;
border-radius: 12px;
}
.product img {
width: 100%;
aspect-ratio: 4/3;
object-fit: cover;
border-radius: 8px;
}
.product .price {
font-size: 1.25rem;
font-weight: bold;
color: #e74c3c;
}
.product button {
align-self: end;
padding: 10px;
background: #007bff;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
Gap в subgrid
Subgrid наследует gap родителя, но можно переопределить:
.parent {
display: grid;
gap: 20px;
}
.child {
display: grid;
grid-template-rows: subgrid;
gap: 8px; /* Переопределяет gap родителя для своих строк */
}
Именованные линии в subgrid
Subgrid может добавлять свои имена линий поверх родительских:
.parent {
display: grid;
grid-template-columns: [full-start] 1fr [content-start] 2fr [content-end] 1fr [full-end];
}
.child {
grid-column: full-start / full-end;
display: grid;
grid-template-columns: subgrid [child-start] [child-mid] [child-end];
/* Квадратные скобки добавляют имена к линиям subgrid */
}
Когда использовать subgrid
| Сценарий | Нужен subgrid? |
|---|---|
| Карточки с выровненными секциями | Да |
| Форма: label + input в колонках родителя | Да |
| Независимые вложенные сетки | Нет |
| Таблица с объединёнными ячейками | Да |
| Простая сетка без вложенности | Нет |
Частые ошибки
- Забыли
grid-row: span N— без указания количества строк subgrid не знает, сколько строк наследовать:/* ОШИБКА */ .child { display: grid; grid-template-rows: subgrid; /* Сколько строк? */ } /* ПРАВИЛЬНО */ .child { grid-row: span 3; display: grid; grid-template-rows: subgrid; } - Subgrid без
display: grid— элемент должен быть grid-контейнером - Ожидание, что subgrid наследует
grid-template-areas— subgrid наследует только линии, не области - Количество потомков не совпадает с количеством строк — лишние элементы создадут неявные строки
Практика
- Создать сетку из 3 карточек с выровненными заголовками и кнопками через subgrid
- Применить subgrid только по одной оси (строки)
- Переопределить
gapв subgrid-элементе - Проверить subgrid в DevTools (grid overlay показывает линии)
- Сравнить макет с subgrid и без
Связанные темы
- Основы Grid — базовые понятия grid
- Grid template — определение треков
- Выравнивание в Grid — выравнивание в ячейках
- Практика Grid — реальные макеты с subgrid