Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Subgrid

Сетка Grid выравнивает своих прямых детей. Но внутри карточки — свои элементы: заголовок, текст, кнопка, и о соседних карточках они ничего не знают. Если у одной карточки заголовок в две строки, её кнопка съезжает ниже, чем у соседей. Subgrid (подсетка) решает это: вложенная сетка берёт строки или колонки у родительской.

Проблема

Три карточки в сетке, у каждой своя внутренняя сетка. Заголовки разной длины, и всё ниже них разъезжается:

<style>
  .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .card { display: grid; gap: 8px; padding: 12px; background: lavender; }
  .card h3 { margin: 0; font-size: 16px; }
  .card p { margin: 0; }
</style>
 
<div class="cards">
  <div class="card"><h3>Капучино</h3><p>Эспрессо и молочная пена.</p><button>В корзину</button></div>
  <div class="card"><h3>Раф с ванильным сахаром и сливками</h3><p>Нежный и сладкий.</p><button>В корзину</button></div>
  <div class="card"><h3>Латте</h3><p>Много молока.</p><button>В корзину</button></div>
</div>

Текст и кнопка второй карточки стоят ниже, чем у соседей: каждая карточка считает свои строки сама.

grid-template-rows: subgrid

Решение — две строчки. Карточка занимает в родительской сетке три строки (grid-row: span 3), а вместо своих строк берёт эти три: grid-template-rows: subgrid:

<style>
  .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .card {
    display: grid;
    grid-row: span 3;
    grid-template-rows: subgrid;
    gap: 8px;
    padding: 12px;
    background: lavender;
  }
  .card h3 { margin: 0; font-size: 16px; }
  .card p { margin: 0; }
</style>
 
<div class="cards">
  <div class="card"><h3>Капучино</h3><p>Эспрессо и молочная пена.</p><button>В корзину</button></div>
  <div class="card"><h3>Раф с ванильным сахаром и сливками</h3><p>Нежный и сладкий.</p><button>В корзину</button></div>
  <div class="card"><h3>Латте</h3><p>Много молока.</p><button>В корзину</button></div>
</div>

Теперь строка заголовков одной высоты у всех карточек: по самому длинному. Текст и кнопки выстроились в линию.

Как это работает

Строки теперь принадлежат родителю .cards, а карточка лишь раскладывает своих детей по ним. Высоту каждой строки браузер считает по всем карточкам сразу. Поэтому число в span должно совпадать с числом частей карточки: три части — span 3.

Свойство карточкиЗачем
display: gridкарточка — тоже сетка
grid-row: span 3занять три строки родителя
grid-template-rows: subgridвзять эти строки себе
gapсвой промежуток между частями

gap подсетка наследует от родителя, но его можно переопределить, как в примере.

Колонки тоже

grid-template-columns: subgrid выравнивает колонки. Так делают форму, где все подписи одной ширины, хотя каждая пара «подпись — поле» лежит в своём блоке:

<style>
  .form { display: grid; grid-template-columns: max-content 1fr; gap: 8px; max-width: 400px; }
  .row { display: grid; grid-column: span 2; grid-template-columns: subgrid; align-items: center; }
</style>
 
<div class="form">
  <div class="row"><label for="n">Имя</label><input id="n"></div>
  <div class="row"><label for="e">Электронная почта</label><input id="e"></div>
</div>

max-content делает первую колонку шириной по самой длинной подписи, и оба поля начинаются на одной линии.

Поддержка

Subgrid работает во всех основных браузерах с 2023 года. В старом браузере subgrid не распознаётся, карточка становится обычной сеткой, и вёрстка выглядит как в первом примере — неровно, но не сломано.

Частая ошибка

Забыли grid-row: span 3. Карточка занимает в родителе одну строку, и подсетке достаётся только она. Лишним частям места нет — они наезжают друг на друга:

<style>
  .cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .card { display: grid; grid-template-rows: subgrid; padding: 12px; background: mistyrose; }
  .card h3, .card p { margin: 0; }
</style>
 
<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 всегда идёт в паре со span на нужное число строк или колонок.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.