Как работает функция minmax()
Перевод статьи How the minmax()
Function Works с сайта bitsofco.de, опубликовано на css-live.ru с разрешения автора — Ире Адеринокун.
Одна из невероятно полезных новинок спецификации CSS Grid Layout — функция minmax()
. Эта функция открывает нам возможность писать более мощный и лаконичный CSS, позволяя задавать в качестве значения для грид-полосы функцию, включающую и минимальное, и максимальное значения.
Функция minmax()
Функция minmax()
принимает два параметра, минимальное значение и максимальное.
minmax(min, max)
Если указанное максимальное значение окажется меньше минимального, оно игнорируется, и функция воспринимается как представляющая только минимальное значение.
Функция minmax()
принимает 6 типов значений:
- Единицы длины
- Проценты
- Гибкие размеры
max-content
min-content
auto
Рассмотрим примеры каждого из них.
Длина
Наверное, самое простое значение, что мы можем использовать с функцией minmax()
— обычная длина. Возьмем, например, этот простой грид, с тремя колонками и одним рядом.
С помощью функции minmax()
мы можем указать, что желтая грид-ячейка остается в пределах от 100px
до 200px
. При изменении размеров окна абсолютное значение будет меняться, но всегда между этими границами.
.grid { display: grid; grid-template-columns: minmax(100px, 200px) 1fr 1fr; }
Вторая и третья колонки сжимаются и расширяются до заполнения оставшегося свободного места поровну, но первая всегда остается шириной от 100px
до 200px
.
Проценты
Помимо обычных единиц длины, с функцией minmax()
можно использовать и проценты. Допустим, к примеру, что мы захотели, чтобы желтая грид-ячейка занимала максимум 50% грида, но не ужималась меньше 200px.
.grid { display: grid; grid-template-columns: minmax(200px, 50%) 1fr 1fr; }
Как бы мы не сужали окно браузера, желтая ячейка никогда не станет меньше 200px. Но когда место есть, она растягивается до максимума в половину ширины грида.
Гибкие размеры
Гибкие размеры — новая единица, тоже введенная спецификацией CSS Grid Layout, как и функция minmax()
. Эта величина, для которой используется единица fr
, представляет собой долю свободного пространства в грид-контейнере. Например, скажем, у нас есть грид шириной 100px
с двумя колонками. У одной колонки фиксированная ширина 20px
, а у другой ширина 1fr
. У второй колонки фактически будет ширина 80px
, поскольку она занимает всё оставшееся свободное место в гриде.
На данный момент единица fr
может использоваться только для максимального значения в функции minmax()
(хотя в спецификации отмечено, что в будущем может появиться возможность применять ее и для минимального значения). Возвращаясь к нашему примеру, можно указать, что наша желтая ячейка должна быть шириной минимум 200px. Если окно браузера станет шире этого, эта ячейка должна быть размером 1fr
, т.е. равна двум другим колонкам.
.grid { display: grid; grid-template-columns: minmax(200px, 1fr) 1fr 1fr; }
Поскольку при больших размерах окна ширина всех колонок 1fr, они делят пространство в гриде поровну.
max-content
Ключевое слово max-content
— специальное значение, представляющее собой «идеальный размер» ячейки. Это наименьший возможный размер ячейки, при котором содержимое умещается в ней свободно. Например, если содержимое ячейки — предложение текста, идеальной шириной ячейки будет полная длина этого предложения, если записать его в одну строку без переносов.
Если взять наш предыдущий пример, давайте укажем для желтой грид-ячейки и минимальный, и максимальный размер, равный max-content
.
.grid { display: grid; grid-template-columns: minmax(max-content, max-content) 1fr 1fr; }
Как видно, колонка растягивается в ширину, чтобы вместить всю длину строки. Поскольку и максимальному, и минимальному значениям указано max-content
, ширина колонки остается постоянной (прим. перев.: того же эффекта можно было бы добиться и без minmax
, указав просто grid-template-columns: max-content 1fr 1fr
).
min-content
Ключевое слово min-content
, как и max-content
— особое значение. Оно представляет собой наименьший возможный размер, при котором в ячейке еще не возникает переполнения, если этого переполнения можно хоть как-то избежать.
Чтобы показать различие между min-content
и max-content
, можно взять содержимое из предыдущего примера, но в оба значения для функции minmax()
подставить min-content
.
.grid { display: grid; grid-template-columns: minmax(min-content, min-content) 1fr 1fr; }
Видно, что содержимое ячейки переносится так, чтобы занимать как можно меньше места по горизонтали, не вызывая переполнения.
auto
Наконец, у нас есть auto
. В зависимости от того, используется оно как максимальное или минимальное значение в функции minmax()
, его смысл меняется.
Если значение auto
используется в качестве максимума, оно эквивалентно значению max-content
. А если в качестве минимума, то значение auto представляет собой наибольший минимальный размер для ячейки. Этот «наибольший минимальный размер» отличается от значения min-content
и задается свойствами min-width/min-height
.
В качестве иллюстрации — вот что происходит, если задать желтой грид-ячейке в нашем примере auto для минимума и максимума.
.grid { display: grid; grid-template-columns: minmax(auto, auto) 1fr 1fr; }
Использование функции minmax()
: отзывчивый дизайн без медиавыражений
Как мы видели, использование функции minmax()
подходит в нескольких случаях, и ее можно использовать несколькими способами. Но, наверное, самое популярное и полезное применение функции minmax()
— возможность создавать отзывчивые макеты без помощи каких-либо медиавыражений.
Возьмем для примера такой грид:
У каждой колонки в гриде минимальная ширина 200px. При изменении размеров окна браузера число колонок меняется, чтобы вместить их идеальную ширину. С помощью CSS-гридов и функции minmax()
это делается всего лишь 2 строчками CSS:
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
Помимо функции minmax()
, здесь еще два ключевых момента:
repeat()
: эта функция позволяет нам указывать одно и то же значение для нескольких колонок в гриде. Она принимает два значения: количество повторений и значение, которое надо повторить.auto-fit
: это ключевое слово можно использовать с функциейrepeat()
вместо количества повторений. Оно гибко меняет используемое число колонок в зависимости от ширины каждой из них.
Правда, одно, на мой взгляд серьезное, ограничение этого приема — то, что это работает только при равной ширине всех колонок. Мы вынуждены пользоваться функцией repeat()
с ключевым словом auto-fit
, так как это дает возможность сделать число колонок гибким. Но всё же и это может быть крайне полезным решением в подходящих обстоятельствах.
P.S. Это тоже может быть интересно:
Подскажите, пожалуйста, как заставить работать последний пример с отзывчивым дизайном без медиазапросов. Не происходит переноса по строкам, а лишь сам грид расширяется в стороны
> надо в grid-templates-areas указывать как множество столбцов? тогда получается 1 строчка и не происходит переноса на другие rows
> grid-templates-rows: auto?
Я верно понимаю, что вопрос про пример с auto-fit? Обычно auto-fit/auto-fill используются в связке с автоматическим размещением элементов (как здесь). Ряды при этом создаются автоматически, ими можно управлять через grid-auto-rows (а не grid-template-rows). С явной привязкой к grid-templates-areas в общем случае это подружить трудно, но можно, например, задавать правила типа «элемент растягивается на все колонки, кроме последней» (grid-column: 1 / -2;). Но вообще надо смотреть конкретную задачу — может, найдется решение еще проще и эффективнее.
P.S. С именинами, тёзка! :)
Спасибо, взаимно)
Да, пытался как-то прикрутить grid-templates-areas, убрав это свойство — всё заработало
SelenIT!!! СПАСИБО ЗА ВАШИ ТРУДЫ . прекрасный сайт, отдельно спасибо за размер шрифта. класная инфа и ее подача без заморочек…
Подскажите, пожалуйста:
Последний пример разве не бессмысленный, если колон
ки могут объединяться в одну только при отсутствии контента в остальных колонках, кроме первой?
Именно поэтому последний Ваш пример приведен без текстового контента.
Следовательно вопрос: А существуют ли способы объединения колонок именно с контентом, ну что бы правая колонка, как есть подскакивала (подстраивалась) под первую автоматически без медиа запросов при изменении окна браузера?
Конечно с медиа это делается как надо, но все же, грид разрекламирован как все могущий. Именно для адаптивности в первую очередь он придуман, ну помимо удобства, а про смешивания объединения контента, ну хотя бы текста, никакой информации нигде не нашел.
Нашел ответ, догадался, с помощью ul li. Содержимое ячеек-колонок обернуть в li, и каждая правая колонка уходит под левую соседку, становясь строкой.
#block-main > ul { display: grid;
grid-area: block-main;
grid-template-columns: repeat(auto-fit, minmax([значение]px, 1fr)); — вот так это заработало у меня.
Без ul li чего только не перепробовал, никак.
И еще: На моб устройствах, по крайней мере на не больших смартфонах, эта отзывчивость без медиа работает только при:
<meta name=»viewport» content=»width=device-width, initial-scale=0, maximum-scale=0″>
При scale=1 у меня уже не работало, одинаково, что при одном положении телефона, что при другом, меняется только общий размер всего.