Математические функции в CSS расширяют логические возможности. Они позволяют не только ускорить процесс верстки, но и задать точные характеристики для объектов, которые можно вычислить математически. Особенно встроенные функции в CSS могут быть полезны при верстке pixel perfect, когда важно соответствие верстки с макетом вплоть до пикселя.

Математические функции в CSS не стоит путать с выражениями, которые могут встречаться в различных препроцессорах, например, LESS, SCSS и так далее. Они могут существовать в препроцессорах, но с оговорками:

  • все расчеты происходят при компиляции и результаты выводятся в готовый файл в виде фиксированного значения;
  • в препроцессорных функциях не получится сочетать разные единицы измерения в одном выражении.

В CSS существует 4 классических математических функций: min, max, clam и calc.

Функциональные обозначения в CSS

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

Внутри скобок может быть несколько выражений, но в случае с CSS они должны соответствовать конкретной функции. Например, в min и max не получится выполнять полноценные математические операции, как это можно сделать в calc.

Математические выражения внутри функций

Внутри круглых скобок происходят основные расчеты, заданные верстальщиков. Эта область математических выражений или аргументов. Внутри скобок поддерживается четыре стандартные операции (в скобках указано обозначение операции): сложение(+), вычитание(-), деление(/), умножение(*).

Поддерживаются дополнительные выражения, например, attr. Они не являются полноценными функциями. В основном такие выражения служат для добавления атрибутов и параметров для HTML-компонентов через CSS. Такие дополнения могут тоже полноценно встраиваться в математические выражения основных функций.

Со всеми этими математическими выражениями способны работать функции: min, max и calc.

Допускается вложение функций друг в друга. Например:

calc(min(аргумент)+max(аргумент))

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

Функции min(), max()

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

width: min(350px, 50%);

В этом примере элемент будет принимать ширину не менее 350 пикселей и не менее 50% от размеров родительского блока. Примерно аналогичным образом работает функция max, но только в ней записывается уже максимальное значение.

Функции min и max могут быть объединены в одну - minmax. Она имеет следующий вид: minmax(min, max). Здесь в качестве аргументов выступают минимальная и максимальная величина соответственно. В случае, если максимальное значение, заданное в качестве аргумента, меньше или равно минимальному, то оно будет проигнорировано. Функции minmax, min и max способны принимать следующие типы значений:

  • фиксированные размеры, например, размер в пикселях;
  • проценты;
  • гибкие размеры, например, в rem и em;
  • max-content;
  • min-content;
  • auto.

В качестве практического примера для демонстрации возможности функции minmax создадим три блока. При обычном разрешении экрана эти блоки будут иметь одинаковые размеры, но при уменьшении окна или разрешения они будут меняться пропорционально друг другу.

Сделаем так, чтобы левая ячейка тоже меняла размер, но при этом оставалась в диапазоне 100-200 пикселей вне зависимости от размера родительского элемента.

.grid {
display: grid;
grid-template-columns: minmax(100px, 200px) 1fr 1fr;
}

Класс grid присвоен первой колонке. Она тоже адаптируется под размеры окна, но при этом ее ширина остается всегда в пределах от 100 до 200 пикселей. Вторая и третья колонки сжимаются и расширяются до заполнения оставшегося свободного места поровну.

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

Аналогично возможно указать гибкие размеры. Это новая единица, тоже введенная спецификацией CSS Grid Layout. К ней можно отнести единицы измерения em, rem, fr. Поддержка последнего была добавлена недавно. Размеры элементов, указанные в fr, занимают равноценное свободное место. Например, есть 4 блока и каждый занимает по 1fr, следовательно, каждый занимает по 25% от 100% размера родительского элемента. Можно также задавать 1.5-2-3 и более fr. В таком случае блок будет просто отбирать больше пространства в процентном соотношении, а пространство между остальными поделиться поровну.

Для примера изменим рассмотрим функцию такого вида minmax(200px, 1fr). В шаблоне 3 элемента и все по умолчанию имеют размер 1fr, то есть занимают равное пространство. Когда размер родителя начнет уменьшаться до такого уровня, что 1fr не сможет равняться 200 пикселей, то первый объект (эта функция задана для него) не будет становиться меньше 200 пикселей. Остальные же будут продолжать делить оставшееся пространство поровну.

Аргументы max-content и min-content задают фиксированный размер относительно контента, находящегося в ячейке. При них размер ячейки подстраивается таким образом, чтобы содержимое свободно вмешалось и не выходило за пределы ячейки. В случае с max-content контент в ячейке не должен переноситься на новую строку и выходить за пределы границ ячейки. В случае с min-content перенос на новую строку допускается.

Функция clamp()

Эта функция чем-то похожа на предыдущие, но только принимает три значения в качестве аргумента - минимальное, максимальное и желаемое значение. Основываясь на этих значениях подбирается оптимальный размер для элемента. Функция имеет вид: clamp(MIN, VAL, MAX).

В качестве примера разберем аргументы с фиксированными значениями:

width: clamp(20px, 40px, 80px);

Ширина будет подстраиваться максимально близко к 40 пикселям, но с учетом размера экрана и соседних элементов. При этом ширина объекта ни при каких обстоятельствах не может быть меньше 20 пикселей и больше 80.


В качестве аргумента можно прописывать плавающие значение, например, проценты, rem, em.

width: clamp(25%, 40px, 5em);

В этом примере объект стремиться к ширине 40 пикселей, но при этом не должен быть меньше 25% от размера родителя, но при он не должен быть больше 6em. Стоит заметить, что размер em напрямую зависит от размера шрифта в документе или в отдельном блоке. Если учесть, что стандартный размер шрифта в документе 14 пикселей, то максимально допустимая ширина в этом примере 70 пикселей.

Функцию clamp можно применять и для расчета размера шрифта:

font-size: clamp(1em, 16px, 3.5rem);

Здесь размер шрифта меняется в зависимости от области видимости. В идеале его размер должен быть 16px, но не может быть меньше 1em и больше 3.5em.

Функция calc()

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

width: calc(100% - 30px);

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

Также здесь доступны операции с числами, не привязанными к значениям:

width: calc(100% / 8);

После выполнения расчетов блок будет занимать ⅛ от родительского элемента.

Еще с помощью этой функции можно складывать параметры цвета:

--palette-hue: calc(var(--palette-hue) + var(--palette-step-1));

Дополнительно в качестве примера разберем настройку размера изображения в карточке с помощью функции calc. Пока имеется такая разметка:

.card {
min-width: 400px;
max-width: 500px;
padding: 1rem;
}

.card__img {
width: 100%;
}

В получившемся результате изображение имеет отступы по бокам от края карточки. Требуется, чтобы у него по бокам не было отступов.

Это можно решить с помощью функции calc:

.card {
min-width: 400px;
max-width: 500px;
padding: 1rem;
}

.card__img {
/* Ширина картинки */
width: calc(100% + 2rem);
/* Сдвиг влево на размер паддинга */
margin-left: -1rem;
}

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

Используя функцию calc нужно помнить о следующих нюансах:

  1. Арифметический знак нужно отделять пробелом от чисел с обеих сторон. В противном случае браузер может проигнорировать функцию или сделать неверные расчеты.
  2. Проводите расчеты только совместимых единиц. Можно считать пиксели с процентами, rem, em и так далее, но нельзя складывать, например, пиксели с градусами.
  3. В @media проводите расчеты только с одинаковыми единицами, проценты с процентами, пиксели с пикселями и так далее.
  4. Делить на ноль нельзя. Будет ошибка.

Заключение

Поддержка отдельных функций браузерами может различаться, но незначительно. В среднем уровень поддержки составляет более 95%. Проблемы могут возникать в старых версиях браузеров и, в основном, с функцией calc:

  • Firefox ниже 59 версии не поддерживает работу с цветами;
  • IE 9-11 не умеет работать с тенями, заданными через функцию calc;
  • IE 9-11 и даже новые версии Edge не поддерживают конструкцию width: calc(), если она применяется для задания размеров ячеек таблиц.

Пока что, это основные 4 функции, доступные в CSS. Планируется в ближайшее время добавить функции mod(), round(), sin() и другие, но пока не известно до конца, как они будут работать, плюс, у них нет поддержки ни одним браузером.

Функции в CSS позволяют упростить верстку, благодаря возможности делать расчеты в качестве аргументов. Ранее для этого требовалось задействовать сторонние инструменты, например, JS.