Функция CSS `calc-size()`
Baseline Ограниченная доступность
Эта функция не входит в Baseline, поскольку она не работает в некоторых наиболее широко используемых браузерах.
Экспериментальная функция: Эта технология является экспериментальной
Перед использованием в production внимательно ознакомьтесь с таблицей совместимости с браузерами.
Экспериментальная функция: Эта технология является экспериментальной
Перед использованием в production внимательно ознакомьтесь с таблицей совместимости с браузерами.
calc-size() CSS-функция позволяет выполнять вычисления со значениями внутреннего размера, такими как auto, fit-content и max-content; обычная функция calc() этого не поддерживает.
Возвращаемые значения calc-size() также можно интерполировать, что позволяет использовать ключевые слова размеров в анимациях и переходах. Фактически, включение calc-size() в значение свойства автоматически применяет к выбранному элементу interpolate-size: allow-keywords.
Однако следует учитывать, что interpolate-size наследуется, поэтому его применение к элементу позволяет интерполировать ключевые слова внутреннего размера для каждого свойства, применённого к этому элементу и его дочерним элементам. В результате для включения анимации внутренних размеров предпочтительно использовать interpolate-size. Используйте calc-size() для включения анимации внутренних размеров только в том случае, если для неё также требуются вычисления.
Синтаксис
/* Pass a value through calc-size() */ calc-size(auto, size) calc-size(fit-content, size) /* Perform a calculation */ calc-size(min-content, size + 100px) calc-size(fit-content, size / 2) /* Calculation including a function */ calc-size(auto, round(up, size, 50px))
Параметры
Синтаксис функции calc-size() выглядит следующим образом:
calc-size(<calc-size-basis>, <calc-sum>)
Параметры:
-
<calc-size-basis> - Значение (чаще всего — внутренний размер), над которым нужно выполнить вычисление.
-
<calc-sum> - Выражение, задающее вычисление, которое необходимо выполнить над
<calc-size-basis>.
Возвращаемое значение
Возвращает значение, равное <calc-size-basis>, модифицированному выражением <calc-sum>. Поскольку значение <calc-size-basis> является значением внутреннего размера, возвращаемое значение представляет собой модифицированное значение внутреннего размера, которое ведёт себя так же, как переданное функции значение внутреннего размера.
Описание
В некоторых алгоритмах компоновки браузеров для ключевых слов внутренних размеров предусмотрено особое поведение. Функция calc-size() явно определена для представления внутреннего размера, а не <length-percentage>, что обеспечивает корректность. calc-size() позволяет безопасно и предсказуемо выполнять вычисления со значениями внутренних размеров.
Допустимые значения первого аргумента (<calc-size-basis>)
Первым аргументом calc-size() может быть одно из следующих внутренних значений:
automin-contentmax-contentfit-content-
content(для контейнеров, размер которых задаётся с помощьюflex-basis).
Для этого аргумента также допустимы несколько особых значений:
-
Вложенное значение
calc-size(). Вряд ли вам часто понадобится это делать, но такая возможность предусмотрена, чтобы CSS-переменную CSS всегда можно было использовать в качестве<calc-size-basis>, если переменная содержит допустимое значение для свойства, которому задаётсяcalc-size(). Например, следующий вариант будет работать:section { height: calc-size(calc-size(max-content, size), size + 2rem); }Как и этот:
:root { --intrinsic-size: calc-size(max-content, size); } section { height: calc-size(var(--intrinsic-size), size + 2rem); } -
Другое значение
<calc-sum>с теми же ограничениями, что и у<calc-sum>, указанного для второго аргумента, за исключением того, что нельзя включать ключевое словоsize. Скорее всего, вам не понадобится так делать, поскольку в этом случае вычисление уже не выполняется над значением внутреннего размера. Однако если значение пользовательского свойства — это<calc-sum>, функция всё равно будет работать. Например, следующий вариант будет работать напрямую или при использовании пользовательского свойства со значением300px + 2rem:section { height: calc-size(300px + 2rem, size / 2); } -
Ключевое слово
any, обозначающее неопределённый фиксированный размер. В этом случае ключевое словоsizeнельзя включать во второй аргумент, аcalc-size()возвращает результат вычисления второго аргумента. Например:section { height: calc-size(any, 300px * 1.5); /* Returns 450px */ }
Смешивать разные внутренние размеры в одном вычислении нельзя. Например, max-content - min-content не имеет смысла. calc-size() допускает только одно значение внутреннего размера в каждом вычислении, что позволяет избежать этой проблемы.
Допустимые значения второго аргумента (<calc-sum>)
Второй аргумент calc-size() представляет собой выражение <calc-sum>.
В этом выражении:
- Ключевое слово
sizeобозначает<calc-size-basis>, указанное в качестве первого аргумента. - Операндами могут быть
size, а также любые типы значений, уместные в данном контексте. - Можно использовать операторы
+,-,*и/. - Также можно использовать другие математические функции, например
round(),max()или даже вложенную функциюcalc-size(). - Всё выражение должно соответствовать типу
<length-percentage>и разрешаться в значение<length>.
Включение анимации значений внутренних размеров
Возвращаемые значения calc-size() можно интерполировать, что позволяет анимировать переход между значением <length-percentage> и возвращаемым значением внутреннего размера calc-size().
Примечание: По возможности не следует анимировать свойства блочной модели, чтобы сократить количество операций компоновки и снизить их влияние на производительность (см. Критический путь рендеринга > Компоновка).
Например, можно использовать переход, чтобы анимировать изменение width контейнера между 0 и auto следующим образом:
section {
width: 0;
transition: width ease 1s;
}
section:hover,
section:focus {
width: calc-size(auto, size);
}
В приведённом выше случае никаких вычислений не выполняется: мы помещаем auto в calc-size() и возвращаем его без изменений. Свойство interpolate-size в большинстве случаев упрощает реализацию подобных анимаций, особенно если нужно учитывать несколько анимаций. Оно наследуется, поэтому его достаточно объявить один раз для свойства предка. Это позволяет анимировать переход между 0 и auto без использования calc-size().
Функцию calc-size() следует использовать для включения анимации внутренних размеров только в том случае, если для неё также требуются вычисления. Например, в следующем случае мы анимируем width и применяем вычисление к конечному состоянию внутреннего размера:
section {
width: 0;
transition: width ease 1s;
}
section:hover,
section:focus {
width: calc-size(auto, size + 2rem);
}
Функция calc-size() полезна, когда нужно анимировать переход между внутренним размером и его модифицированной версией. С помощью interpolate-size и calc() это невозможно. Например, следующее определение @keyframes анимирует изменение width контейнера между fit-content и значением, равным 70% от fit-content.
@keyframes narrower {
from {
width: fit-content;
}
to {
width: calc-size(fit-content, size * 0.7);
}
}
Примечание: Обратите внимание, что calc-size() не позволяет анимировать переход между двумя разными значениями внутренних размеров.
Формальный синтаксис
<calc-size()> = calc-size( <calc-size-basis>, <calc-sum> ) <calc-size-basis> = <intrinsic-size-keyword> | <calc-size()> | any | <calc-sum> <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]* <calc-size()> = calc-size( <calc-size-basis>, <calc-sum> ) <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]* <calc-value> = <number> | <dimension> | <percentage> | <calc-constant> | ( <calc-sum> ) <calc-constant> = e | pi | infinity | -infinity | NaN
Примеры
Основы использования calc-size
В этом примере показано, как задать базовые размеры контейнера с помощью calc-size().
HTML
HTML содержит один элемент <section> с дочерним содержимым.
<section>
<h2>Favorite quote</h2>
<p>
Fashion is something so ugly it has to be changed every fifteen minutes.
</p>
</section>
CSS
* {
box-sizing: border-box;
}
section {
font-family: "Helvetica", "Arial", sans-serif;
border: 1px solid black;
}
h2 {
margin: 0;
font-weight: normal;
font-size: 1.1rem;
text-align: center;
letter-spacing: 1px;
}
p {
font-size: 0.8rem;
}
В CSS мы используем flexbox, чтобы расположить дочерние элементы по центру внутри <section>, и задаём для width и height элемента <section> функции calc-size(). Значение width задаётся как сумма fit-content и 6rem. Значение height задаётся как auto, умноженное на два.
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: calc-size(fit-content, size + 6rem);
height: calc-size(auto, size * 2);
}
Остальная часть CSS скрыта для краткости.
Результат
Мы создали горизонтальное и вертикальное пространство, чтобы текст располагался по центру без использования отступов.
Основы анимации calc-size
В этом примере показано, как использовать calc-size() для анимации перехода между заданным размером и внутренним размером. В демонстрации представлен значок персонажа в виде именного бейджа: при наведении указателя или фокусе на нём появляется информация о персонаже. Появление информации реализовано с помощью перехода свойства height между заданной длиной и max-content.
HTML
HTML содержит один элемент <section> с атрибутом tabindex="0", благодаря которому элемент может получать клавиатурный фокус. Элемент <section> содержит элементы <header> и <main>, у каждого из которых есть собственное дочернее содержимое.
<section tabindex="0">
<header>
<h2>Chris Mills</h2>
</header>
<main>
<p>Chris is the silent phantom of MDN.</p>
<ul>
<li><strong>Height</strong>: 3.03m</li>
<li><strong>Weight</strong>: 160kg</li>
<li><strong>Tech Fu</strong>: 7</li>
<li><strong>Bad Jokes</strong>: 9</li>
</ul>
</main>
</section>
CSS
* {
box-sizing: border-box;
}
section {
font-family: "Helvetica", "Arial", sans-serif;
width: 175px;
border-radius: 5px;
background: #eeeeee;
box-shadow:
inset 1px 1px 4px rgb(255 255 255 / 0.5),
inset -1px -1px 4px rgb(0 0 0 / 0.5);
}
header {
padding: 10px;
border-bottom: 2px solid #cccccc;
}
main {
padding: 0.7rem;
}
h2 {
margin: 0;
font-weight: normal;
font-size: 1.1rem;
text-align: center;
letter-spacing: 1px;
}
p,
li {
font-size: 0.8rem;
line-height: 1.5;
}
p {
margin-top: 0;
}
В CSS мы задаём для height элемента <section> значение 2.5rem, а для свойства overflow — hidden, чтобы по умолчанию отображался только <header>. Затем задаём transition, который анимирует <section> height в течение одной секунды при изменении состояния. Наконец, задаём для <section> height вызов функции calc-size() при наведении :hover и установке :focus. Возвращаемое функцией значение эквивалентно max-content + 2rem.
section {
height: 2.5rem;
overflow: hidden;
transition: height ease 1s;
}
section:hover,
section:focus {
height: calc-size(max-content, size + 2rem);
}
Остальная часть CSS скрыта для краткости.
Результат
Попробуйте навести указатель на <section> или установить на него фокус с помощью клавиатуры — его высота анимированно увеличится до полного значения высоты + 2rem, показывая всё содержимое и добавляя 2rem пространства внизу.
Настройка ширины текста на основе fit-content
В этом примере показан контейнер с текстом и кнопка, при нажатии на которую ширина контейнера становится меньше или больше в соответствии с предпочтениями читателя.
HTML
HTML содержит один элемент <section> с дочерним текстовым содержимым, а также элемент <button> для изменения ширины <section>.
<section class="easy-reader">
<h2>Easy reader</h2>
<p>
Eius velit aperiam ipsa. Deleniti eum excepturi ut magni maxime maxime
beatae. Dicta aperiam est laudantium ut illum facere qui officiis. Sunt
deleniti quam id. Quis sunt voluptatem praesentium minima dolorum autem
consequatur velit.
</p>
<p>
Vitae ab incidunt velit aspernatur deleniti distinctio rerum. Et natus sed
et quos mollitia quia quod. Quae officia ex ea. Ducimus ut voluptatem et et
debitis. Quidem provident laboriosam exercitationem similique deleniti.
Temporibus vel veniam mollitia magni unde a nostrum.
</p>
<button class="width-adjust">Narrower</button>
</section>
CSS
* {
box-sizing: border-box;
}
body {
width: 600px;
margin: 0 auto;
}
section {
margin-top: 20px;
font-family: "Helvetica", "Arial", sans-serif;
background: #eeeeee;
border: 2px solid #cccccc;
padding: 0 20px;
position: relative;
}
p,
li {
font-size: 0.8rem;
line-height: 1.5;
}
button {
position: absolute;
top: 2px;
right: 2px;
}
В CSS мы задаём для свойства width элемента <section> значение по умолчанию fit-content. Затем определяем два набора @keyframes: narrower, который анимирует переход от fit-content к 70% от fit-content (вычисленного с помощью calc-size()), и wider, который анимирует те же значения в обратном направлении. Наконец, назначаем эти анимации двум классам — .narrower и .wider. Каждая анимация длится одну секунду, а её конечное состояние сохраняется после завершения.
section {
width: fit-content;
}
@keyframes narrower {
from {
width: fit-content;
}
to {
width: calc-size(fit-content, size * 0.7);
}
}
@keyframes wider {
from {
width: calc-size(fit-content, size * 0.7);
}
to {
width: fit-content;
}
}
.narrower {
animation: narrower 1s ease forwards;
}
.wider {
animation: wider 1s ease forwards;
}
Остальная часть CSS скрыта для краткости.
JavaScript
Код JavaScript позволяет переключаться между узкой и широкой шириной: при нажатии кнопки соответствующий класс применяется к <section>:
const widthAdjustBtn = document.querySelector(".width-adjust");
const easyReader = document.querySelector(".easy-reader");
widthAdjustBtn.addEventListener("click", () => {
if (easyReader.classList.length === 1) {
easyReader.classList.add("narrower");
widthAdjustBtn.textContent = "Wider";
} else if (easyReader.classList.contains("wider")) {
easyReader.classList.replace("wider", "narrower");
widthAdjustBtn.textContent = "Wider";
} else if (easyReader.classList.contains("narrower")) {
easyReader.classList.replace("narrower", "wider");
widthAdjustBtn.textContent = "Narrower";
}
});
Результат
Попробуйте несколько раз нажать <button>, чтобы изменить ширину <section>: сделать её шире или уже. Для этого значение fit-content используется для изменения width.
Использование функции внутри функции calc-size()
Как упоминалось ранее, внутри calc-size() можно использовать другую функцию. В этом примере для элементов field-sizing: content типа <input> задаётся размер по ширине введённого содержимого, а затем функция max() внутри calc-size() гарантирует, что элементы <input> будут не меньше заданного минимального размера и начнут увеличиваться только тогда, когда введённый текст превысит этот размер. Для этого задаётся значение fit-content плюс 20px.
HTML
HTML содержит элемент <form> с тремя текстовыми элементами типа <input>. С каждым элементом <input> связана метка <label>, обеспечивающая доступность формы, а также задан атрибут maxlength, чтобы введённые значения не становились настолько длинными, что нарушат макет формы.
<form>
<div>
<label for="name">Name:</label>
<input type="text" id="name" name="name" maxlength="48" />
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" maxlength="48" />
</div>
<div>
<label for="address">Address:</label>
<input type="text" id="address" name="address" maxlength="60" />
</div>
</form>
CSS
* {
box-sizing: border-box;
}
body {
width: 600px;
margin: 0 auto;
}
form {
margin-top: 20px;
padding: 20px;
font-family: "Helvetica", "Arial", sans-serif;
background: #eeeeee;
border: 2px solid #cccccc;
}
div {
display: flex;
align-items: center;
}
div:not(div:last-child) {
margin-bottom: 20px;
}
В CSS мы задаём для width элементов <label> значение 100px. Для элементов <input> задаём field-sizing: content, чтобы их ширина соответствовала введённому содержимому. По умолчанию у них не было бы ширины, поскольку в них ничего не введено. Чтобы это исправить, задаём для них значение width, равное calc-size(fit-content, max(100px, size + 20px)). Это означает, что их минимальная ширина составляет 100px, даже если значение не введено. Когда введённое значение становится шире, чем 100px, значение их width меняется на fit-content плюс 20px. В результате ширина элементов начинает увеличиваться вместе с размером содержимого, сохраняя при этом промежуток 20px справа.
label {
width: 100px;
}
input {
field-sizing: content;
width: calc-size(fit-content, max(100px, size + 20px));
}
Остальная часть CSS скрыта для краткости.
Результат
Попробуйте ввести текст в поля формы и посмотрите, как они увеличиваются, когда введённые значения начинают достигать минимальной ширины, заданной функцией max().
Спецификации
| Спецификация |
|---|
| Модуль значений и единиц CSS, уровень 5 # calc-size |
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome для Android | Firefox для Android | Opera для Android | Safari на iOS | Samsung Internet | WebView для Android | WebView на iOS | |
calc-size |
129 |
129 |
Нет |
115 |
Нет |
129 |
Нет |
86 |
Нет |
28.0 |
129 |
Нет |
См. также
interpolate-sizecalc()round()- Анимация перехода к height: auto; (и другим ключевым словам внутренних размеров) в CSS на developer.chrome.com (2024)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/calc-size