calc-size()
Ограниченная доступность
Эта функция не поддерживается Baseline, так как она не работает во всех широко используемых браузерах.
Экспериментально: Это экспериментальная технология
Перед использованием в производстве внимательно ознакомьтесь со таблицей совместимости браузеров.
Функция 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 в качестве<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> ]*
<calc-value> =
<number> |
<dimension> |
<percentage> |
<calc-keyword> |
( <calc-sum> )
<calc-keyword> =
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
В 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
В CSS мы устанавливаем height для <section> в 2.5rem и overflow в hidden, чтобы отображалось только <header> по умолчанию, а затем определяем transition, который анимирует <section> height в течение 1 секунды во время изменения состояния. Наконец, мы устанавливаем значение <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
В CSS мы устанавливаем width контейнера по умолчанию в 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> между широкой и узкой шириной чтения, достигнутой путем манипулирования width на основе значения fit-content.
Использование функции внутри функции calc-size()
Как упоминалось ранее, можно использовать другую функцию внутри calc-size(). В этом примере устанавливается field-sizing: content для элементов <input>, чтобы сделать их шириной, равной введённому содержанию, а затем используется функция max() внутри calc-size() для обеспечения того, что элементы имеют минимальный размер, и начинают увеличиваться только тогда, когда введённый текст становится шире этого размера — устанавливая их значение равным 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
В CSS мы устанавливаем width для элементов <label> в 100px. Мы устанавливаем field-sizing: content для элементов <input>, чтобы сделать их шириной, равной введённому содержанию, — по умолчанию у них нет ширины, поскольку ничего не будет введено. Для исправления этого, мы устанавливаем их значения 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 Values and Units Module Level 5 # calc-size |
Совместимость с браузерами
| Рабочий стол | Мобильные устройства | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari iOS | Samsung Internet | WebView Android | |
calc-size |
129 | 129 | Нет | 115 | Нет | 129 | Нет | Нет | Нет | Нет | 129 |
См. также
interpolate-sizecalc()round()- Анимация до height: auto; (и другие ключевые слова для определения размеров по умолчанию) в CSS на developer.chrome.com (2024)
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/calc-size