Автоматическое изменение размера столбцов в CSS Grid: auto-fill против auto-fit

Автоматическое изменение размера столбцов в CSS Grid: auto-fill против auto-fit

От автора: в CSS Grid помимо явной установки размеров колонок есть еще одна из мощнейших функций – в Grid можно повторять колонки для заполнения контейнера и автоматически размещать в них элементы. В частности, мы можем указать количество столбцов в сетке, а затем браузер будет управлять адаптивностью этих колонок за нас. На маленьких экранах будет показываться меньше столбцов, а на больших – больше, так как экран позволяет вместить больше столбцов. Для этого даже не нужно писать медиа запросы.

Нам достаточно написать для этого всего одну строку CSS. Это напоминает мне момент из Гарри Поттера, когда Дамблдор взмахнул своей палочкой и «мебель разлетелась по местам; осколки безделушек мгновенно собрались вместе; перья вернулись в подушки; порванные книги починились и расставились по полкам…»

Магия без медиа запросов достигается с помощью функции repeat() и ключевых слов авторасстановки. Суммируем все. Функция repeat() позволяет повторять колонки нужно количество раз. Например, если нужно 12 колонок, можно написать следующий код:

.grid { display: grid; /* define the number of grid columns */ grid-template-columns: repeat(12, 1fr);
}

1fr указывает браузеру, что пространство между колонками нужно распределить равными частями, чтобы каждая колонка занимала одинаковое одну и ту же ширину. То есть все колонки резиновые и имеют одинаковую ширину. В нашем случае сетка всегда будет поддерживать 12 колонок, не смотря на ширину. Это не очень хорошо, как вы могли догадаться. Контент на маленьких экранах будет слишком сильно сжат.

Поэтому нам нужно добавить минимальную ширину для колонок, чтобы они не становились слишком узкими. Для этого подойдет функция minmax().

grid-template-columns: repeat( 12, minmax(250px, 1fr) );

Из-за принципа работы Grid это вызовет переполнение в строке. Колонки не будут перепрыгивать на новую строку, если ширина не позволяет вместить их все с минимальной шириной, ведь мы явно задали браузеру поддерживать 12 колонок в ряду.

Чтобы колонки перемещались на новый ряд, можно воспользоваться ключевыми словами auto-fit или auto-fill.

grid-template-columns: repeat( auto-fit, minmax(250px, 1fr) );

Эти ключевые слова подскажут браузеру, как нужно менять размер столбцов и перемещать их на новую строку. Если ширина не вмещает все колонки без перекрытия, часть колонок переместится на новую строку. Если в строку помещается только часть от всей ширины колонки, то это пространство будет распределено между всеми полностью вмещающимися колонками, а непоместившаяся колонка переедет на новую строку. Это спасает от ситуации, когда в конце строки остается пустое неиспользуемое пространство. А достигается такое поведение через единицы измерения fr.

На первый взгляд, судя по названиям, auto-fit и auto-fill выполняют противоположные задачи. Однако на самом деле разница между ними немного тоньше. Может показаться, что с auto-fit вы получите дополнительное пространство в конце ряда. Но когда и как? Давайте разбираться.

Fill или Fit? В чем разница?

В недавнем воркшопе по CSS я резюмировал различия между auto-fill и auto-fit:

auto-fill ЗАПОЛНЯЕТ строку максимально возможным количеством столбцов. Создается неявное количество столбцов при любой возможности их вместить, ведь задача этого значения в ЗАПОЛНЕНИИ строки максимальным количеством колонок. Новые колонки могут быть пусты, но они все равно будут занимать отведенное им место в строке. auto-fit ПОДГОНЯЕТ ТЕКУЩЕЕ КОЛЛИЧЕСТВО колонок под доступное пространство, расширяя их так, чтобы они заняли все доступное пространство. Браузер делает это после ЗАПОЛНЕНИЯ доступного пространства новыми колонками (как и auto-fill), после чего сжимает пустые столбцы.

Сначала вы можете не понять, как это работает. Но все прояснится после визуализации. Воспользуемся для визуализации Firefox DevTools Grid Inspector и посмотрим на размер и положение элементов сетки и колонок. В качестве примера возьмем следующее демо.

Колонки заданы через функцию repeat() и имеют минимальную ширину 100px, максимальная ширина указана 1fr. То есть колонки будут расширяться и равными долями занимать свободное место. Для ограничения количества колонок мы будем использовать наши ключевые слова для автоматического распределения. Позволим браузеру адаптировать сетку и переносить колонки на новые строки при необходимости.

В первом примере браузер будет подгонять размер и положение колонок через auto-fill. Во втором примере через auto-fit.

.grid-container--fill { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
} .grid-container--fit { grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}

До определенного момента auto-fill и auto-fit ведут себя одинаково.

Автоматическое изменение размера столбцов в CSS Grid: auto-fill против auto-fit

Но внутри они ведут себя по-разному. Одинаковый результат получился из-за точно выбранной ширины.

Наши два ключевых слова начинают вести себя по-разному в зависимости от количества и размера колонок, указанных в grid-template-columns. То есть результат в каждом примере будет разный.

Разница становится видна невооруженным глазом, когда ширина вьюпорта позволяет вместить одну или более колонки в ряд. В этот момент у браузера есть 2 пути. И выбранный путь сильно зависит от того, будет ли контент в новых добавленных колонках.

Что делает браузер, если в строку помещается еще одна колонка:

У меня есть лишнее место под еще одну колонку. В этой новой колонке будет контент (т.е. грид элементы)? Да? Тогда, все ок. Я добавлю эту колонку, а на маленьких экранах она будет перепрыгивать на новую строку.

Если в новой колонке не будет контента: «Я разрешаю новой колонке занимать место в строке (и тем самым влиять на положение и размер остальных столбцов)? Или же нужно сжать эту колонку, а ее ширину использовать для расширения уже имеющихся?

auto-fill и auto-fit отвечают на последний вопрос и говорят браузеру, как себя вести в такой ситуации. Сжимать или не сжимать, вот в чем вопрос. Это же и ответ. Сжимать или нет зависит от контента и того, как контент должен вести себя в контексте адаптивного дизайна.

Разберем, как это работает. Увидеть разницу между auto-fill и auto-fit можно на записях экрана ниже. Я изменяю размер вьюпорта по горизонтали так, чтобы хватило места для одной или более колонок. Не забывайте, что эти две строки идентичны, у них одинаковый контент и количество колонок. Различие одно – в первом демо я использую auto-fill, а во втором auto-fit.

Увидели? Если нет, посмотрите следующее видео.

Как работает auto-fill: «заполни весь ряд! Добавь как можно больше колонок. Мне неважно, пустые они или нет – они все равно должны быть. Если хватает места, добавь колонку. Мне неважно, пусть занимает место. Как если бы в новой колонке был контент или грид элементы.»

Auto-fill заполняет строку максимально возможным количеством колонок, даже если они пустые. Auto-fit ведут себя немного по-другому.

auto-fit делает то же самое – добавляет новые колонки в строке по мере расширения вьюпорта. Но новые колонки не сжаты. Это отлично видно в Grid inspector. Обратите внимание на количество строк в сетке, оно увеличивается по мере расширения вьюпорта. Также добавляются и новые колонки.

Как работает auto-fit: «Сделай так, чтобы все твои колонки поместились в отведенное пространство. Расширяй их насколько нужно для заполнения строки. Пустые колонки не должны занимать места. Лучше используй их ширину для расширения заполненных (контентом или грид элементами) колонок.»

Полезно помнить, что в обоих случаях (при сжатии или расширении) колонки добавляются неявно – в спецификации этому отведено отдельное значение. В нашем примере мы добавляем/создаем колонки в явно заданной сетке на 12 колонок. Поэтому для обозначения конца сетки можно использовать номер колонки -1, что не будет работать при неявной сетке. Спасибо Rachel Andrew за этот совет.

Резюмируем

Разница между auto-fill и auto-fit видна только, когда в строке есть место для новых колонок. С auto-fit контент будет растягиваться для заполнения всей ширины строки. auto-fill позволяет пустым колонкам занимать место в строке наравне со своими непустыми соседями. Для них будет отведено место даже, если внутри них нет грид элементов, что влияет на размер/ширину.

Какое поведение выбрать зависит от вас. Мне еще нужно придумать случай, когда auto-fill будет более подходящим чем auto-fit. Может, вы знаете такие примеры? Если да, делитесь ими в комментариях.

Автор: Sara Soueidan

Источник: css-tricks.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен