Menu

calc() в CSS: смешивание единиц, правила синтаксиса, примеры

calc() позволяет считать в CSS и смешивать единицы, например 100% минус боковая панель фиксированной ширины 200px. Разберем правила синтаксиса (пробелы важны), calc() с CSS-переменными, типичные задачи, которые она решает, и почему невалидный calc() молча игнорируется.

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

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

calc() выполняет арифметику внутри значения CSS и может смешивать единицы, размер которых известен только при раскладке. Классический случай: «вся ширина минус боковая панель фиксированной ширины»:

100% известен только после раскладки страницы, а 180px фиксирован, поэтому ни одна единица не выразила бы это сама. calc() вычисляет: в превью шириной 800px строка шириной 784px, и основной колонке достается 604px, а строка под раскладкой выводит настоящие числа. Сегодня эту раскладку без вычислений сделали бы flexbox или grid, но такое же вычитание встречается повсюду: высота минус шапка, ширина минус промежуток.

Правила синтаксиса

width: calc(100% - 2rem);          /* + and - need spaces on both sides */
width: calc(100% / 3);             /* divide by a plain number */
margin: calc(var(--space) * 2);    /* multiply by a plain number */
height: calc(100vh - (64px + 1rem)); /* parentheses group */
ПравилоВалидноНевалидно
Пробелы вокруг + и -calc(100% - 20px)calc(100%-20px)
*: хотя бы с одной стороны простое числоcalc(2 * 1rem)calc(2px * 3px)
/: длину делят на простое числоcalc(100% / 3)width: calc(300px / 3px) (не длина)
Единицы должны быть совместимыcalc(1rem + 10px)calc(1rem + 2s)

Правило пробелов существует потому, что 100% -20px читалось бы как два отдельных значения, второе из которых отрицательное число. Когда calc() невалиден, все объявление отбрасывается, и элемент сохраняет значение из более ранних правил.

Попробуйте выражение

Введите любое выражение для ширины блока. Браузер покажет, валидно ли оно и какую ширину дало:

Попробуйте 100%-200px (невалидно, нет пробелов), 100% / 3, 50% + 4rem, 2 * 120px, 200px * 2px (невалидно) и (100% - 40px) / 2.

calc() с CSS-переменными

Переменные и calc() хорошо работают вместе: храните базовое значение один раз и выводите из него остальные. Переменная без единиц становится длиной, если умножить ее на одну единицу:

Измените --space на 12px или --cols на 4, и все производные значения последуют за ними. Объявление и область видимости переменных разобраны на странице про переменные CSS.

Типичные применения

Задачаcalc()
Заполнить пространство рядом с элементом фиксированной шириныwidth: calc(100% - 240px)
Секция под фиксированной шапкойmin-height: calc(100vh - 64px)
Половина ширины минус половина промежуткаwidth: calc(50% - 8px)
Центрировать абсолютно позиционированный блок 100pxleft: calc(50% - 50px)
Размер шрифта, который немного растет с экраномfont-size: calc(1rem + 0.5vw)
Превратить числовую переменную в длинуcalc(var(--n) * 1px)
Отрицательное значение переменнойcalc(var(--space) * -1)

Для значения, которое должно оставаться в пределах, используйте clamp(): она принимает те же вычисления в аргументах без записи calc().

Где работает calc()

Везде, где допустимы длина, проценты, число, угол или время: width, margin, padding, top, font-size, line-height, размеры дорожек grid, transition-delay и углы внутри transform. calc() можно вкладывать, и вложенный calc() равнозначен обычным скобкам.

Хороший пример это углы. У каждой риски ниже свой --i (от 0 до 11), и одно правило превращает его в угол через calc(var(--i) * 30deg):

Риска 3 получает rotate(90deg), который Chrome показывает как матрицу matrix(0, 1, -1, 0, 0, 0): четверть оборота. left: calc(50% - 2px) центрирует каждую риску, вычитая половину ее собственной ширины 4px.

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

  • Нет пробелов вокруг - или +. calc(100%-20px) невалидно и игнорируется.
  • Умножение двух длин. calc(10px * 2px) в CSS не имеет смысла. Одна сторона * должна быть простым числом.
  • calc() для процентной высоты без высоты у родителя. calc(100% - 20px) для height, как и height: 100%, требует родителя с заданной высотой.
  • calc() там, где справился бы flexbox или grid. width: calc(33.333% - 10px) для колонок хрупко; display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px обходится без вычислений.
  • Ожидание сообщения об ошибке. Браузер не предупреждает о невалидном calc(). Проверьте элемент в инструментах разработчика: невалидное объявление показано зачеркнутым.

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

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

Вычисляет значение из выражения с +, -, * и / и может смешивать единицы, которые браузер узнает только при раскладке. width: calc(100% - 200px) это полная ширина родителя минус 200px, какой бы ни была ширина родителя.

Почему не работает calc()?

Самая частая причина: нет пробелов. Вокруг + и - должны быть пробелы с обеих сторон, поэтому calc(100%-20px) невалидно. Другие причины: умножение двух длин (10px * 2px) или деление на длину, что не дает длины. Невалидный calc() делает невалидным все объявление, и браузер его игнорирует.

Можно ли использовать CSS-переменные в calc()?

Да. calc(var(--gap) * 2) удваивает переменную, а calc(var(--columns) * 1px) превращает число без единиц в пиксели. Сначала подставляется значение переменной, а затем выполняется вычисление.

Нужны ли пробелы вокруг * и / в calc()?

Нет. Пробелы обязательны только вокруг + и -, потому что без них -20px читалось бы как отрицательное число. Пробелы вокруг * и / необязательны, но писать их везде проще всего запомнить.

Чем calc() отличается от clamp()?

calc() вычисляет одно значение из выражения. clamp(MIN, VAL, MAX) удерживает значение между двумя пределами. Они сочетаются: каждый аргумент clamp() уже может содержать вычисления в стиле calc, например clamp(1rem, 1rem + 2vw, 3rem).

Coddy programming languages illustration

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

НАЧАТЬ