Узнайте о функциях сравнения CSS min()
, max()
и clip()
.
Функции сравнения CSS (min()
, max()
, clip()
) стали поддерживаться в Firefox 8 апреля 2020 года, что означает, что теперь они поддерживаются во всех основных браузерах. Эти функции CSS предоставят нам возможность иметь динамические макеты и более гибкие компоненты дизайна. Их можно использовать для размеров контейнера, размера шрифта, заполнения. и многое другое. Более того, веб-дизайнерам, возможно, придется думать по-другому при разработке макетов из-за этих захватывающих функций CSS.
В этой статье я постараюсь сделать их ясными, объясню все непонятные моменты, которые могут возникнуть, и предоставлю несколько практических примеров и вариантов использования.
Поддержка браузера
Первое, что я хочу выделить, это поддержка браузера, так как это новинка. Поддержка для min
и max
равна:
А вот поддержка для clip()
:
Функции сравнения CSS
Согласно спецификации CSS, все дело в сравнении нескольких значений и представлении одного из них на основе используемой функции. Давайте изучим функции.
Функция min()
Функция min()
содержит одно или несколько вычислений, разделенных запятыми, и представляет наименьшее из них. Мы используем min()
для установки максимального значения.
Рассмотрим следующий пример. Мы хотим, чтобы элемент имел максимальную ширину 500px
.
.element {
width: min(50%, 500px);
}
Браузер должен выбрать наименьшее из значений (50%
, 500px
). Выбор зависит от ширины области просмотра. Если 50%
вычисляет значение более 500px
, оно будет проигнорировано и вместо него будет использоваться 500px
.
В противном случае, если 50%
вычисляются до значения меньше 500px
, то 50%
будут использоваться в качестве значения ширины. Можете ли вы угадать ширину области просмотра, при которой это произойдет? (50% X = 500px
). Ширина области просмотра составляет 1000px
.
Я надеюсь, что вышеизложенный пункт ясен. Я много ломал голову, пытаясь понять, как это работает, поэтому мне нужно убедиться, что мое объяснение понятно. Для этого я сделал интерактивную демонстрацию, с которой можно поиграть:
Функция max()
Функция max()
содержит одно или несколько вычислений, разделенных запятыми, и представляет наибольшее из них. Мы используем max()
для установки минимального значения.
Рассмотрим следующий пример. Мы хотим, чтобы элемент имел минимальную ширину 500px
.
.element {
width: max(50%, 500px);
}
Браузер должен выбрать наибольшее из значений (50%, 500px
). Выбор зависит от ширины области просмотра. Если 50%
вычисляет значение меньше 500px
, оно будет проигнорировано и будет использоваться 500px
.
В противном случае, если 50%
вычисляются до значения, превышающего 500px
, то 50%
будут использоваться в качестве значения ширины. Это противоположность функции min()
.
Функция clip()
Что делает clip()
, так это то, что он зажимает значение между двумя определенными значениями, минимальным и максимальным. Он принимает три параметра (минимальное значение, предпочтительное значение, максимальное значение).
Рассмотрим следующий пример.
.element {
width: clamp(200px, 50%, 1000px);
}
У нас есть элемент с минимальной шириной 200px
, предпочтительным значением 50%
и максимальным значением 1000px
. Давайте визуализируем это!
Вот резюме для примера выше:
- Ширина никогда не будет меньше
200px
. - Центральное (предпочтительное) значение равно
50%
и будет работать, только если ширина области просмотра больше400px
и менее2000px
. - Ширина не превысит
1000px
.
clamp()
похож на имеющийся у нас физический инструмент. Он фиксирует значение на основе двух предоставленных значений по краям (min
, max
).
Посмотрите интерактивную демонстрацию.
Как рассчитывается clamp()?
Согласно Mozilla Developer Network (MDN), когда в качестве значения используется clip()
, это эквивалентно использованию функций max()
и min()
. Рассмотрим приведенный ниже пример:
.element {
width: clamp(200px, 50%, 1000px);
/* Эквивалентно приведенному ниже */
width: max(200px, min(50%, 1000px));
}
Значение 50%
зависит от ширины области просмотра браузера, предположим, что ширина области просмотра составляет 1150px
.
.element {
width: max(200px, min(50%, 1000px));
/* Предполагая, что ширина области просмотра составляет 1150px */
width: max(200px, min(575px, 1000px));
/* Решение */
width: max(200px, 575px);
/* Решение */
width: 575px;
}
Контекст имеет значение
Вычисленное значение зависит от контекста. Это может быть %
, em
, rem
, vw/vh
. Даже процентное значение может быть основано либо на ширине области просмотра, если элемент находится непосредственно в body
, либо на основе его родителя.
Математические выражения
Стоит отметить, что доступны математические вычисления, поэтому нет необходимости использовать calc()
. Согласно спецификации:
Полные математические выражения разрешены в каждом из аргументов; нет необходимости вкладывать внутрь calc()
! Вы также можете указать более двух аргументов, если у вас есть несколько ограничений для применения.
Рассмотрим следующий пример.
.type {
/* Заставьте размер шрифта оставаться между 12 и 100px */
font-size: clamp(12px, 10 * (1vw + 1vh) / 2, 100px);
}
Какие функции сравнения CSS изменятся в нашем дизайне?
Часто при разработке веб-страницы дизайнер работает с мобильными и настольными размерами, а для некоторых проектов это может быть больше. Каков эффект от наличия функций сравнения сегодня?
Для меня я вижу это как иллюстрацию ниже.
Первый показывает текущий способ проектирования, есть четкие места для размеров дизайна или видовых экранов. Однако второй является постепенным, что указывает на использование минимального и максимального значения для проектного свойства. Я предполагаю, что дизайнеры в будущем будут делать что-то вроде этого:
Разве это не захватывающе? Для меня это! Я очень рад работать над веб-проектами, которые требуют определенной гибкости в своих компонентах. Конечно, не все компоненты должны быть динамическими, но некоторые из них могут быть такими.
Случаи применения
Боковая панель и основная
Обычно боковая панель страницы имеет фиксированную ширину, а основная ширина может изменяться. Мы можем улучшить боковую панель, сделать ее более динамичной и занимать больше места, если область просмотра достаточно велика. Для этого мне нужно установить для него минимальную ширину с помощью функции max()
.
Рассмотрим приведенный ниже пример.
.wrapper {
display: flex;
}
aside {
flex-basis: max(30vw, 150px);
}
main {
flex-grow: 1;
}
Минимальная ширина стороны составляет 150px
, и она будет равна 30vw
, если ширина области просмотра больше 500px
(500 * 30% = 150).
Размер шрифта заголовков
Отличный вариант использования clip()
для заголовков. Предположим, вам нужен заголовок с минимальным размером 16px
и максимальным размером 50px
. Функция clip()
даст нам промежуточное значение, не опускаясь ниже или выше минимума и максимума соответственно.
.title {
font-size: clamp(16px, 5vw, 50px);
}
Использование clip()
здесь идеально, потому что это гарантирует, что используемый размер шрифта доступен и легко читается. Если вы будете использовать min()
для установки максимального размера шрифта, то вы не сможете управлять шрифтом на маленьких окнах просмотра.
.title {
font-size: min(3vw, 24px); /* Не рекомендуется, плохо для доступности */
}
См. рисунок ниже для наглядного пояснения.
На мобильном экране размер шрифта крошечный. По этой причине не используйте функцию min()
только для размера шрифта. Конечно, вы можете отменить или добавить его с помощью медиа-запроса, но тогда вы упустите весь смысл использования функций сравнения CSS.
Как я упоминал ранее, вы можете вложить min()
внутрь функции max()
, которая будет имитировать функцию clip()
. Смотри ниже:
.title {
font-size: max(16px, min(10vw, 50px));
}
После обсуждения в Твиттере выяснилось, что использовать только 10vw
в качестве предпочтительного значения размера шрифта не очень хорошо. Это вызовет проблему доступности, когда пользователь увеличит масштаб браузера.
.title {
font-size: clamp(16px, (1rem + 5vw), 50px);
}
В приведенном выше примере я добавил выражение (1rem + 5vw
), которое решит проблему.
Декоративные заголовки
Видите тот большой прозрачный текст под заголовком раздела? Это декоративный текст, который должен масштабироваться в зависимости от размера области просмотра. Мы можем использовать функцию max()
с единицами измерения окна просмотра CSS, чтобы установить для нее минимальное значение.
.section-title:before {
content: attr(data-test);
font-size: max(13vw, 50px);
}
Сглаживание градиентов
При использовании градиента в CSS вам может потребоваться немного изменить его для мобильных устройств, сделав переход между цветами немного более плавным. Позвольте мне показать вам пример. У нас есть следующий градиент:
Обратите внимание, как виден переход в мобильной версии и есть линия, разделяющая цвета, что не очень хорошо. Мы можем исправить это, используя старый добрый медиа-запрос (О, я только что сказал, что медиа-запрос — это «старая добрая» штука?).
@media (max-width: 700px) {
.element {
background: linear-gradient(135deg, #2c3e50, #2c3e50 25%, #3498db);
}
}
Пока это работает, мы можем использовать функцию CSS min()
, чтобы сделать это более динамичным. См. ниже:
.element {
background: linear-gradient(135deg, #2c3e50, #2c3e50 min(20vw, 60%), #3498db);
}
Прозрачный градиент
Когда вам нужно поместить текст поверх фотографии, у вас должен быть градиент под ним, чтобы сделать текст читабельным. Как и в предыдущем примере, размер градиента должен варьироваться между маленькими и большими окнами просмотра. См. рисунок ниже:
.element {
background: linear-gradient(to top, #000 0, transparent max(20%, 20vw));
}
Это небольшое улучшение может сделать градиент более логичным на мобильных устройствах. Если размер градиента составляет 50%
от его родителя на десктопе, для мобильных устройств он должен составлять около 30%
. Используя функцию max()
, мы можем установить для нее минимальное значение.
Динамическое расстояние
У нас может быть динамическое расстояние между элементами дизайна с помощью единиц измерения окна просмотра CSS. Однако это не всегда может быть хорошим решением, поскольку пользователь может просматривать дизайн на повернутом экране с большой высотой по вертикали. Вот как мы делаем это с помощью медиа-запросов:
h1,
h2,
h3,
h4,
h5 {
margin: 7vh 0 1.05rem;
}
@media (max-height: 2000px) {
h1,
h2,
h3,
h4,
h5 {
margin: 2.75rem 0 1.05rem;
}
}
Хотя приведенное выше решение работает, мы можем сделать то же самое только с одной строкой кода!
h1,
h2,
h3,
h4,
h5 {
margin: min(7vh, 2.75rem) 0 1.05rem;
}
Используя min()
, мы устанавливаем максимальное значение маржи 2,75rem
, которое не должно быть превышено. Просто и легко!
Ширина контейнера
Если у вас есть контейнер, который должен занимать 80%
ширины своего родителя, а ширина не должна превышать 780px
, что использовать? Обычно это может быть что-то вроде этого:
.container {
max-width: 780px;
width: 80%;
}
Однако с помощью функции min()
можно установить максимальное значение следующим образом:
.container {
max-width: min(80%, 780px);
}
Section - Вертикальное заполнение
Что мне понравилось в clip()
, так это то, что он идеально подходит для установки минимального и максимального отступов для раздела. Рассмотрим пример ниже, где у нас есть раздел героя.
С помощью одной строки CSS мы можем добиться упомянутой выше гибкости.
.hero {
padding: clamp(2rem, 10vmax, 10rem) 1rem;
}
Смотрите интерактивную демонстрацию.
Граница и тень
Для некоторых случаев дизайна есть элементы с большой шириной и радиусом границы, которые должны быть меньше на мобильных устройствах. Используя clip()
, мы можем сделать их динамическими в соответствии с шириной области просмотра.
.element {
box-shadow: 0 3px 10px 0 red;
border: min(1vw, 10px) solid #468eef;
border-radius: clamp(7px, 2vw, 20px);
box-shadow: 0 3px clamp(5px, 4vw, 50px) 0 rgba(0, 0, 0, 0.2);
}
Зазор сетки
Прекрасный пример использования — это когда у нас есть grid-gap
с использованием сетки CSS, и мы хотим уменьшить его для мобильных окон просмотра. С clip()
это довольно просто.
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: clamp(1rem, 2vw, 24px);
}
Если вы хотите больше узнать о сетке и функциях сравнения, вот отличная статья Дэнни Винтера.
Функция сравнения CSS не работает с безразмерными значениями
Я пытался что-то сделать и хотел установить 0
в качестве минимального значения для clip()
. См. приведенный ниже CSS:
.element {
width: clamp(0, 10vmax, 10rem);
}
Этот CSS недействителен, так как кажется, что безразмерные числа не должны использоваться там.
Как добавить резервный вариант для неподдерживающих браузеров!
Как и в случае с любой новой функцией CSS, важно обеспечить запасной вариант. Для этого мы можем использовать одно из следующих действий:
Добавьте запасной вариант вручную
Это означает, что мы должны обеспечить запасной вариант, добавив свойство перед сравнением CSS. См. пример ниже:
.hero {
padding: 4rem 1rem;
padding: clamp(2rem, 10vmax, 10rem) 1rem;
}
Поддерживающие браузеры будут игнорировать первый. В то время как неподдерживающие будут использовать первое заполнение.
Использование CSS @supports
Мы можем использовать запрос функции @supports
, чтобы определить, поддерживаются ли функции сравнения CSS. Я предпочитаю это в ручном решении, потому что любой браузер, поддерживающий функции сравнения, должен поддерживать запрос функции @supports
.
.hero {
/* По умолчанию, для неподдерживающих браузеров */
padding: 4rem 1rem;
}
@supports (width: min(10px, 5vw)) {
/* Улучшение для поддержки браузеров */
.hero {
padding: clamp(2rem, 10vmax, 10rem) 1rem;
}
}
Проблемы доступности
Хотя функции сравнения CSS предоставляют нам новый способ создания более динамичных веб-страниц, нам нужно быть более осторожными в том, как их использовать. Например, использования min()
для установки размера шрифта недостаточно, так как он будет слишком мал для мобильных устройств. Вы должны установить минимальные и максимальные значения для вещей, которые жизненно важны для взаимодействия с пользователем.
Надеюсь Вам понравилась статья!