Все, что я узнал о min(), max(), clamp()

Все, что я узнал о min(), max(), clamp()

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

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

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

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

Все, что я узнал о min(), max(), clamp()

А вот поддержка clamp():

Все, что я узнал о min(), max(), clamp()

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

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

Функция Min()

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

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

Все, что я узнал о min(), max(), clamp()

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

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

Все, что я узнал о min(), max(), clamp()

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

Функция Max()

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

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

Все, что я узнал о min(), max(), clamp()

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

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

Функция Clamp()

clamp() фиксирует значение между двумя определенными значениями, минимальным и максимальным. Она принимает три параметра (минимальное значение, предпочтительное значение, максимальное значение). Рассмотрим следующий пример.

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

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

Все, что я узнал о min(), max(), clamp()

Вот описание примера выше:

Ширина никогда не опустится ниже 200px

Центральное (предпочтительное) значение — 50%, и оно будет работать, только если ширина области просмотра больше 400px или меньше 2000px.

Ширина не увеличится больше 1000px

clamp() похожа на физический зажим. Она фиксирует значение на основе двух предоставленных значений по краям (min, max). Посмотрите интерактивную демонстрацию.

Как рассчитывается clamp()?

Согласно Mozilla Developer Network (MDN), когда clamp() используется как значение, оно эквивалентно использованию функций max() и min(). Рассмотрим приведенный ниже пример:

.element { width: clamp(200px, 50%, 1000px); /* Is equivalent to the below */ width: max(200px, min(50%, 1000px));
}

Значение 50% зависит от ширины области просмотра браузера, давайте предположим, что ширина области просмотра равна 1150px.

.element { width: max(200px, min(50%, 1000px)); /* Assuming the viewport width is 1150px */ width: max(200px, min(575px, 1000px)); /* Resolves to */ width: max(200px, 575px); /* Resolves to */ width: 575px;
}

Контекст имеет значение

Вычисленное значение зависит от контекста. Это может быть %, em, rem, vw/vh. Даже процентное значение может быть либо на основе ширины области просмотра в случае, если элемент находится непосредственно в body, либо на основе его родителя.

Математические выражения

Стоит отметить, что математические вычисления допустимы, поэтому нет необходимости использовать calc(). Согласно спецификации: Полные математические выражения допускаются в каждом из аргументов; нет необходимости вкладывать их в calc()! Вы также можете предоставить более двух аргументов, если у вас есть несколько ограничений.

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

.type { /* Force the font-size to stay between 12px and 100px */ font-size: clamp(12px, 10 * (1vw + 1vh) / 2, 100px);
}

Что дают функции сравнения CSS?

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

Все, что я узнал о min(), max(), clamp()

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

Все, что я узнал о min(), max(), clamp()

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

Случаи использования

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

Все, что я узнал о min(), max(), clamp()

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

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

.wrapper { display: flex;
} aside { flex-basis: max(30vw, 150px);
} main { flex-grow: 1;
}

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

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

Все, что я узнал о min(), max(), clamp()

Отличный вариант использования для clamp() — заголовки. Предположим, вам нужен заголовок с минимальным размером 16px и максимальным размером 50px. Функция clamp() даст нам возможность задать минимум и максимум соответственно.

.title { font-size: clamp(16px, 5vw, 50px);
}

Использовать здесь clamp() идеально, потому что это гарантирует, что применяемый размер шрифта доступен и легко читается. Если вы будете использовать min() для установки максимального размера шрифта, то вы не сможете контролировать шрифт в маленьких областях просмотра.

.title { font-size: min(3vw, 24px); /* Not recommended, bad for accessibility */
}

Все, что я узнал о min(), max(), clamp()

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

Как я упоминал ранее, вы можете вложить min() внутрь функции max(), что будет имитировать функцию clamp(). См. ниже:

.title { font-size: max(16px, min(10vw, 50px));
}

Демонстрация.

После обсуждения в Твиттере выяснилось, что использование только 10vw в качестве предпочтительного значения font-size не является оптимальным. Это вызовет проблему доступности, когда пользователь увеличит масштаб браузера.

.title { font-size: clamp(16px, (1rem + 5vw), 50px);
}

В приведенном выше примере я добавил выражение (1rem + 5vw), которое решит проблему.

Декоративные заголовки

Все, что я узнал о min(), max(), clamp()

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

.section-title:before { content: attr(data-test); font-size: max(13vw, 50px);
}

Демонстрация.

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

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

.element { background: linear-gradient(135deg, #2c3e50, #2c3e50 60%, #3498db);
}

Все, что я узнал о min(), max(), clamp()

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

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

Все, что я узнал о min(), max(), clamp()

Демонстрация.

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

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

Все, что я узнал о min(), max(), clamp()

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

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

Демонстрация.

Динамические поля

Все, что я узнал о min(), max(), clamp()

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

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. Просто и понятно!

Демонстрация.

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

Все, что я узнал о min(), max(), clamp()

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

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

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

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

Демонстрация.

Вертикальные отступы раздела

Что мне понравилось, так это то, что clamp() идеально подходит для установки минимального и максимального отступов для раздела. Рассмотрим пример ниже, где у нас есть hero-раздел.

Все, что я узнал о min(), max(), clamp()

С помощью одной строки CSS мы можем достичь гибкости, описанной выше.

.hero { padding: clamp(2rem, 10vmax, 10rem) 1rem;
}

Демонстрация.

Граница и тень

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

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

Демонстрация.

Зазор сетки

Все, что я узнал о min(), max(), clamp()

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

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

Демонстрация.

Функции сравнения CSS со значениями без единиц измерения

Я пытался установить 0, как минимальное значение для clamp(). Смотрите CSS ниже:

.element { width: clamp(0, 10vmax, 10rem);
}

Этот CSS недействителен, поэтому кажется, что здесь не следует использовать числа без единиц измерения.

Как добавить запасной вариант для не поддерживающих браузеров

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

1. Добавить запасной вариант вручную

Это означает, что мы должны предоставить запасной вариант, добавив свойство перед сравнением CSS. Смотрите пример ниже:

.hero { padding: 4rem 1rem; padding: clamp(2rem, 10vmax, 10rem) 1rem;
}

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

2. Использование CSS @supports

Мы можем использовать запрос функций @supports, чтобы определить, поддерживаются ли функции сравнения CSS. Я предпочитаю это ручному решению, потому что любой браузер, который поддерживает функции сравнения, должен иметь поддержку запроса функции @supports.

.hero { /* Default, for non-supporting browsers */ padding: 4rem 1rem;
} @supports (width: min(10px, 5vw)) { /* An enhancement for supporting browsers */ .hero { padding: clamp(2rem, 10vmax, 10rem) 1rem; }
}

Проблемы доступности

Хотя функции сравнения CSS предоставляют нам новый способ создания более динамичных веб-страниц, мы должны быть осторожными в том, как их использовать. Например, использования min() для установки font-size недостаточно, поскольку оно будет слишком маленьким для мобильных устройств. Вы должны установить минимальные и максимальные значения для вещей, которые являются жизненно важными для пользовательского опыта.

Автор: Ahmad Shadeed

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

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