$ sudo teach IT

Иногда нужное значение нельзя записать одним числом, потому что оно складывается из разных величин. Например: «на всю высоту экрана минус шапка в 60 пикселей», «половина ширины родителя минус отступ», «на всю ширину, но с учётом фиксированной колонки сбоку». Проценты и пиксели тут смешиваются, и заранее посчитать результат невозможно — он зависит от экрана. Функция calc() решает это: она позволяет выполнять арифметику прямо в CSS, комбинируя разные единицы. Браузер сам вычислит результат и пересчитает его при изменении размеров.

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

Что уже умеем / что добавим

Вы умеете задавать гибкие размеры и хранить значения в переменных. Но пока не могли комбинировать разные единицы в одном значении — например, вычесть пиксели из процентов. Теперь добавим calc() — арифметику в CSS. В сквозном проекте мы точно рассчитаем высоту главного экрана сайта компании и ширину контентной области с учётом отступов.

Что вы узнаете в рамках статьи

  • Что делает функция calc() и какие операции доступны.
  • Как смешивать разные единицы (проценты, пиксели, vh) в одном значении.
  • Почему важны пробелы вокруг знаков операций.
  • Как сочетать calc() с CSS-переменными.

Ключевые термины

  • calc() — функция для арифметических вычислений в значениях CSS.
  • Операции — сложение (+), вычитание (), умножение (), деление (/).
  • Смешение единиц — комбинирование разных единиц (например, 100% - 40px) в одном выражении.
  • vh — единица, равная 1% высоты окна (из курса об адаптиве).

Что такое calc() и какие операции доступны

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

.box {
  width: calc(100% - 40px);
}

Ширина блока будет равна всей ширине родителя минус 40 пикселей. Самое ценное здесь — смешение единиц: 100% и 40px невозможно сложить «в голове» заранее, ведь проценты зависят от размера родителя, но браузер вычислит это сам в момент отрисовки и пересчитает при изменении размеров. Умножение и деление тоже работают: calc(100% / 3) даст точную треть ширины, а calc(1rem * 2) — удвоенный размер.

Смешение разных единиц

Главная сила calc() — соединять единицы, которые иначе несовместимы. Классический пример — блок на всю высоту экрана за вычетом фиксированной шапки:

.hero {
  height: calc(100vh - 60px);
}

Здесь 100vh — вся высота окна, а 60px — высота фиксированной шапки. Результат — ровно та высота, что остаётся под шапкой, на любом экране. Без calc() так не записать: 100vh и 60px — разные единицы. Подобным образом считают ширину контента рядом с боковой панелью (calc(100% - 250px)), отступы, размеры сетки. Комбинировать можно и больше двух величин: calc(100% - 40px - 1rem) — браузер справится с любой корректной формулой.

Пробелы вокруг операций

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

/* Правильно: пробелы вокруг минуса есть */
width: calc(100% - 40px);

/* Ошибка: пробелов нет, значение не сработает */
width: calc(100%-40px);

Причина в том, что минус и плюс без пробелов браузер может принять за знак самого числа (например, -40px — это отрицательное число, а не вычитание). Поэтому правило простое: всегда ставьте пробелы вокруг + и -. Для * и / пробелы формально не обязательны, но их тоже принято ставить для читаемости. Это самая частая причина, по которой «calc() не работает», — стоит проверять пробелы в первую очередь.

Сочетание с переменными

calc() особенно хорош вместе с CSS-переменными: вы храните базовые значения в переменных, а из них вычисляете производные. Это делает стили одновременно гибкими и точными:

:root {
  --header-height: 64px;
  --gap: 24px;
}

.hero {
  height: calc(100vh - var(--header-height));
}

.content {
  width: calc(100% - var(--gap) * 2);
}

Высота главного экрана считается от высоты шапки, заданной переменной, а ширина контента — с учётом двойного отступа. Если поменять --header-height в одном месте, все вычисления обновятся сами. Такое сочетание — основа аккуратных, поддерживаемых макетов: смысловые величины лежат в переменных, а calc() собирает из них нужные размеры. Обратите внимание, как var() спокойно подставляется прямо внутрь формулы.

Применяем в проекте

Рассчитаем главный экран сайта компании так, чтобы он занимал всю высоту окна за вычетом шапки, и зададим ширину контентной области с учётом отступов. Возьмём высоту шапки и отступ из переменных, а размеры соберём через calc().

:root {
  --header-height: 64px;
  --gap: 24px;
}

.hero {
  height: calc(100vh - var(--header-height));
}

.content {
  width: calc(100% - var(--gap) * 2);
  margin: 0 auto;
}

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

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

  • Нет пробелов вокруг и +.
    calc(100%-40px) не сработает; вокруг сложения и вычитания пробелы обязательны.
  • Деление на ноль или на единицу с единицей.
    Делить и умножать можно только на число без единицы; calc(100% / 3px) некорректно.
  • Смешивать несовместимое.
    Внутри calc() единицы должны быть складываемыми по смыслу; проверяйте, что формула имеет физический смысл.
  • Усложнять там, где не нужно.
    Если значение можно задать одним числом, calc() ни к чему; применяйте его, когда действительно нужно смешать единицы.

Итоги

Отличная работа — вы научились вычислять значения прямо в CSS! Теперь вы умеете использовать calc() для сложения, вычитания, умножения и деления, смешивать разные единицы вроде процентов, пикселей и vh, помните про обязательные пробелы вокруг операций и умеете сочетать calc() с переменными. В сквозном проекте вы точно рассчитали высоту главного экрана и ширину контента сайта компании.

Прекрасный прогресс — ваши макеты стали точными и гибкими одновременно! В следующем уроке мы займёмся современными эффектами: тенями, градиентами, фильтрами и модным «стеклянным» размытием через backdrop-filter, которые придадут сайту глубину и стиль.

На следующий урок