Debug panel

Close debug panel
Roma’s Unpolished Posts

Observation: Clamp to Infinity

Published on:
Last updated on:
Categories:
CSS Clamp, CSS 61, Observation 9
Current drink:
Yunnan tea

Min and Max

A confession: I constantly get confused by min() and max() comparison functions — in CSS and JS alike. I often use them for the lower and upper bounds, and, in my head, it is not intuitive to use min() for the “upper” bound, and max() for the “lower”.

Overall, it frequently takes me a few moments to parse any code that contains these mins and maxes.

That’s why I really like the clamp() function for defining the bounds — I find it much easier to understand and parse in my head.

A Problem with clamp() in CSS

After another time of me using min() (or was it max()?), I wondered: could I just always use clamp(), even if I need to have only the lower or the upper bound?

The function itself does not provide a simple way to omit one of the bounds — all the arguments are required, and there is no none value that could be used instead of a value.

Update from 2024-02-19

  • On December 15, 2023, Lea Verou proposednone keyword that could be used to achieve the same result that I’m referring to in this article.
  • On February 14, 2024, CSSWG resolved to add it to the specs!

Looking for a Solution

The first thought is to use a massive value, like 99999px for the upper bound, and a similar negative one for the lower. But I would really like to evade magical numbers like that, which, potentially, could backfire in case I’ll actually need to handle bigger values.

My second thought was: hey, didn’t we get the infinity in CSS recently?

<div style="
	border: solid clamp(-infinity, 1em, infinity);
">test</div>

Ah, but it does not work:

test

A live example that shows just an unstyled word “test”.

Of course, because infinity is a <number>, and clamp() requires all arguments to be of the same type.

My third thought was to divide by zero. A perfectly normal thought for me!

<div style="
	border: solid clamp(-1px/0, 1em, 1px/0);
">test</div>

This works:

test

A live example that shows a thick border around the word “test”.

Then I started to write this post and gather the links to specs, as I often do. And guess what, there is a note in the specs:

As these keywords are <number>s, to get an infinite length, for example, requires an expression like calc(infinity * 1px).

Of course, this works as well:

<div style="
	border: solid
		clamp(1px * -infinity, 1em, 1px * infinity);
">test</div>
test

A live example that shows a thick border around the word “test”.

I did use 1px * -infinity instead of -1px * infinity just to test that it works as it should.

But this is so verbose! Is the division by zero a hack? I’m not sure, but it is much more concise, and also is defined in the specs as a valid way to get the infinity:

Dividing a value by zero produces either +∞ or −∞, according to the standard sign rules.

Use Cases

Would I use this in the future? I don’t know. I think it is still a good idea to think of using the clamp() instead of the min() or max() right away — very often you’d still have to add the other bound later, and with clamp() it would be so much easier!

Another case where this can be potentially helpful is when we’re setting up some API using CSS variables — we could provide a way to clamp something optionally, where the default values for both boundaries would be infinities, but could be provided via CSS variables.

Aside: Starting to Record Observations

One thing I wanted to start doing — and this blog now would allow me to — start writing about some observations I sometimes make when experimenting with CSS. Not always something I find has obvious use cases, and not always I have time to write a proper long and polished article like I do at my main site. However, how many interesting things I did stumble upon and did not share in pursuit of perfectionism?

Posting every day for almost 2 weeks made me think a bit less about the polish of the text, and more about “just doing it”. Which I did try to do today.

Please share your thoughts about this on Mastodon!