CSS infinity (and -infinity!) solve some pretty specific problems elegantly, but can also just be plain fun to use.
Showing support for infinity, -infinity, NaN, pi, and e
Lets spur creative CSS juices with infinity and follow a couple use cases.
Basics and gotchas #
infinity and -infinity need to always be wrapped in calc().
If you want it to represent a dimension, it also needs to be multiplied by a unit like:
div {
border-radius: calc(infinity * 1px);
z-index: calc(infinity);
}
Not quite limited to calc() too, you can use it with other calc()-like scenarios like clamp(), min(), max(), etc, which we'll dig into a bit 🤘🏻
1. Circles and Pills #
Before infinity, I would have used scientific notation like 1e9px (which is 1000000000px) to create a "big enough" radius for circles and pills at any size.
But with infinity..!?
.radius-full {
border-radius: calc(infinity * 1px);
}
2. Perma-state #
Setting duration calc(infinity * 1s) makes an animation/transition so long that it appears to be frozen ⛄️
Hover over those boxes and the duration will be pinned to happen over infinity seconds, sticking the state for the duration of the page's life.
I like how the duration of your hover is permanently made visible too. Visible millisecond duration via background color.
3. z-index #
Need to beat z-index: 999999999 or something?
.tippy-top-of-stacking-context {
z-index: calc(infinity)
}
This will max out at the largest int a browser allows: 2147483647. Speaking of that number, you can see it by using counters like this:
.css-max-int {
counter-reset: cssInt calc(infinity);
&::after {
content: counter(cssInt);
}
}
See!
4. To infinity and beyond #
Use calc(infinity * 1px) to remove the floor or ceiling of a clamp.
div {
inline-size: clamp(
calc(-infinity * 1px), /* no floor */
100%,
calc(infinity * 1px) /* no ceiling */
);
}
5. Freeze view transitions #
Make view transitions never complete.
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation-duration: calc(infinity * 1s);
}
The ::view-transition tree stays in the devtools DOM, giving you an opportunity to inspect or tweak.
You can also freeze and inspect animations using the Animations panel in devtools.
6. Responsive radius #
Another scenario where I would have reached for making a large number with scientific notation, is a responsive border radius.
.viewport-responsive-radius {
border-radius: clamp(0px, (100vi - 100%) * infinity, 20px);
}
.container-responsive-radius {
border-radius: clamp(0px, (100cqi - 100%) * infinity, 20px);
}
If the elements inline-size is less than 100vi, the radius will be 0. If it's greater than 100vi, the radius will be 20px.
There are a set of these available in Open Props.
7. Bools #
Clamp an arbitrary number down to exactly 0 or 1, then use it:
.flippy {
--solo: clamp(0, (2 - sibling-count()) * infinity, 1);
--crowded: clamp(0, (sibling-count() - 5) * infinity, 1);
flex-grow: calc(1 - var(--solo));
font-size: calc(1rem - var(--crowded) * 0.125rem);
}
One variable now can drive color, offset, opacity, gaps, whatever.
8. Backdrop #
You can use the spread feature of box-shadow to create a non-interactive backdrop:
.backdrop {
box-shadow: 0 0 0 calc(infinity * 1px) #0005;
}
Paint past the "entire viewport".
9. Scroll Trigger #
Trigger a scroll driven transition in, and never transition out.
.nav-title {
timeline-trigger-activation-range-end: calc(infinity * 1px);
}
.product-title {
animation: slide-and-fade 150ms ease both;
animation-trigger: play-forwards play-backwards;
}
Though you'll see in the demo I use scroll 100% which is a specced way that feels closer to the intent I was going for, in that I wanted the range end to be the end of the scroll area.
Try it:
Also, just for funsies to share, here's the scroll driven version of the same navbar effect. Doesn't use infinity, but fun to try and compare scroll-triggered vs scroll-driven animation.
Thats all #
Hope you found that interesting!
Comment with your own creative uses of infinity?

