123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- <!doctype html><!-- This is a valid HTML5 document. -->
- <!-- Screen readers, SEO, extensions and so on. -->
- <html lang="en">
- <!-- Has to be within the first 1024 bytes, hence before the `title` element
- See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
- <meta charset="utf-8">
- <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
- <!-- The viewport meta is quite crowded and we are responsible for that.
- See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <!-- Required to make a valid HTML5 document. -->
- <title>Playing with Infinity in CSS (archive) — David Larlet</title>
- <meta name="description" content="Publication mise en cache pour en conserver une trace.">
- <!-- That good ol' feed, subscribe :). -->
- <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
- <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
- <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
- <link rel="manifest" href="/static/david/icons2/site.webmanifest">
- <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
- <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
- <meta name="msapplication-TileColor" content="#f7f7f7">
- <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
- <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
- <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
- <!-- Is that even respected? Retrospectively? What a shAItshow…
- https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
- <meta name="robots" content="noai, noimageai">
- <!-- Documented, feel free to shoot an email. -->
- <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
- <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <script>
- function toggleTheme(themeName) {
- document.documentElement.classList.toggle(
- 'forced-dark',
- themeName === 'dark'
- )
- document.documentElement.classList.toggle(
- 'forced-light',
- themeName === 'light'
- )
- }
- const selectedTheme = localStorage.getItem('theme')
- if (selectedTheme !== 'undefined') {
- toggleTheme(selectedTheme)
- }
- </script>
-
- <meta name="robots" content="noindex, nofollow">
- <meta content="origin-when-cross-origin" name="referrer">
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://codersblock.com/blog/playing-with-infinity-in-css/">
-
- <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
-
-
- <article>
- <header>
- <h1>Playing with Infinity in CSS</h1>
- </header>
- <nav>
- <p class="center">
- <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
- </svg> Accueil</a> •
- <a href="https://codersblock.com/blog/playing-with-infinity-in-css/" title="Lien vers le contenu original">Source originale</a>
- <br>
- Mis en cache le 2024-03-06
- </p>
- </nav>
- <hr>
- <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>
- </article>
-
-
- <hr>
-
- <footer>
- <p>
- <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
- </svg> Accueil</a> •
- <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
- </svg> Suivre</a> •
- <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
- </svg> Pro</a> •
- <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
- </svg> Email</a> •
- <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
- </svg> Légal</abbr>
- </p>
- <template id="theme-selector">
- <form>
- <fieldset>
- <legend><svg class="icon icon-brightness-contrast">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
- </svg> Thème</legend>
- <label>
- <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
- </label>
- <label>
- <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
- </label>
- <label>
- <input type="radio" value="light" name="chosen-color-scheme"> Clair
- </label>
- </fieldset>
- </form>
- </template>
- </footer>
- <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
- <script>
- function loadThemeForm(templateName) {
- const themeSelectorTemplate = document.querySelector(templateName)
- const form = themeSelectorTemplate.content.firstElementChild
- themeSelectorTemplate.replaceWith(form)
-
- form.addEventListener('change', (e) => {
- const chosenColorScheme = e.target.value
- localStorage.setItem('theme', chosenColorScheme)
- toggleTheme(chosenColorScheme)
- })
-
- const selectedTheme = localStorage.getItem('theme')
- if (selectedTheme && selectedTheme !== 'undefined') {
- form.querySelector(`[value="${selectedTheme}"]`).checked = true
- }
- }
-
- const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
- window.addEventListener('load', () => {
- let hasDarkRules = false
- for (const styleSheet of Array.from(document.styleSheets)) {
- let mediaRules = []
- for (const cssRule of styleSheet.cssRules) {
- if (cssRule.type !== CSSRule.MEDIA_RULE) {
- continue
- }
- // WARNING: Safari does not have/supports `conditionText`.
- if (cssRule.conditionText) {
- if (cssRule.conditionText !== prefersColorSchemeDark) {
- continue
- }
- } else {
- if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
- continue
- }
- }
- mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
- }
-
- // WARNING: do not try to insert a Rule to a styleSheet you are
- // currently iterating on, otherwise the browser will be stuck
- // in a infinite loop…
- for (const mediaRule of mediaRules) {
- styleSheet.insertRule(mediaRule.cssText)
- hasDarkRules = true
- }
- }
- if (hasDarkRules) {
- loadThemeForm('#theme-selector')
- }
- })
- </script>
- </body>
- </html>
|