min(), max() и clip() CSS-функции

Узнайте о функциях сравнения CSS min(), max() и clip().

Функции сравнения CSS (min(), max(), clip()) стали поддерживаться в Firefox 8 апреля 2020 года, что означает, что теперь они поддерживаются во всех основных браузерах. Эти функции CSS предоставят нам возможность иметь динамические макеты и более гибкие компоненты дизайна. Их можно использовать для размеров контейнера, размера шрифта, заполнения. и многое другое. Более того, веб-дизайнерам, возможно, придется думать по-другому при разработке макетов из-за этих захватывающих функций CSS.

В этой статье я постараюсь сделать их ясными, объясню все непонятные моменты, которые могут возникнуть, и предоставлю несколько практических примеров и вариантов использования.

   

Поддержка браузера

Первое, что я хочу выделить, это поддержка браузера, так как это новинка. Поддержка для min и max равна:

CSS-функции

А вот поддержка для clip():

CSS-функции

   

Функции сравнения CSS

Согласно спецификации CSS, все дело в сравнении нескольких значений и представлении одного из них на основе используемой функции. Давайте изучим функции.

   

Функция min()

Функция min() содержит одно или несколько вычислений, разделенных запятыми, и представляет наименьшее из них. Мы используем min() для установки максимального значения.

Рассмотрим следующий пример. Мы хотим, чтобы элемент имел максимальную ширину 500px.


.element {
  width: min(50%, 500px);
}

CSS-функции min()

Браузер должен выбрать наименьшее из значений (50%, 500px). Выбор зависит от ширины области просмотра. Если 50% вычисляет значение более 500px, оно будет проигнорировано и вместо него будет использоваться 500px.

В противном случае, если 50% вычисляются до значения меньше 500px, то 50% будут использоваться в качестве значения ширины. Можете ли вы угадать ширину области просмотра, при которой это произойдет? (50% X = 500px). Ширина области просмотра составляет 1000px.

CSS-функции min()

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

  

Функция max()

Функция max() содержит одно или несколько вычислений, разделенных запятыми, и представляет наибольшее из них. Мы используем max() для установки минимального значения.

Рассмотрим следующий пример. Мы хотим, чтобы элемент имел минимальную ширину 500px.


.element {
  width: max(50%, 500px);
}

CSS-функции max()

Браузер должен выбрать наибольшее из значений (50%, 500px). Выбор зависит от ширины области просмотра. Если 50% вычисляет значение меньше 500px, оно будет проигнорировано и будет использоваться 500px.

В противном случае, если 50% вычисляются до значения, превышающего 500px, то 50% будут использоваться в качестве значения ширины. Это противоположность функции min().

  

Функция clip()

Что делает clip(), так это то, что он зажимает значение между двумя определенными значениями, минимальным и максимальным. Он принимает три параметра (минимальное значение, предпочтительное значение, максимальное значение).

Рассмотрим следующий пример.


.element {
  width: clamp(200px, 50%, 1000px);
}

У нас есть элемент с минимальной шириной 200px, предпочтительным значением 50% и максимальным значением 1000px. Давайте визуализируем это!

CSS-функции max()

Вот резюме для примера выше:

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 изменятся в нашем дизайне?

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

Для меня я вижу это как иллюстрацию ниже.

CSS-функции

Первый показывает текущий способ проектирования, есть четкие места для размеров дизайна или видовых экранов. Однако второй является постепенным, что указывает на использование минимального и максимального значения для проектного свойства. Я предполагаю, что дизайнеры в будущем будут делать что-то вроде этого:

CSS-функции

Разве это не захватывающе? Для меня это! Я очень рад работать над веб-проектами, которые требуют определенной гибкости в своих компонентах. Конечно, не все компоненты должны быть динамическими, но некоторые из них могут быть такими.

  

Случаи применения

Боковая панель и основная

Боковая панель и основная

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

Рассмотрим приведенный ниже пример.


.wrapper {
  display: flex;
}

aside {
  flex-basis: max(30vw, 150px);
}

main {
  flex-grow: 1;
}

Минимальная ширина стороны составляет 150px, и она будет равна 30vw, если ширина области просмотра больше 500px (500 * 30% = 150).

Демо - codepen.io/shadeed/pen/mdeqWNM/7f9558f31fdf60bc08c827817c10bf3a?editors=1100

  

Размер шрифта заголовков

Размер шрифта заголовков

Отличный вариант использования 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);
}

Демо - codepen.io/shadeed/pen/oNjodgR/e0128b73de7c84cb9b98cf733a3835c4?editors=1100

  

Сглаживание градиентов

При использовании градиента в 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);
}

Сглаживание градиентов

Демо - codepen.io/shadeed/pen/VwvyvJN/2c4bf2ded32f66390fdef13409be4a10?editors=1100

  

Прозрачный градиент

Когда вам нужно поместить текст поверх фотографии, у вас должен быть градиент под ним, чтобы сделать текст читабельным. Как и в предыдущем примере, размер градиента должен варьироваться между маленькими и большими окнами просмотра. См. рисунок ниже:

Прозрачный градиент


.element {
  background: linear-gradient(to top, #000 0, transparent max(20%, 20vw));
}

Это небольшое улучшение может сделать градиент более логичным на мобильных устройствах. Если размер градиента составляет 50% от его родителя на десктопе, для мобильных устройств он должен составлять около 30%. Используя функцию max(), мы можем установить для нее минимальное значение.

Демо - codepen.io/shadeed/pen/qBOpOVY/babf1bfd4c85eeb1b6f9f549dd0fe602?editors=1100

  

Динамическое расстояние

Динамическое расстояние

У нас может быть динамическое расстояние между элементами дизайна с помощью единиц измерения окна просмотра 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, которое не должно быть превышено. Просто и легко!

Демо - codepen.io/shadeed/pen/NWGXrKV/94dd79cb803a6b9bced68e4a5d35d537?editors=0100

  

Ширина контейнера

Ширина контейнера

Если у вас есть контейнер, который должен занимать 80% ширины своего родителя, а ширина не должна превышать 780px, что использовать? Обычно это может быть что-то вроде этого:


.container {
  max-width: 780px;
  width: 80%;
}

Однако с помощью функции min() можно установить максимальное значение следующим образом:


.container {
  max-width: min(80%, 780px);
}

Демо - codepen.io/shadeed/pen/pojpyEG/3d8b44709b04efdd7336fe91363e3d76?editors=1100

  

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

Демо - codepen.io/shadeed/pen/XWmVomZ/7b5c7979e09573ca32150ebfc7f74a66?editors=1100

  

Зазор сетки

Зазор сетки

Прекрасный пример использования — это когда у нас есть grid-gap с использованием сетки CSS, и мы хотим уменьшить его для мобильных окон просмотра. С clip() это довольно просто.


.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-gap: clamp(1rem, 2vw, 24px);
}

Если вы хотите больше узнать о сетке и функциях сравнения, вот отличная статья Дэнни Винтера (blog.logrocket.com/flexible-layouts-without-media-queries).

Демо - codepen.io/shadeed/pen/VwvQmoz/a14c7d9fcbbae84340a4f83833294f5b?editors=1100

  

Функция сравнения 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() для установки размера шрифта недостаточно, так как он будет слишком мал для мобильных устройств. Вы должны установить минимальные и максимальные значения для вещей, которые жизненно важны для взаимодействия с пользователем.

Надеюсь Вам понравилась статья!

Ссылка на автора - twitter.com/shadeed9 !


Top

🔖 Выбор по тегам ×

💌 Написать сообщение ×

Все поля обязательны для заполнения!