Перенос элементов в CSS Grid: auto-fill, auto-fit и minmax()

Чтобы карточки в CSS Grid сами переносились на новую строку, хватит одного правила: grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)).

Разбираем, как браузер считает колонки, чем auto-fill отличается от auto-fit, как ограничить их число сверху и почему широкая карточка ломает сетку на телефоне.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 3156 статей автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3810 экспертных мнений Подписаться на Телеграм-канал
Обложка: Перенос элементов в CSS Grid: auto-fill, auto-fit и minmax()

Чтобы элементы в CSS Grid сами переносились на новую строку, задайте контейнеру grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)). Браузер посчитает, сколько колонок шириной от 200 пикселей влезает в ширину контейнера, растянет их на всё свободное место, а лишние карточки отправит ниже. Медиа-запросы для такой сетки не нужны: на телефоне останется одна колонка, на широком мониторе их станет пять или шесть.

Ниже разберём, как браузер считает колонки, чем auto-fill отличается от auto-fit, как управлять направлением переноса и какие ошибки ломают сетку. Если с CSS вы только знакомитесь, начните с материала о том, что такое CSS и как его применять.

CheckroiCheckroiПодборка курсов по CSS181 курс • 37 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Сетка с автопереносом за три строки

Рой раскладывает карточки ровными колонками на большом экране

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

<div class="cards">
  <div class="card">1</div>
  <div class="card">2</div>
  …
  <div class="card">8</div>
</div>
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

Что делает каждая часть правила:

  1. display: grid превращает контейнер в сетку, а дочерние блоки становятся её элементами.
  2. repeat(auto-fill, …) просит браузер повторить колонку столько раз, сколько поместится.
  3. minmax(200px, 1fr) задаёт размер колонки: не уже 200 пикселей и не шире равной доли свободного места.
  4. gap: 16px добавляет отступ между колонками и строками. Браузер учитывает его, когда считает, сколько колонок влезет.

Как одна и та же сетка из восьми карточек раскладывается при разной ширине контейнера:

Ширина контейнера Колонок Ширина колонки Строк
1000 px 4 238 px 2
700 px 3 около 222,7 px 3
400 px 1 400 px 8

Обратите внимание на последнюю строку. При ширине 400 пикселей две колонки по 200 уже не влезают, потому что между ними нужен ещё отступ в 16 пикселей. Поэтому сетка сразу схлопывается в одну колонку на всю ширину.

Подключить такие стили к странице можно любым из трёх способов, их мы разбирали в инструкции как подключить CSS к HTML.

Как браузер считает количество колонок

Правило описано в спецификации CSS Grid Layout. Если у контейнера известна ширина, браузер берёт наибольшее целое число повторов, при котором сетка вместе с отступами не вылезает за контейнер. Если не влезает даже одна колонка, остаётся одна.

На практике это простая проверка: N колонок × минимальная ширина + (N − 1) × gap ≤ ширина контейнера.

  • Контейнер 1000 px: четыре колонки дают 4 × 200 + 3 × 16 = 848 px, это влезает. Пять колонок дают 1064 px, это уже нет. Итог: 4.
  • Контейнер 700 px: три колонки дают 632 px, четыре дают 848 px. Итог: 3.
  • Контейнер 400 px: две колонки дают 416 px. Итог: 1.

Количество колонок решает минимум из minmax(). Максимум 1fr уже потом делит остаток поровну. В контейнере на 1000 пикселей после вычета трёх отступов остаётся 952, и каждая из четырёх колонок получает по 238.

Сетка с переносом определяется одной цифрой: минимальной шириной карточки. Подберите её по самому узкому состоянию, в котором карточка ещё читается, и колонки на всех экранах получатся сами.

Канал основателя Checkroi Вани Буявца3 800 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

auto-fill и auto-fit: в чём разница

Два ряда карточек: в одном пустая ячейка, в другом карточки растянуты

Пока карточек больше, чем помещается в строку, разницы между ключевыми словами нет. Она появляется, когда элементов мало, например в каталоге с тремя товарами на широком экране.

Возьмём контейнер 1000 px и всего три карточки:

Правило Что получится Ширина карточки
repeat(auto-fill, minmax(200px, 1fr)) создаются 4 колонки, четвёртая остаётся пустой 238 px
repeat(auto-fit, minmax(200px, 1fr)) пустая четвёртая колонка схлопывается в 0 около 322,7 px

Спецификация формулирует это так: auto-fit ведёт себя как auto-fill, но после размещения элементов пустые повторённые колонки схлопываются. Такая колонка получает размер 0 px, и отступы по обе стороны от неё тоже исчезают. Поэтому три карточки делят всю тысячу пикселей.

Какое ключевое слово выбрать:

  • auto-fill подходит для каталогов и галерей, где карточки должны выглядеть одинаково при любом количестве. Три товара встанут по ширине так же, как тридцать.
  • auto-fit подходит для блоков, которые должны занимать всю строку: тарифы, преимущества, два-три баннера рядом.

Если сомневаетесь, начните с auto-fill. Одинаковые карточки в каталоге почти всегда смотрятся аккуратнее растянутых.

Оба приёма относятся к адаптивной вёрстке, когда одна и та же страница подстраивается под любой экран. Какие ещё подходы к ней бывают, мы разбирали в материале о том, что такое вёрстка и какой она бывает.

Как ограничить число колонок сверху

У auto-fill нет потолка. На мониторе шириной 2560 пикселей сетка с минимумом 200 px выстроит десяток колонок, и карточки товаров превратятся в узкие полоски. Частая задача звучит так: переносить автоматически, но не больше трёх в ряд.

Для этого минимум колонки делают зависимым от ширины контейнера через функцию max():

.cards {
  --gap: 16px;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(
    auto-fill,
    minmax(max(200px, calc((100% - 2 * var(--gap)) / 3)), 1fr)
  );
}

Выражение calc((100% - 2 * var(--gap)) / 3) равно ширине одной колонки из трёх. Пока она больше 200 пикселей, минимум растёт вместе с контейнером, и четвёртая колонка не помещается. Когда контейнер сужается, срабатывает нижняя граница в 200 px, и сетка переходит на две колонки, а потом на одну.

Ширина контейнера Колонок Ширина колонки
1400 px 3 456 px
1000 px 3 около 322,7 px
600 px 2 292 px
300 px 1 300 px

Чтобы поменять потолок, замените тройку в делителе и двойку перед var(--gap): для четырёх колонок это (100% - 3 * var(--gap)) / 4. Количество отступов всегда на один меньше числа колонок.

Формулы с calc() и пользовательскими свойствами вроде --gap пригодятся не только в сетках. Если хотите освоить их вместе с остальной вёрсткой, посмотрите курсы по frontend-разработке.

Направление переноса: grid-auto-flow

Рой радуется, глядя как сетка сама перестраивается на телефоне и ноутбуке

По умолчанию сетка заполняется по строкам: слева направо, а когда строка кончилась, вниз на следующую. За это отвечает свойство grid-auto-flow, и у него три полезных значения.

row и column

Значение row стоит по умолчанию. Значение column переворачивает порядок: элементы идут сверху вниз, а когда колонка заполнилась, браузер создаёт следующую справа.

.list {
  display: grid;
  grid-template-rows: repeat(3, auto);
  grid-auto-flow: column;
}

Семь элементов в такой сетке встанут тремя колонками: 1, 2, 3 в первой, 4, 5, 6 во второй и 7 в третьей. Так удобно верстать длинные списки ссылок в подвале сайта, где читатель идёт глазами сверху вниз.

dense: заполнить дыры

Дыры в сетке появляются, когда широкий элемент не помещается в остаток строки. Пример: сетка из четырёх колонок, первая карточка занимает две, вторая три.

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.wide  { grid-column: span 2; }
.wider { grid-column: span 3; }
  • Без dense. Вторая карточка не влезает в две свободные колонки первой строки и уходит вниз. В первой строке остаётся дыра шириной в две колонки, а третья карточка встаёт справа от второй.
  • С grid-auto-flow: row dense. Браузер возвращается назад и ставит третью и четвёртую карточки в пустые ячейки первой строки.

У dense есть цена. Элементы на экране идут уже не в том порядке, что в разметке, а по спецификации экранные чтецы и переход по Tab по-прежнему идут по порядку в HTML. Для галереи фотографий это не страшно, для формы или пошаговой инструкции такое расхождение запутает пользователя.

Высота новых строк: grid-auto-rows

Строки, которые браузер дорисовывает сам при переносе, называются неявными. Их высоту задаёт grid-auto-rows:

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px;
  grid-auto-rows: 50px;
}

Здесь первая строка явная, высотой 100 пикселей. Все следующие, которые появятся от переноса, получат по 50 пикселей. Если нужно, чтобы строка росла под содержимое, но не была ниже заданной, пишите grid-auto-rows: minmax(120px, auto).

Сами карточки чаще всего делают обычными блоками, подробнее о них в материале про тег div в HTML.

Grid или flex-wrap для переноса

Перенос умеет и флексбокс: display: flex плюс flex-wrap: wrap. Разница видна в последней строке.

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.row > div { flex: 1 1 200px; }

Пять карточек в контейнере 1000 px: первые четыре встанут по 238 пикселей, а пятая уйдёт вниз одна и растянется на всю ширину, на 1000 пикселей. Флексбокс распределяет место внутри каждой строки отдельно, колонок у него нет. Сетка из первого раздела оставит пятую карточку шириной 238 пикселей под первой.

Если вы работали с Bootstrap, то уже видели флексбокс в деле: сетка Bootstrap 5 построена именно на нём, с двенадцатью колонками и классами под каждую ширину экрана. Как начать с этим фреймворком, рассказали в обзоре Bootstrap.

Задача Что взять
Каталог, галерея, карточки одной ширины Grid с auto-fill
Теги, кнопки, чипсы разной длины Flex с flex-wrap
Меню в одну строку, которое иногда переносится Flex с flex-wrap
Карточки должны стоять ровными колонками на любой строке Grid
CheckroiCheckroiПодборка курсов по Frontend-разработке107 курсов • 26 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→ Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 800 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

Частые ошибки и как их исправить

Правило не работает: repeat(auto-fill, 1fr)

Браузер считает такое значение недопустимым и просто пропускает свойство. Проверка CSS.supports('grid-template-columns', 'repeat(auto-fill, 1fr)') в консоли вернёт false. Причина в спецификации: автоповтору нужны определённые размеры, иначе число колонок не посчитать.

Решение: задайте минимум в пикселях, rem или процентах через minmax(200px, 1fr). По той же причине не сработает и minmax(1fr, 200px): значение во fr допустимо только как максимум.

Два автоповтора в одном правиле

Запись repeat(auto-fill, 100px) repeat(auto-fit, 100px) недопустима: auto-fill или auto-fit может стоять в списке колонок только один раз. Обычный repeat(3, 100px) рядом с ним использовать можно.

Горизонтальная прокрутка на телефоне

Если контейнер уже минимума колонки, колонка его не сожмёт. Карточка с минимумом 200 px в контейнере 150 px вылезет на 50 пикселей, и у страницы появится горизонтальная прокрутка.

Решение: ограничьте минимум шириной контейнера через функцию min().

grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr));

Теперь в контейнере 150 px колонка будет ровно 150 px, а на широких экранах всё работает как раньше.

Широкая карточка ломает узкую сетку

Допустим, первую карточку хочется сделать двойной: grid-column: span 2. На широком экране всё в порядке, она занимает две колонки из четырёх. А в контейнере 400 px, где колонка одна, браузер дорисует вторую колонку, чтобы карточке было куда растянуться. В нашем примере эта лишняя колонка вышла шириной 8 пикселей, и следующая карточка сплющилась в узкую полоску справа.

Решение: для блока на всю строку используйте grid-column: 1 / -1. Он растягивается от первой линии сетки до последней при любом числе колонок и лишних колонок не создаёт. Если карточка должна быть именно двойной, включайте span 2 только в медиа-запросе для экранов, где колонок гарантированно больше одной.

Справа остаётся пустая полоса

Так бывает при фиксированной ширине без 1fr: repeat(auto-fill, 200px). В контейнере 1000 px встанут четыре колонки по 200 px, вместе с отступами это 848 px, и справа останется полоса в 152 px.

Решение: верните максимум 1fr в minmax() или отцентруйте сетку через justify-content: center, если колонки должны остаться строго по 200 px.

Медиа-запросы на каждую ширину

Частая привычка после флоатов и Bootstrap: писать отдельный медиа-запрос под каждое число колонок. С auto-fill эти правила не нужны, сетка перестраивается сама. Медиа-запросы оставьте для того, что меняется по смыслу, например отступы, размер шрифта или порядок крупных блоков. Как их писать, рассказали в статье про медиа-запросы в CSS.

Где освоить CSS Grid системно

Сетка с автопереносом закрывает большую часть повседневной вёрстки, но в реальных проектах к ней добавляются области через grid-template-areas, вложенные сетки и связка с флексбоксом. Разобраться в этом быстрее на курсе с практикой и проверкой домашних заданий, чем по разрозненным примерам.

Тем, кто думает сделать её работой, пригодится разбор профессии HTML-верстальщика. Ниже подборка курсов по CSS из нашего каталога, все программы можно сравнить в разделе курсов по CSS.

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
HTML и CSS с нуля
Перейти на сайт курса
SkillboxSkillbox91 626 ₽7635 ₽/мес.11 месяцевОбзор курса
HTML и CSS. Адаптивная вёрстка и автоматизация
Перейти на сайт курса
HTMLAcademyHTML Academy23 400 ₽3900 ₽/мес.2 месяцаОбзор курса
Основы вёрстки HTML и CSS
Перейти на сайт курса
Академия СинергияАкадемия Синергия32 676 ₽2723 ₽/мес.3 месяцаОбзор курса
HTML и CSS с нуляSkyproSkypro195 160 ₽7972 ₽/мес.12 месяцевОбзор курса
Онлайн-курс Вёрстка на HTML и CSS
Перейти на сайт курса
БруноямБруноям36 900 ₽2491 ₽/мес.3 месяцаОбзор курса

Больше программ — в полном каталоге курсов по CSS

Часто задаваемые вопросы

Чем auto-fill отличается от auto-fit в CSS Grid?

Разница видна, только когда карточек меньше, чем помещается в строку. auto-fill оставляет пустые колонки, и карточки сохраняют ширину. auto-fit схлопывает пустые колонки в 0, и оставшиеся карточки растягиваются на всю строку: три карточки в контейнере 1000 px получат около 322,7 px вместо 238 px.

Почему не работает repeat(auto-fill, 1fr)?

Автоповтору нужен определённый размер колонки, иначе браузер не посчитает, сколько их поместится. Значение с одним 1fr недопустимо, и свойство пропускается. Задайте минимум через minmax(200px, 1fr).

Как сделать в CSS Grid не больше трёх колонок с автопереносом?

Сделайте минимум колонки зависимым от ширины контейнера: repeat(auto-fill, minmax(max(200px, calc((100% - 2 * var(--gap)) / 3)), 1fr)). На широком экране будет три колонки, на узком сетка перейдёт на две и одну.

Нужны ли медиа-запросы для адаптивной сетки на Grid?

Для числа колонок нет: repeat(auto-fill, minmax(…)) перестраивает сетку сам. Медиа-запросы оставьте для того, что меняется по смыслу, например отступов, размера шрифта или широкой карточки со span 2.

Что лучше для переноса элементов: Grid или flex-wrap?

Для карточек одной ширины лучше Grid: элементы последней строки встают в те же колонки. У flex-wrap одинокий элемент в последней строке растягивается на всю ширину, зато он удобен для тегов и кнопок разной длины.

Как убрать горизонтальную прокрутку у grid-сетки на телефоне?

Прокрутка появляется, когда контейнер уже минимума колонки. Ограничьте минимум функцией min(): minmax(min(200px, 100%), 1fr). Тогда в контейнере 150 px колонка займёт ровно 150 px.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!