Menu

clamp() в CSS: адаптивный размер шрифта, min() и max()

clamp(MIN, PREFERRED, MAX) возвращает предпочтительное значение, но никогда не меньше MIN и не больше MAX. Разберем, как она делает размеры шрифта и отступы плавными без медиазапросов, как вычислить среднее значение и как с ней связаны min() и max().

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Что делает clamp()

clamp(MIN, PREFERRED, MAX) принимает три значения и возвращает среднее, пока оно остается между двумя другими. Классическое применение: заголовок, который растет вместе с экраном, но останавливается на разумных пределах, без медиазапросов:

Предпочтительное значение 1rem + 3vw: 16px плюс 3% ширины. В превью шириной 800px это 16 + 24 = 40px, что между 24px (1.5rem) и 48px (3rem), поэтому заголовок 40px. На телефоне шириной 320px предпочтительное значение 25.6px. Шире 1067px оно превысило бы 48px, поэтому останавливается на 48px. Меняйте размер окна, чтобы видеть, как меняется число; vw здесь это процент от ширины фрейма превью.

Посмотрите без изменения окна

vw следует за окном просмотра, которое трудно менять во время чтения. Единицы контейнерных запросов следуют за контейнером: cqi это 1% ширины контейнера. Двигайте ползунок, чтобы менять блок, и такой же clamp() будет откликаться:

Сдвиньте в начало, и заголовок остановится на 20px (MIN). Сдвиньте в конец, и он остановится на 40px (MAX). Между ними он следует 0.5rem + 6cqi. Это тот же механизм, что и версия с vw, только с линейкой поменьше.

Три аргумента

font-size: clamp(1rem, 0.8rem + 1vw, 1.5rem);
/*               MIN   PREFERRED     MAX    */
АргументРольТипичная единица
MINнаименьшее допустимое значениеrem
PREFERREDзначение, которое меняется вместе с экраномrem + vw (или cqi)
MAXнаибольшее допустимое значениеrem

Внутри каждого аргумента можно считать без calc(): 1rem + 2vw подходит как есть. Вокруг + и - нужны пробелы с обеих сторон, иначе все объявление невалидно.

Если MIN больше MAX, побеждает MIN: clamp(3rem, 5vw, 2rem) всегда 3rem.

Как вычислить среднее значение

Чтобы шрифт рос от 16px на экране 320px до 24px на экране 1280px:

  1. Наклон: (24 − 16) ÷ (1280 − 320) = 8 ÷ 960 = 0.00833, то есть 0.833vw (vw считается на 100px).
  2. Начальная точка: 16px − 0.00833 × 320px = 13.33px, то есть 0.833rem.
  3. Поставьте пределы вокруг:
font-size: clamp(1rem, 0.833rem + 0.833vw, 1.5rem);

При ширине 320px это дает 13.33 + 2.67 = 16px, при 1280px 13.33 + 10.67 = 24px, а за пределами этого диапазона значение остается на границах. Онлайн-«калькуляторы clamp» делают ровно эту арифметику.

min() и max()

clamp() это сочетание двух более простых функций:

  • min(a, b) возвращает меньшее значение, поэтому задает верхний предел.
  • max(a, b) возвращает большее значение, поэтому задает нижний предел.
  • clamp(MIN, VAL, MAX) то же самое, что max(MIN, min(VAL, MAX)).

Поначалу названия кажутся перевернутыми: чтобы сказать «не больше 600px», используют min().

В широком превью первая карточка останавливается на 420px. Внутри родителя шириной 260px меньшее значение это 100%, поэтому вторая карточка 260px. max(12px, 3%) дает первой карточке 3% ширины ее родителя (body: около 23.5px в превью шириной 800px), а второй 12px, потому что 3% от 260px (7.8px) ниже нижнего предела.

width: min(100%, 420px) одним объявлением заменяет старую пару width: 100%; max-width: 420px;.

Не только шрифты: отступы и ширины

clamp() работает в любом свойстве, которое принимает длину. Проценты в среднем значении делают компонент плавным относительно родителя, а не окна просмотра:

В родителе шириной 300px карточка шириной 240px (80%) с padding 15px (5% от 300px). В родителе шириной 760px 80% дали бы 608px, поэтому карточка останавливается на максимуме 520px, а 5% от 760px это 38px, поэтому padding останавливается на 32px.

Доступность: оставляйте rem в среднем значении

Размер шрифта только из vw, например font-size: 5vw, не растет, когда читатель увеличивает размер шрифта по умолчанию в настройках браузера, и не растет при масштабировании, потому что масштаб делает окно просмотра уже в пикселях CSS. Слагаемое rem (1rem + 2vw) и пределы в rem сохраняют связь текста с настройкой читателя. rem и vw подробно объяснены на странице про единицы.

Частые ошибки

  • min() для минимума. min() выбирает меньшее значение, а это верхний предел. Для «не меньше 12px» используйте max(12px, ...).
  • Нет пробелов вокруг + или -. clamp(1rem, 1rem+2vw, 3rem) невалидно, и свойство откатывается к предыдущему значению.
  • Только vw в середине. Тогда текст игнорирует настройку размера шрифта читателя. Добавьте слагаемое rem.
  • MIN больше MAX. Результат всегда MIN, а это редко то, что имелось в виду.
  • Пределы в px для размеров шрифта. Они ограничивают текст даже для читателей, которым он нужен крупнее. Используйте rem.

Часто задаваемые вопросы

Что делает clamp() в CSS?

clamp(MIN, PREFERRED, MAX) использует предпочтительное значение, пока оно остается между двумя пределами, а иначе ближайший предел. font-size: clamp(1rem, 4vw, 2rem) следует за 4% ширины окна просмотра, но никогда не опускается ниже 1rem и не поднимается выше 2rem.

Как сделать адаптивный размер шрифта через clamp?

Поставьте в середину значение от окна просмотра, а по краям фиксированные пределы, и добавьте в середину rem, чтобы текст по-прежнему следовал настройке размера шрифта читателя: font-size: clamp(1.5rem, 1rem + 2vw, 3rem);.

Что будет, если минимум в clamp() больше максимума?

Побеждает минимум. clamp(3rem, 5vw, 2rem) всегда дает 3rem, потому что clamp() применяет минимум после максимума.

Чем min() отличается от max() в CSS?

min() возвращает наименьшее из значений, поэтому работает как верхний предел: width: min(100%, 600px) никогда не шире 600px. max() возвращает наибольшее, поэтому работает как нижний предел: font-size: max(1rem, 2vw) никогда не меньше 1rem.

Поддерживается ли clamp() во всех браузерах?

Да, clamp(), min() и max() работают во всех актуальных версиях Chrome, Edge, Firefox и Safari и подходят для любого свойства, которое принимает длину, число, проценты или угол.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ