CSS-live.ru

Как работает функция 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() — обычная длина. Возьмем, например, этот простой грид, с тремя колонками и одним рядом.

grid-

С помощью функции minmax() мы можем указать, что желтая грид-ячейка остается в пределах от 100px до 200px. При изменении размеров окна абсолютное значение будет меняться, но всегда между этими границами.

.grid {
    display: grid;
    grid-template-columns: minmax(100px, 200px) 1fr 1fr;
}

grid-

Вторая и третья колонки сжимаются и расширяются до заполнения оставшегося свободного места поровну, но первая всегда остается шириной от 100px до 200px.

Проценты

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

.grid {
    display: grid;
    grid-template-columns: minmax(200px, 50%) 1fr 1fr;
}

grid-

Как бы мы не сужали окно браузера, желтая ячейка никогда не станет меньше 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;
}

grid-

Поскольку при больших размерах окна ширина всех колонок 1fr, они делят пространство в гриде поровну.

max-content

Ключевое слово max-content — специальное значение, представляющее собой «идеальный размер» ячейки. Это наименьший возможный размер ячейки, при котором содержимое умещается в ней свободно. Например, если содержимое ячейки — предложение текста, идеальной шириной ячейки будет полная длина этого предложения, если записать его в одну строку без переносов.

Если взять наш предыдущий пример, давайте укажем для желтой грид-ячейки и минимальный, и максимальный размер, равный max-content.

.grid {
    display: grid;
    grid-template-columns: minmax(max-content, max-content) 1fr 1fr;
}

grid-

Как видно, колонка растягивается в ширину, чтобы вместить всю длину строки. Поскольку и максимальному, и минимальному значениям указано 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;
}

grid-

Видно, что содержимое ячейки переносится так, чтобы занимать как можно меньше места по горизонтали, не вызывая переполнения.

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;
}

grid-

Использование функции minmax(): отзывчивый дизайн без медиавыражений

Как мы видели, использование функции minmax() подходит в нескольких случаях, и ее можно использовать несколькими способами. Но, наверное, самое популярное и полезное применение функции minmax() — возможность создавать отзывчивые макеты без помощи каких-либо медиавыражений.

Возьмем для примера такой грид:

grid-

У каждой колонки в гриде минимальная ширина 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. Это тоже может быть интересно:

7 комментариев

  1. Подскажите, пожалуйста, как заставить работать последний пример с отзывчивым дизайном без медиазапросов. Не происходит переноса по строкам, а лишь сам грид расширяется в стороны
    > надо в grid-templates-areas указывать как множество столбцов? тогда получается 1 строчка и не происходит переноса на другие rows

    > grid-templates-rows: auto?

    1. Я верно понимаю, что вопрос про пример с auto-fit? Обычно auto-fit/auto-fill используются в связке с автоматическим размещением элементов (как здесь). Ряды при этом создаются автоматически, ими можно управлять через grid-auto-rows (а не grid-template-rows). С явной привязкой к grid-templates-areas в общем случае это подружить трудно, но можно, например, задавать правила типа «элемент растягивается на все колонки, кроме последней» (grid-column: 1 / -2;). Но вообще надо смотреть конкретную задачу — может, найдется решение еще проще и эффективнее.

      P.S. С именинами, тёзка! :)

  2. Спасибо, взаимно)
    Да, пытался как-то прикрутить grid-templates-areas, убрав это свойство — всё заработало

  3. SelenIT!!! СПАСИБО ЗА ВАШИ ТРУДЫ . прекрасный сайт, отдельно спасибо за размер шрифта. класная инфа и ее подача без заморочек…

  4. Подскажите, пожалуйста:

    Последний пример разве не бессмысленный, если колон

    ки могут объединяться в одну только при отсутствии контента в остальных колонках, кроме первой?

    Именно поэтому последний Ваш пример приведен без текстового контента.

    Следовательно вопрос: А существуют ли способы объединения колонок именно с контентом, ну что бы правая колонка, как есть подскакивала (подстраивалась) под первую автоматически без медиа запросов при изменении окна браузера?

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

    1. Нашел ответ, догадался, с помощью ul li. Содержимое ячеек-колонок обернуть в li, и каждая правая колонка уходит под левую соседку, становясь строкой.

      #block-main > ul { display: grid;
      grid-area: block-main;

      grid-template-columns: repeat(auto-fit, minmax([значение]px, 1fr)); — вот так это заработало у меня.

      Без ul li чего только не перепробовал, никак.

      1. И еще: На моб устройствах, по крайней мере на не больших смартфонах, эта отзывчивость без медиа работает только при:

        <meta name=»viewport» content=»width=device-width, initial-scale=0, maximum-scale=0″>

        При scale=1 у меня уже не работало, одинаково, что при одном положении телефона, что при другом, меняется только общий размер всего.

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.