Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
Experimental: Check browser support before using this in production.
The CSS calc-size()
function enables us to perform calculations using intrinsic size values such as auto
, min-content
, max-content
, and fit-content
. These calculations aren’t possible with “regular” calc()
.
/* Equivalent to auto */
width: calc-size(auto, size);
/* Equivalent to auto plus 100px! */
width: calc-size(auto, size + 100px);
Additionally, the value returned by calc-size()
is interpolated, making it super easy to animate or transition between an extrinsic size value (e.g., 0
) and said intrinsic size value (e.g., auto
). This is because calc-size()
automatically applies interpolate-size: allow-keywords
to the selector. In the example below, we double the width of the <div>
on hover despite not even knowing its original width.
<div>lorem</div>
div {
transition: 300ms;
display: inline-block;
}
div:hover {
width: calc-size(auto, size * 2);
}
At the time of writing we can use calc-size()
in Chrome and Edge from version 129, but check the browser support section below for up-to-date information.
Syntax
calc-size(<calc-size-basis>, <calc-sum>)
Arguments
<calc-size-basis>
: The intrinsic size value to interpolate pre-calculation (can beauto
,min-content
,max-content
, orfit-content
). This value ultimately resolves to a<length>
.<calc-sum>
: The expression containing<calc-size-basis>
(represented by thesize
operand).
In plain English, we start by specifying the intrinsic size value that we want to interpolate (e.g., auto
), which goes on to be represented by the size
operand. Then, after a comma, we write an expression that involves said operand (e.g., size * 2
). This expression can even include other CSS functions such as min()
calc()
, as well as CSS variables.
Basic usage
/* Interpolation only */
width: calc-size(auto, size);
width: calc-size(min-content, size);
width: calc-size(max-content, size);
width: calc-size(fit-content, size);
/* Interpolation and calculation */
width: calc-size(auto, size * 2);
width: calc-size(auto, size / 2);
width: calc-size(auto, size + 100px);
width: calc-size(auto, size - 100px);
/* Calculation with additional function */
width: calc-size(auto, min(200px, size * 2));
/* Calculation with CSS variable */
width: calc-size(auto, size * var(--multiplier));
/* Calculation with additional function and CSS variable */
width: calc-size(auto, min(300px, size * var(--multiplier)));
When would we just interpolate? Consider this example:
<details>
<summary>Summary</summary>
Details
</details>
details::details-content {
height: 0;
/* Not important */
overflow-y: clip;
transition: 300ms allow-discrete;
}
details[open]::details-content {
/* Interpolation only */
height: calc-size(auto, size);
}
Here we’re setting height: 0
on the disclosure’s content and then letting it slide out when toggled. We don’t want to perform any calculations with the size
, we just want the content to expand to its intrinsic height.
If you’d prefer to write height: auto
instead of height: calc-size(auto, size)
, declare interpolate-size: allow-keywords
within the details::details-content
rule. This will ensure that all intrinsic size values within that rule are interpolated automatically. Alternatively, declare it within the :root
rule to enforce this behavior throughout the document:
/* Interpolate intrinsic sizes */
:root {
interpolate-size: allow-keywords;
}
Then transition/animate like this:
details::details-content {
height: 0;
/* Not important */
overflow-y: clip;
transition: 300ms allow-discrete;
}
details[open]::details-content {
/* height: calc-size(auto, size); */
height: auto;
}
You’ll still need to use calc-size()
for calculations though.
Example: Star ratings
<div data-rating="2.25">
<i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i>
</div>
div {
width: calc-size(min-content, size * calc(attr(data-rating type(<number>)) / 5));
overflow: hidden;
}
What we have here is five Font Awesome stars wrapped in a <div>
with a data-rating="2.25"
attribute value, which we can assume has been generated by templating logic. In the CSS, we read this value using attr(data-rating type(<number>))
and divide it by the total number of stars (5
) using calc()
(calc(attr(data-rating type(<number>)) / 5)
), leaving us with 0.45
. Finally, we interpolate the <div>
’s width (min-content
) and multiply it by the 0.45
(width: calc-size(min-content, size * calc(attr(data-rating type(<number>)) / 5))
), cutting the width short to show only 2.25 stars.
Browser support
calc-size()
has been supported in Chrome and Edge since version 129 (September 2024), but isn’t currently supported in Safari or Firefox (as of April 2025). The interpolate-size
property has the exact same degree of browser support, so it’s not a viable alternative for calc-size()
when interpolating sizes.
However, what we can do is detect browser support for calc-size()
using @supports
, and then use it conditionally:
@supports (width: calc-size(auto, size)) {
/* calc-size() supported */
}
@supports not (width: calc-size(auto, size)) {
/* calc-size() not supported */
}
The same thing in JavaScript:
if (CSS.supports("width: calc-size(auto, size)")) {
/* calc-size() supported */
}
if (!CSS.supports("width: calc-size(auto, size)")) {
/* calc-size() not supported */
}