|
123456789101112131415161718192021222324252627282930313233343536 |
- title: Playing with Infinity in CSS
- url: https://codersblock.com/blog/playing-with-infinity-in-css/
- hash_url: 1f4e359d100592aee6e46505a40b2a01
- archive_date: 2024-03-06
- og_image: https://codersblock.com/assets/images/blog/infinity-light-streaks.png
- description: CSS has an infinity constant. When I first learned about this, my brain lit up with all kinds of absurd possibilities. Let’s discuss! There might even be some...
- favicon: https://codersblock.com/favicon-32x32.png
- language: en_US
-
- <div class="post-content"><p>CSS has an <code>infinity</code> constant. When I first learned about this, my brain lit up with all kinds of absurd possibilities. Let’s discuss! There might even be some practical use cases.</p><p>No promises, though.</p><p>Before we get into things, there’s one important ground rule: <code>infinity</code> can only be used inside a <code>calc()</code> statement. Alright, let’s go.</p><p>Have you ever needed an element to appear on top of everything else, but the constantly escalating <code>z-index</code> arms race forces you to resort to higher and higher <code>z-index</code> values?</p><p>End the battle. Use <code>infinity</code> to get the highest possible <code>z-index</code> and win forever.</p><p>In the demo below, there is no possible <code>z-index</code> value for the blue card that will put it above the purple card with <code>z-index: calc(infinity)</code>. Give it a try!</p><p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="ExMGBVP" data-user="lonekorean"><span>See the Pen <a href="https://codepen.io/lonekorean/pen/ExMGBVP">Unbeatable z-index</a> by Will Boyd (<a href="https://codepen.io/lonekorean">@lonekorean</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><p>What happens when you create a <code><div></code> with a <code>width</code> and <code>height</code> of <code>infinity</code> pixels?</p><pre class="language-css"><code class="language-css"><span class="token selector">.big</span> <span class="token punctuation">{</span>
- <span class="token property">width</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * 1px<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * 1px<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span></code></pre><p>Notice we’re multiplying <code>infinity</code> by <code>1px</code> to turn it into a pixel length.</p><p>Here’s a demo showing the result, with some extra output so we can get a better idea of what’s happening in the browser.</p><p class="codepen" data-height="440" data-default-tab="result" data-slug-hash="JjzwQYR" data-user="lonekorean"><span>See the Pen <a href="https://codepen.io/lonekorean/pen/JjzwQYR">The Largest Possible Element</a> by Will Boyd (<a href="https://codepen.io/lonekorean">@lonekorean</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><p>The values under <code>getComputedStyle()</code> are what the CSS properties resolve to. The values under <code>getBoundingRect()</code> reflect the actual size of the rendered <code><div></code> in the viewport. Here’s the code snippet.</p><pre class="language-javascript"><code class="language-javascript">
- <span class="token keyword">const</span> computed <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">getComputedStyle</span><span class="token punctuation">(</span>bigEl<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">const</span> computedWidth <span class="token operator">=</span> computed<span class="token punctuation">.</span><span class="token function">getPropertyValue</span><span class="token punctuation">(</span><span class="token string">'width'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">const</span> computedHeight <span class="token operator">=</span> computed<span class="token punctuation">.</span><span class="token function">getPropertyValue</span><span class="token punctuation">(</span><span class="token string">'height'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
-
-
- <span class="token keyword">const</span> rect <span class="token operator">=</span> bigEl<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">const</span> rectWidth <span class="token operator">=</span> rect<span class="token punctuation">.</span>width <span class="token operator">+</span> <span class="token string">'px'</span><span class="token punctuation">;</span>
- <span class="token keyword">const</span> rectHeight <span class="token operator">=</span> rect<span class="token punctuation">.</span>height <span class="token operator">+</span> <span class="token string">'px'</span><span class="token punctuation">;</span></code></pre><p>First of all, <code>infinity</code> in CSS is not actually infinite. It’s just a really big number. My disappointment is immeasurable, unlike <code>infinity</code> in CSS.</p><p>On my machine (Windows desktop using Chrome) the total area of the <code><div></code> in the demo is <strong>33,554,428px</strong> squared, which works out to roughly <strong>79km<sup>2</sup></strong>. Not bad! But also not infinite.</p><p>Notice I said “on my machine” in that last paragraph. Although <code>infinity</code> is supported in all major browsers, the value it resolves to can be inconsistent across browsers and operating systems.</p><p>Some examples from the demo above:</p><ul><li>Chrome on macOS gives me <strong>16,777,214px</strong> for both the <code>width</code> and <code>height</code>, half what I get on Windows.</li><li>Firefox reports a <code>width</code> of <strong>1.78957e+7px</strong> when using <code>getComputedStyle()</code> and <strong>8,947,849px</strong> when using <code>getBoundingRect()</code>.</li><li>Firefox doesn’t even try with <code>height: calc(infinity * 1px)</code> — just ignores it. But setting <code>height: 17895697px</code> (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=552412#c3">the largest CSS length Firefox allows</a>) works. I don’t know why Firefox doesn’t resolve <code>height</code> to that value like it seems to do with <code>width</code>.</li></ul><p>On top of all that, <code>infinity</code> can resolve to different values based on which CSS property you’re using it with. Remember that <code>z-index</code> example from earlier? The value of <code>infinity</code> there was <strong>2,147,483,647</strong> — consistent across all browsers I tested, but different from the various <code>width</code> and <code>height</code> values we just saw.</p><p>All these wacky values for <code>infinity</code> are not randomly picked, of course — they are a result of how the numbers are being stored. For example, <strong>2,147,483,647</strong> is <strong>2<sup>31</sup> - 1</strong>, the largest possible value for a signed 32-bit integer.</p><p>What happens if you try to animate an element to <code>infinity</code>, like this?</p><pre class="language-css"><code class="language-css"><span class="token selector">.interstellar</span> <span class="token punctuation">{</span>
- <span class="token property">animation</span><span class="token punctuation">:</span> go 10s<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
-
- <span class="token atrule"><span class="token rule">@keyframes</span> go</span> <span class="token punctuation">{</span>
- <span class="token selector">to</span> <span class="token punctuation">{</span> <span class="token property">translate</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * 1px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
- <span class="token punctuation">}</span></code></pre><p>Turns out the element will immediately jump to the end of the animation and stay there for the duration. So in this case, the element stays as far off to the right as the browser can handle for the entire 10 seconds.</p><p>Makes sense. There are no incremental values on the way to infinity. A fraction of infinity is still infinity. So for every frame of the animation, the animated value is infinity.</p><p>What happens when you set an infinite <code>animation-delay</code>?</p><pre class="language-css"><code class="language-css"><span class="token selector">.interstellar</span> <span class="token punctuation">{</span>
- <span class="token property">animation-delay</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * 1s<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span></code></pre><p>You can probably guess. The animation never starts.</p><p>Would you ever actually want to use <code>infinity</code> in your CSS? Maybe! Sometimes you just need a huge value (whatever it is) and <code>infinity</code> can give that to you.</p><p>For example, you can make a pill shape by using <code>border-radius</code> with a (non-percentage) length value. Using a value bigger than you need won’t change the shape and is actually a good idea in case the element changes size.</p><pre class="language-css"><code class="language-css"><span class="token selector">div</span> <span class="token punctuation">{</span>
- <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * 1px<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span></code></pre><p class="codepen" data-height="340" data-default-tab="result" data-slug-hash="LYaMKpx" data-user="lonekorean"><span>See the Pen <a href="https://codepen.io/lonekorean/pen/LYaMKpx">Pill Shape</a> by Will Boyd (<a href="https://codepen.io/lonekorean">@lonekorean</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><p>Another possible use is with a <a href="https://webaim.org/techniques/css/invisiblecontent/#offscreen">common snippet of CSS</a> used to make content “screen reader only” by positioning it way off the side of the page.</p><pre class="language-css"><code class="language-css"><span class="token selector">.screen-reader-only</span> <span class="token punctuation">{</span>
- <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
- <span class="token property">left</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>infinity * -1px<span class="token punctuation">)</span><span class="token punctuation">;</span>
-
-
- <span class="token punctuation">}</span></code></pre><p>But is <code>infinity</code> really any better than some arbitrarily big value like <code>9999px</code>? Functionally, no. Same end result. But I think it does help make code more self-documenting, because <code>infinity</code> conveys intent. It expresses that it’s all about the magnitude, not a specific magic number.</p><p>Dividing by zero will give you <code>infinity</code>. In other words, <code>calc(1 / 0)</code> and <code>calc(infinity)</code> are the same. This also works with units. So you can do something like <code>calc(1px / 0)</code> and get the same value as <code>calc(infinity * 1px)</code>.</p><p>Good to know, but I’d still use <code>infinity</code> directly to make the CSS more obvious.</p><p>There’s also a <code>-infinity</code> constant that gives you the smallest possible value. No surprises here, it’s the same as multiplying <code>infinity</code> by <code>-1</code>.</p><p>To recap, the main thing to know about CSS <code>infinity</code> is that it’s essentially shorthand for the largest possible value in a particular situation. This value can and will change between browsers, operating systems, and CSS properties.</p><p>Whether or not to use <code>infinity</code> is up to you. Browser support is <a href="https://caniuse.com/mdn-css_types_calc-constant_infinity">pretty good</a>, and <code>infinity</code> can be a good indicator of intention that makes your CSS more readable, but it’s certainly not mandatory.</p></div>
|