Естественно адаптивная сетка CSS с помощью minmax() и min()

Естественно адаптивная сетка CSS с помощью minmax() и min()

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

Естественно адаптивная сетка CSS с помощью minmax() и min()

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

Этот метод использует ряд функций спецификации Grid:

repeat() указывает Grid создать несколько треков с одинаковыми параметрами размера (необязательно одинакового размера, хотя в этом случае все они в конечном итоге будут одинаковыми).

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

minmax(10rem, 1fr) указывает определить размер каждого трека, найдя значение от минимума в 10rem до максимума 1fr. Единицы fr обеспечивают то, чтобы трек мог растягиваться и заполнять любое оставшееся пространство.

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

Адаптивный … ну, вроде того

Естественно адаптивная сетка CSS с помощью minmax() и min()

Поскольку каждый трек сетки имеет минимальный размер 10rem, они не могут сжиматься меньше этого размера. Это означает, что когда контейнер меньше чем 10rem, элементы сетки переполняют контейнер! Чтобы это исправить, нам нужно обернуть объявление grid-template-columns в медиа-запрос, например, так:

Но теперь, когда мы находимся в области медиа-запроса, наша сетка переключается только тогда, когда область просмотра мала. Мы не можем поместить его в небольшой контейнер, или мы снова сталкиваемся с проблемой переполнения. Вот почему на сайте Хейдона Пикеринга и Энди Белла Every Layout в целом не используются медиа-запросы и CSS Grid, а вместо этого естественная адаптивность достигается через Flexbox.

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

Естественно адаптивная сетка

В предыдущем примере у нас возникли проблемы, поскольку мы устанавливали фиксированное значение в качестве минимального размера дорожки. Когда размер контейнера уменьшался, элементы не уменьшились вместе с ним, и, следовательно, переполняли контейнер. Но что, если бы мы могли установить минимальный размер, который уменьшался бы в зависимости от размера контейнера, гарантируя, что наши треки никогда не будут слишком большими для контейнера?

К счастью, мы можем сделать это с помощью функции min():

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

min() принимает одно или несколько значений и возвращает наименьшее из них. Магия функции заключается в том, что, как и у функции calc(), аргументы могут использовать разные единицы измерения, что позволяет нам возвращать значения, которые динамически изменяются в зависимости от контекста. В этом случае мы возвращаем текущую ширину контейнера с максимальным значением 10rem.

Естественно адаптивная сетка CSS с помощью minmax() и min()

min() является одной из трех новых функций сравнения, представленных как часть модуля «Значения и единицы измерения CSS» уровня 4. В нем также вводится max(), которая, естественно, делает обратное min(). И, наконец, clamp(), это удобная функция, которая применяет минимум и максимум к одному значению.

В этом примере есть два случая, о которых нам нужно позаботиться, и min() является решением для обоих. Когда контейнер меньше чем 10rem, минимальное значение в нашем выражении minmax() устанавливается равным полной ширине контейнера, что дает нам нормальное представление с одним столбцом без переполнения. Когда контейнер больше чем 10rem, устанавливается минимальное значение 10rem, поэтому мы получаем адаптивную сетку с равными треками, по крайней мере, 10rem для каждого.

В реальном мире

Я знаю, о чем вы подумали. «Это звучит круто и все такое, но я пока не могу это использовать». Вы только наполовину правы.

min() не очень хорошо поддерживается, но оно доступно, по крайней мере, в одном браузере: Safari реализовали как min(), так и max() несколько версий назад! К сожалению, clamp() пока нет, но вы можете смоделировать его с помощью двух других. Кроме того, Tеб Аткинс недавно объявил о поддержке в Chrome. Если вы хотите отслеживать поддержку браузерами, на CanIUse есть страница для всех трех функций.

После всех этих хороших новостей, вот рабочая версия кода выше (откройте в Safari, чтобы увидеть его в действии):

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

Здесь в качестве запасного варианта используется выражение calc(). Ключевой частью является комбинация фиксированного минимума с процентной шириной calc(10% + 7.5rem). Вычисляя минимум на основе этих двух факторов, мы снижаем порог срабатывания переполнения. Теперь он будет срабатывать, когда контейнер немного больше, чем 7.5rem, тогда как в предыдущем решении он срабатывал при 10rem. Однако это решение несколько сложнее, поэтому вам нужно будет отрегулировать как процентные, так и фиксированные значения в соответствии с дизайном сетки.

Благодаря этому в качестве запасного варианта мы можем воспользоваться возможностью CSS переопределять дубликаты объявлений свойств путем повторного объявления grid-template-columns. Браузеры с поддержкой min(), а именно Safari, получат полностью адаптивное решение, в то время как Chrome, Firefox, Edge и другие получат запасной вариант. Поскольку все больше браузеров добавляют поддержку min(), они автоматически переключатся на новый макет.

Завершение

Функции min(), max() и clamp() являются действительно мощными инструментами, позволяющими нам переключаться между значениями в режиме реального времени в зависимости от меняющихся условий. Возможность протестировать их в реальном браузере открывает множество возможностей для исследования, и я уверен, что это небольшое исправление для CSS Grid открывает большие возможности относительно того, как разработчики будут использовать эти функции в будущем.

Автор: Evan Minto

Источник: https://evanminto.com

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