Дайджесты новостей
Макросъёмка образца модульной дизайнерской плитки с размерной линейкой, иллюстрирующая работу функций calc-size и round в CSS.

calc-size() и round(): как выровнять высоту блока по целым плиткам фонового узора

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

Раньше для решения этой задачи приходилось привлекать тяжелую артиллерию на JavaScript. Разработчики вешали наблюдатель ResizeObserver, измеряли offsetHeight элемента, вычисляли остаток от деления на высоту плитки и принудительно выставляли инлайновый стиль min-height. Это не только нагружало поток отрисовки, но и вызывало неприятные скачки макета (Cumulative Layout Shift).

Известный исследователь интерфейсов Ахмад Шадид (Ahmad Shadeed) показал, что современная спецификация W3C наконец-то позволяет решить эту задачу на чистом CSS с помощью связки математических функций calc-size() и round().

Магия связки calc-size() и round()

Функция round(), появившаяся в модуле CSS Values 4, умеет округлять числовые значения до заданного шага (интервала). Но у нее было фундаментальное ограничение: она не могла оперировать ключевыми словами вроде auto или max-content, потому что браузер вычисляет их только на этапе компоновки макета.

Здесь на сцену выходит функция calc-size(), стандартизированная в спецификации CSS Values and Units Module Level 5. Она принимает ключевое слово размера в качестве базиса, а вторым аргументом позволяет выполнить математическую операцию над вычисленным значением через ключевое слово size:

.tile-card {
  --tile-width: 52px;
  --tile-height: 44px;
  background-image: url("pattern-tile.png");
  background-repeat: repeat;
  background-size: var(--tile-width) var(--tile-height);
  padding: 24px;
  
  /* Контентная высота округляется вверх до кратности плитке */
  height: calc-size(auto, round(up, size, var(--tile-height)));
}

Давай разберем эту формулу на пальцах. Базис auto говорит браузеру: «Сначала посчитай естественную высоту блока по объему находящегося внутри текста». Затем переменная size подставляет это число пикселей в функцию round(up, size, var(--tile-height)). Режим up округляет результат строго в большую сторону до ближайшего числа, кратного высоте нашей плитки в 44 пикселя. Если тексту требуется 150 пикселей, блок автоматически вырастет до 176 пикселей (44 × 4), и нижний ряд узора останется идеально целым.

Прогрессивное улучшение через @supports

Почему важно использовать именно стратегию округления up? Функция round() поддерживает три режима: nearest (к ближайшему целому), down (вниз) и up (вверх). Если применить down или nearest, итоговая высота контейнера может оказаться меньше высоты текста, что приведет к переполнению блока и выпадению контента наружу.

На текущий момент функция calc-size() полноценно поддерживается в браузерных движках на базе Chromium (начиная с версии Chrome 129). В Firefox и Safari реализация спецификации находится на этапе активной подготовки. Поэтому в промышленном коде эту технику необходимо внедрять по принципу прогрессивного улучшения через директиву @supports:

/* Базовый безопасный стиль для всех браузеров */
.tile-card {
  --tile-width: 52px;
  --tile-height: 44px;
  background-image: url("pattern-tile.png");
  background-repeat: repeat;
  background-size: var(--tile-width) var(--tile-height);
  padding: 24px;
  height: auto;
}

/* Прогрессивное выравнивание высоты в современных браузерах */
@supports (height: calc-size(auto, size)) {
  .tile-card {
    height: calc-size(auto, round(up, size, var(--tile-height)));
  }
}

В сочетании с другими современными возможностями верстки, о которых мы упоминали в подборке про 12 возможностей современного CSS, такой подход избавляет проект от лишних килобайтов скриптов и возвращает браузеру его нативную роль вычислителя геометрии.