Roma’s Unpolished PostsRoma’s personal bloghttps://blog.kizu.dev/enApps with Presence on Mastodonhttps://blog.kizu.dev/apps-with-presence-on-mastodon/https://blog.kizu.dev/apps-with-presence-on-mastodon/A small thing I have started doing recently is trying to choose an app that I’m going to use for some purpose based on its presence in Mastodon.Thu, 13 Jul 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Appleseed Cast — Storms</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>For a few years I had a “tools burnout”, where I almost completely stopped using various apps, tools, and plugins.</p>
<p>While all of these could be very handy, things can get overwhelming pretty fast. Every tool comes with a certain cognitive load: the necessity to learn it, to remember how it works, and then how to use it. Not always, it can be worth it. Another problem — the sheer number of options. Reading about all the tools that do a similar thing, comparing them, and trying them — all that takes a lot of time and effort.</p>
<p>What if I could simplify it a bit?</p>
<p>Recently, I decided to start using more tools again and looked into what was available.</p>
<p>One interesting approach I found for narrowing down the choices: choosing only the things that have a presence on Mastodon.</p>
<p>Why?</p>
<ol>
<li>
<p>If it is on Mastodon, the tool is relatively recent, and has some level of support.</p>
</li>
<li>
<p>If the authors of that tool see Mastodon as worthy of their presence, they are likely to share a common set of values with me. But if they continue to use only Twitter or are happy to join Bluesky or Threads but not Mastodon, it is very telling.</p>
</li>
<li>
<p>With a tool present in Fediverse, I have a very convenient way to follow the updates for it or to reach its developers if needed.</p>
</li>
<li>
<p>And, of course, as I already mentioned, this narrows down the available choices a lot.</p>
</li>
</ol>
<h2 id="things-idid-choose-this-way">Things I Did Choose This Way</h2>
<h3 id="overcast"><a href="https://overcast.fm/">Overcast</a></h3>
<p><a href="https://mastodon.social/@overcastfm">@[email protected]</a> — a podcasts app.</p>
<p>I got fed up with the Apple Podcasts app (it is bad) and decided to find something better. Even though Overcast is not available on macOS as a native app, it is possible to install the iPad version of it, and it works pretty nicely and syncs with the version I’m using on the iPhone.</p>
<h3 id="netnewswire"><a href="https://netnewswire.com/">NetNewsWire</a></h3>
<p><a href="https://indieweb.social/@NetNewsWire">@[email protected]</a>) — an RSS/Atom reader.</p>
<p>I finally decided to return to reading RSS and wanted to find a good reader. NetNewsWire seems perfect now: it has a very similar feel to the Reeder I used a long time ago, is free and open source, and also syncs with the iOS version perfectly.</p>
<h3 id="obsidian"><a href="https://obsidian.md/">Obsidian</a></h3>
<p><a href="https://mas.to/@obsidian">@[email protected]</a> — a knowledge base/note-taking app from the authors of <a href="https://dynalist.io/">Dynalist</a>.</p>
<p>I did know about Obsidian for a while and tried it once or twice, but I did not yet stick with it beforehand. The final straw was <a href="https://chirp.enworld.org/@phd20/110678570703135302">one post in mastodon</a>:</p>
<iframe src="https://chirp.enworld.org/@phd20/110678570703135302/embed" width="100%" style="height: 17em" allowfullscreen sandbox="allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-forms"></iframe>
<p>This post did mention <a href="https://phd20.com/blog/quick-dungeon-map-prep-obsidian/">an article</a> about a plugin for Obsidian that uses <a href="https://leafletjs.com/">Leaflet</a> under the hood (also on mastodon — <a href="https://front-end.social/@[email protected]">@[email protected]</a>) for an RPG dungeon map.</p>
<p>I knew that it was possible to create plugins for Obsidian, but only now has it clicked for me that it is based on the web platform: plugins can be written with JS and everything can be styled with CSS, with CSS snippets being a thing that people actively share. <strong>Edit:</strong> I already wrote an article about one such snippet — <a href="/fixing-obsidians-markdown-display-with-css/">“Fixing Obsidian’s Markdown Display with CSS”</a>.</p>
<p>There is also an unofficial <a href="https://lemmy.world/c/obsidianmd">Lemmy community</a> for it, and I did subscribe to it in Mastodon, trying to see how the interactions between different entities in the Fediverse work.</p>
<h3 id="thunderbird"><a href="https://thunderbird.net/">Thunderbird</a></h3>
<p><a href="https://mastodon.online/@thunderbird">@[email protected]</a> — an email client.</p>
<p>For a long time, I did use web apps, but I think it is time to get back to desktop apps. Owning your content is nice, and with the ways services evolve and change, relying on an online entity to store everything for you started to feel wrong to me. I would prefer to have all my emails on hand locally, available offline.</p>
<h3 id="astro"><a href="https://astro.build/">Astro</a></h3>
<p><a href="https://m.webtoo.ls/@astro">@[email protected]</a> — a web framework this blog is running on.</p>
<p>I wanted to try it for a while, and one of the reasons was its presence in Mastodon. I think the front-end community is thriving on Mastodon, and I would not hesitate to recommend any newcomer join in — so many great developers and authors are now there!</p>
<h2 id="things-i-used-before">Things I Used Before</h2>
<p>The tools above were the ones I started to use after I joined Mastodon and decided to narrow down my choices based on Mastodon presence. But some tools I was already using were also on Mastodon.</p>
<h3 id="ia-writer"><a href="https://ia.net/writer">iA Writer</a></h3>
<p><a href="https://mastodon.online/@ia">@[email protected]</a> — a markdown writing app.</p>
<p>I’ve been using it <em>for years</em> (since June 26, 2011, according to the receipts). As someone who has always loved typography, I always liked how they approached it in the iA Writer and on their site.</p>
<p>While I’m using other apps for notes, outlines, etc. (like the Obsidian I started using recently), I continue to use iA Writer a lot, as I genuinely love the writing experience it provides.</p>
<h3 id="pixelmator-pro"><a href="https://www.pixelmator.com/pro/">Pixelmator Pro</a></h3>
<p><a href="https://mastodon.social/@pixelmator">@[email protected]</a> — an image and video editor.</p>
<p>I purchased it a few years ago and use it for any raster images I need to edit. I recently started using it for editing the videos of the examples I put in articles on my <a href="https://kizu.dev">main site</a> — it is very easy to cut and crop videos there.</p>
<h3 id="baba-is-you"><a href="https://www.hempuli.com/baba/">Baba is You</a></h3>
<p><a href="https://mastodon.gamedev.place/@BabaIsYou">@[email protected]</a> by <a href="https://mastodon.gamedev.place/@Hempuli">@[email protected]</a> — my favorite game.</p>
<p>Surprise — it is not an app or a tool, but a game :) A very hard puzzle game, and I can recommend it to <em>anyone</em>. When I play it, it feels like it trains the same neurons that are responsible for CSS — utilizing, changing, and combining the rules on the fly to achieve previously unthinkable things through logical insights.</p>
<hr>
<p>For now, that’s it! I will not update this list if I start using something else, but I might write a new post here about it (and cross-link them).</p>
<p>There is also another idea I had for a while — to create something like a “gear” page where I could gather and link to all the software and hardware I use. Maybe one day I will create it as a page on my site. We’ll see!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/110707128336196582">on Mastodon</a>!</p>Scroll-Driven Animations in Stable Chromehttps://blog.kizu.dev/scroll-driven-animations-in-stable-chrome/https://blog.kizu.dev/scroll-driven-animations-in-stable-chrome/Scroll-driven animations did land in stable Chrome 115, which means that a lot of the techniques I wrote about are now possible to use there.Wed, 26 Jul 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Mammal Hands — Floating World</dd><dt>Current drink:</dt><dd>White tea with litchi, pineapple, mango, and papaya</dd></dl><hr /><p>Before my first <a href="https://kizu.dev/anchor-positioning-experiments/">experiments with anchor positioning</a>, I had not previously written about non-production experimental things. I’m usually very practice-oriented and like to play with things that I can just go and put into production. However, a lot of new CSS developments sounded too tasty to leave aside, and when playing with things, I found out that I have a lot to say and contribute.</p>
<p>While there is a long road ahead for anchor positioning itself, I did end up writing three articles about scroll-driven animations while they were being developed in Chrome Canary, describing a number of practical techniques:</p>
<ol>
<li><a href="https://kizu.dev/scroll-driven-animations/">“Future CSS: Wishes Granted by Scroll-driven Animations”</a></li>
<li><a href="https://kizu.dev/fit-to-width-text/">“Fit-to-Width Text”</a> </li>
<li><a href="https://kizu.dev/position-driven-styles/">“Position-Driven Styles”</a></li>
</ol>
<p>I did start playing with them when they were under an experimental flag and continued when they were moved outside of it and planned for an eventual release. There were a lot of things I had to adapt to and change in my experiments through the implementation and specs changes — one of the aspects when you touch experimental stuff.</p>
<p>But I’m very happy with what I managed to achieve in my experiments.</p>
<p>Now, starting from Chrome 115, almost all of these experiments actually work in stable Chrome (outside one experiment using <code>timeline-scope</code>)!</p>
<p>That is a bit of a weird feeling. I did come up with a number of experimental techniques that have now become <em>real</em>:</p>
<ul>
<li><a href="https://kizu.dev/scroll-driven-animations/#stuck-states-for-the-sticky-headers"><code>:stuck</code> implementation</a>, which, I’d argue, is even more powerful than the proposed state query version.</li>
<li><a href="https://kizu.dev/scroll-driven-animations/#stuck-states-for-the-sticky-headers">Proper scrolling shadows</a></li>
<li><a href="https://kizu.dev/fit-to-width-text/">Fit-to-width text</a></li>
<li><a href="https://kizu.dev/position-driven-styles/#value-distribution">Distributing values across a list of items</a></li>
<li><a href="https://kizu.dev/position-driven-styles/#staggered-animations">Staggered animations</a></li>
<li><a href="https://kizu.dev/position-driven-styles/#controlling-the-stacking">Reverse layer ordering</a></li>
<li><a href="https://kizu.dev/position-driven-styles/#edge-detection">Edge detection</a> for elements on the edges of their flex or grid containers.</li>
<li><a href="https://kizu.dev/position-driven-styles/#flex-wrap-detection">Flex-wrap detection</a>.</li>
<li>…and I have a number of experiments and techniques I have not yet published— stay tuned!</li>
</ul>
<p>How cool is it not only to get the new CSS spec’s implementation into a stable browser, but to already have a bunch of techniques to apply?</p>
<p>Of course, there is still a need to wait until other browsers pick up scroll-driven animations, but things seem to be positive: WebKit <a href="https://github.com/WebKit/standards-positions/issues/152">seems to be in support of it</a>, and it sounds like Mozilla has already <a href="https://github.com/mozilla/standards-positions/issues/347#issuecomment-1601630660">started working on the implementation</a>. That means that, unless done with extreme care, we shouldn’t use these techniques in production.</p>
<p>But there is one place where we could already start playing with the scroll-driven animations: CSS overrides for sites that you look at in Chrome. That sounds like a good place where the low browser support won’t matter much, so keep that in mind: we can now tweak styles with scroll-driven animations!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/110780251414043545">on Mastodon</a>!</p>Not an Ideal Starthttps://blog.kizu.dev/not-an-ideal-start/https://blog.kizu.dev/not-an-ideal-start/The first entry in my new blog: initial struggles and future plans.Sun, 09 Jul 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Shallows</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Hey hey! This is the first entry in my new blog.</p>
<p>I did write an <a href="https://kizu.dev/new-blog/">introduction to it on my site</a> — you can read it there for my reasoning about why I did create it and what would be different from the articles on <a href="https://kizu.dev">the main site</a>.</p>
<p>In short: to have a more personal place, where I could share random things, experiment with new tech, and separate all of this from my regular polished articles about CSS and Frontend.</p>
<p>Though, at least initially, this blog still would be rather technical, but we’ll see how things would progress!</p>
<h2 id="the-stack">The Stack</h2>
<ol>
<li><a href="https://www.netlify.com/">Netlify</a> — my main site is hosted there, the domain is registered with it, making it very easy to just continue using it. Almost no complains.</li>
<li><a href="https://astro.build/">Astro</a> — wanted to try for a while, and while it works, I’m not entirely sure I would stick with it. But at least for a while I’ll stick with it — would be unwise to dismiss it right away.</li>
<li><a href="https://www.typescriptlang.org/">TypeScript</a> — first time I’ll be using it outside of my work. I sincerely think that once you have it set up, it can help tremendously. I cannot imagine writing JS without relying on types — either with a proper setup or at least via a <code>@ts-check</code> in a <code>.js</code> file.</li>
<li><a href="https://mdxjs.com/">MDX</a> — in all my previous blog iterations, I always pushed markdown to the maximum, inventing new syntax for the things I wanted to have in it and so on — the ability to rely on components and remark plugins would make the things I want to do with content much more convenient.</li>
</ol>
<h3 id="everything-else-from-scratch">Everything Else — From Scratch</h3>
<p>I decided to opt out of any built-in CSS from the Astro starter and not take anything from my existing site’s CSS. Having a blank canvas would allow me to experiment with CSS in any way I want, and I have some ideas of what I want to do here.</p>
<p>So, for now, you might notice the absence of almost any styles — things will change a lot in the future!</p>
<h2 id="bumps-on-the-road">Bumps on the Road</h2>
<p>I was a bit naive, thinking that starting from scratch with a modern stack would go smoothly. It didn’t!</p>
<ol>
<li>Right away, I had a bunch of TS issues in VS Code, getting the “Cannot find module ‘astro:content’…” issue and others. Restarting the TS server did not help, and running <code>astro sync</code> did not help. Updating VS Code and restarting it a few times did help though. Things are overcomplicated in the modern front-end for sure.</li>
<li>When I was hooking up Netlify for my repo via <code>netlify-cli</code>, I had a few hiccups due to it using the same <code>3000</code> port for the thing it was doing as my Astro dev server that was running at the same time. Lesson learned: next time I’d like to set up a new Netlify site, I will stop the dev server right away.</li>
<li>The RSS experience in the Astro blog starter was not ideal:
<ul>
<li>While I did choose to use TS, it came with the <code>rss.xml.js</code> from the box, so I had to rename it to <code>rss.xml.ts</code> and adjust a few type-related things inside ( - The <code>BaseHead.astro</code> template did not come with a <code><link rel="alternate" type="application/rss+xml" … /></code>, so I had to add it manually.</li>
<li>Not a big deal, but the generated RSS was not using Atom and did not have a <code>language</code> field, so I had to use the <code>xmlns</code> and <code>customData</code> to provide these.</li>
</ul>
</li>
<li>I did not like how the content collections work in Astro: no good way to control the slug, provide default values for metadata based on the files, and some other issues. I think I would have to explore the <a href="https://docs.astro.build/en/reference/integrations-reference/">integration API</a> and remark <a href="https://github.com/unifiedjs/unified#plugin">plugins</a> as a way to augment it to do what I want from it, but so far the experience was subpar.</li>
</ol>
<p>But hey! Things work for now, and I will see how things would scale. Astro islands is also a thing that I really hope to delve into as a very convenient way to add dynamic content to my articles — and if that part would go smoothly, to see if I could somehow integrate it onto my main site.</p>
<hr>
<p>That’s it for now! There are a lot of things I already want to write here, but I’ll try not to throw everything into one post.</p>
<p>Until later!</p>
<hr>
<p>Oh, wait!</p>
<h2 id="css-snapshot">CSS Snapshot</h2>
<p>Just for fun — not sure how long I could keep it up — I’ll try writing about which changes and additions I’m adding to the blog alongside every article.</p>
<p>With this article, here is the complete CSS I have in this blog:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">html</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#79B8FF"> dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> box-sizing</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">border-box</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">42</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> min-height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.25</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D"> /* https://modernfontstacks.com/ */</span></span>
<span class="line"><span style="color:#79B8FF"> font-family</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> 'Iowan Old Style'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF"> 'Palatino Linotype'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF"> 'URW Palladio L'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> P052,</span></span>
<span class="line"><span style="color:#79B8FF"> serif</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">code</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> white-space</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pre-wrap</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> tab-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>And that’s it. For now.</p>
<p>Other than the basic styles making things slightly more readable, I’m adding one thing I wanted to try for a while — relying on the built-in system fonts instead of any custom ones. I did choose the “Old Style” stack from a very helpful <a href="https://modernfontstacks.com/">“Modern Font Stacks”</a> project by <a href="https://danklammer.com/">Dan Klammer</a> for now, but I’ll pay more attention to everything around typography at a later point.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/110686018570616601">on Mastodon</a>!</p>Astro MDX Componentshttps://blog.kizu.dev/astro-mdx-components/https://blog.kizu.dev/astro-mdx-components/Today’s post is sponsored by me not knowing what I’m doing. In other words: fiddling with how my blog is built. Given Astro is a relatively new framework, I struggled to find solutions to some probably simple things I wanted to do with it. In this post, I’ll document what I did find working for me, and maybe this could be of any assistance to others also struggling with Astro & its MDX integration.Tue, 14 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Sharon Murphy — Can’t Catch Polly</dd><dt>Current drink:</dt><dd>Cold Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Today’s post is sponsored by me not knowing what I’m doing. In other words: fiddling with how my blog is built.</p>
<p>As I mentioned in <a href="/not-an-ideal-start/">the first post here</a>, I’m using <a href="https://astro.build/">Astro framework</a> and <a href="https://mdxjs.com/">MDX</a> for building everything.</p>
<p>Given Astro is a relatively new framework, I struggled to find solutions to some probably simple things I wanted to do with it.</p>
<p>In this post, I’ll document what I did find working for me, and maybe this could be of any assistance to others also struggling with Astro & its MDX integration.</p>
<h2 id="providing-mdx-components-by-default">Providing MDX Components by Default</h2>
<p>The biggest reason I like MDX is because it allows a straightforward way of augmenting your markdown, as it is possible to provide your <a href="https://mdxjs.com/table-of-components/">custom components</a> for every HTML tag it will output.</p>
<p>The best part about MDX with Astro is that it builds everything statically by default, and if we provide any custom components to the underlying MDX, they’d be just rendered as plain HTML (unless we’d enable any <a href="https://docs.astro.build/en/concepts/islands/">dynamic islands</a>).</p>
<p>I want to do numerous things with these custom components, and, the important part: <strong>I want to always use them</strong>.</p>
<p>The default way of applying custom components to MDX is by first importing right into your <code>.mdx</code> file, and then <em>exporting</em> them back as a <code>components</code> object. This is described in the Astro docs: <a href="https://docs.astro.build/en/guides/markdown-content/#assigning-custom-components-to-html-elements">“Assigning Custom Components to HTML elements”</a>, and it provides this code snippet as an example:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="js"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Blockquote </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> '../components/Blockquote.astro'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> const</span><span style="color:#79B8FF"> components</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {blockquote: Blockquote}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">></span><span style="color:#E1E4E8"> This quote will be a custom Blockquote</span></span></code></pre>
<p>And that’s how I did do it, for every blog post… Not ideal. Is there a better way? When I was looking for it, most suggestions were to somehow pass components via remark plugins, but I’m not entirely sure if that would work with Astro. If it is up to me, I’d better not enter the plugins’ territory unless I really have to.</p>
<p>Finally, after a few attempts to find a solution, I found out that it <em>is</em> possible to provide custom components, but only if you’re using the <a href="https://docs.astro.build/en/guides/content-collections/">“Content Collections”</a> feature.</p>
<p>Basically, when we render a content collection, the final step to render the content to HTML is to do something like this (reduced snippet from the <a href="https://docs.astro.build/en/guides/content-collections/#rendering-content-to-html">“Rendering content to HTML”</a> section):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="jsx"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">---</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">Content</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">headings</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> entry.</span><span style="color:#B392F0">render</span><span style="color:#E1E4E8">();</span></span>
<span class="line"><span style="color:#F97583">---</span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#79B8FF">Content</span><span style="color:#E1E4E8"> /></span></span></code></pre>
<p>What I <em>did not find in the docs</em> is that that dynamic <code>Content</code> component <strong>accepts a <code>components</code></strong> prop!</p>
<p>That means that all I need to do to provide my default custom components is first</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="js"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Link </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> '@components/mdx/Link.astro'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> Paragraph </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> '@components/mdx/Paragraph.astro'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> ListItem </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> '@components/mdx/ListItem.astro'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> components</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> a: Link,</span></span>
<span class="line"><span style="color:#E1E4E8"> p: Paragraph,</span></span>
<span class="line"><span style="color:#E1E4E8"> li: ListItem,</span></span>
<span class="line"><span style="color:#E1E4E8">};</span></span></code></pre>
<p>And then pass this object to <code>Content</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="jsx"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#79B8FF">Content</span><span style="color:#B392F0"> components</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{components} /></span></span></code></pre>
<p>And that’s it — now every page rendered this way would automatically apply these components.</p>
<h2 id="accessing-the-slots-content">Accessing the Slots Content</h2>
<p>Now that I have an ability to override the components, one thing that I want to do inside of them — access the content that is passed to them. Then, either do things based on what is inside, or maybe even modify the content. Why did I want this? Perhaps I’ll write about this one day!</p>
<p>In more traditional frameworks like React or Preact, we’d have the <code>children</code> in the props, which we could analyze or modify in some way.</p>
<p>But can we do something similar with <code>.astro</code> components? I did not find this ability initially, so used a bit hacky Preact solution for a while, but I was not happy with the solution I had.</p>
<p>After another attempt to go through the docs, I, finally, got to the solution: <a href="https://docs.astro.build/en/reference/api-reference/#astroslotsrender"><code>Astro.slots.render()</code></a>. Here is the code example from this doc:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="jsx"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">---</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> html</span><span style="color:#F97583"> =</span><span style="color:#F97583"> await</span><span style="color:#E1E4E8"> Astro.slots.</span><span style="color:#B392F0">render</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'default'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583">---</span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#79B8FF">Fragment</span><span style="color:#B392F0"> set</span><span style="color:#E1E4E8">:</span><span style="color:#B392F0">html</span><span style="color:#F97583">=</span><span style="color:#E1E4E8">{html} /></span></span></code></pre>
<p>The “default” slot is what would be in every MDX component, so now we can do anything with this <code>html</code>: it is just a rendered string with HTML inside. We could look inside of it, modify, and then pass further into any element via <a href="https://docs.astro.build/en/reference/directives-reference/#sethtml"><code>set: html</code></a> Astro prop.</p>
<h2 id="thats-it">That’s It</h2>
<p>Now I have an ability to do almost anything with the MDX components, without the need to include them <em>every time</em> I write a blog post. And also an ability to just use Astro components without any additional frameworks when all I want is to modify the final generated HTML.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111409862180231008">on Mastodon</a>!</p>Weekly Bookmarks 2https://blog.kizu.dev/weekly-bookmarks-002/https://blog.kizu.dev/weekly-bookmarks-002/The second installment of the things I deemed useful to bookmark in my blog.Sun, 22 Oct 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — Dynamics of subway</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>Hey hey! Oh wow, I did not forget to publish this weekly post. Though, I wish I had prepared some of the links in advance as a way to speed up the process.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="css-techniques-and-news">CSS Techniques and News</h2>
<ul>
<li>
<p><a href="https://blog.stephaniestimac.com/posts/2023/10/css-text-wrap/">“When to use CSS <code>text-wrap: balance;</code> vs <code>text-wrap: pretty;</code>”</a> by <a href="https://stephaniestimac.com/">Stephanie Stimac</a> — a comparison of two different values of <code>text-wrap</code> currently available in Chrome, alongside their use cases.</p>
</li>
<li>
<p><a href="https://www.w3.org/blog/CSS/2023/10/20/css-text-level-4-draft-updated/">“CSS Text Level 4 Draft Updated”</a> by <a href="https://florian.rivoal.net/">Florian Rivoal</a> — an important thing to mention in addition to the previous article, as the <code>text-wrap</code> naming would change to <code>text-wrap-style</code> eventually. Unfortunate that it did ship with the current name, with people already adopting it, but the new naming is a bit more clear.</p>
</li>
<li>
<p>Gecko’s <a href="https://groups.google.com/a/mozilla.org/g/dev-platform/c/uAscf5sfEdc/m/0EQcFYqxAAAJ">“Intent to ship: CSS <code>text-wrap: balance</code>”</a> — related to the previous two articles: it seems that Firefox wants to ship the <code>text-wrap: balance</code> anyway, and then later adjust to the new naming, making the situation slightly more weird, but also more interop?</p>
</li>
<li>
<p><a href="https://chriscoyier.net/2023/10/17/a-couple-of-new-css-functions-id-never-heard-of/">“A Couple of New CSS Functions I’d Never Heard Of”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a nice little <em>round</em>-up of new CSS functions. I actually never heard about <code>xywh()</code>, and I already like how its name describes its API. Maybe we could rename <code>border-image</code> property accordingly, eh?</p>
</li>
<li>
<p><a href="https://codepen.io/propjockey/pen/OJdJmya?editors=1100">“@supports @property”</a> by <a href="http://propjockey.io/">Jane Ori</a> — a CodePen showing how we can detect the support of <code>@property</code>. A bit hacky, as we don’t actually have a native way to detect this, it relies on detecting unrelated features that shipped in the exact same browser versions that <code>@property</code> did.</p>
<p>The ability to test for this natively was resolved by CSSWG in the <a href="https://github.com/w3c/csswg-drafts/issues/2463#issuecomment-1016720310">“Feature detection for descriptors” issue</a>, though there are still unresolved issues like <a href="https://github.com/w3c/csswg-drafts/issues/6966">testing for preludes</a>. Browsers are yet to implement this, though, and hopefully when they do, we will be able to test for things like <code>@property</code> natively.</p>
</li>
<li>
<p>Chromiums’s <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/PkEsMirl2zE/m/ArphSa39AAAJ">“Intent to Ship: CSS Scrollbars: <code>scrollbar-color</code>, <code>scrollbar-width</code>”</a> — I’m not sure yet what I think about these — I understand that it is unlikely we’d get the much more powerful WebKit’s pseudo-elements, so having at least <em>some</em> standard way to control the scrollbars would be nice, <em>but</em> I’d really want to see the <code>scrollbar-width</code> accepting <code><length></code> instead of its current <code>auto | thin | none</code>.</p>
<p>I think one of the reasons not to have it was to prevent the scrollbars being too thin… But what if we’d just say “Treat any length value as something like <code>max(thin, my-value)</code>”? Basically, have the value that the scrollbar can get via <code>thin</code> be the lower bound, so we could still control the scrollbar width in a way that it would be consistent with other design elements.</p>
</li>
<li>
<p>Gecko’s <a href="https://groups.google.com/a/mozilla.org/g/dev-platform/c/z6PaiICBCRg/m/w171E3_DAAAJ">“Intent to prototype & ship: CSS text-indent keywords <code>hanging</code> & <code>each-line</code>”</a> — can be very useful for wrapping <code><code></code> elements (not to be confused with <a href="https://drafts.csswg.org/css-text/#hanging-punctuation-property">hanging punctuation</a>).</p>
</li>
<li>
<p>Chromiums’s <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/oAu01pBscs8/m/JUaPY3KwAQAJ">“Intent to Ship: CSS Exponential Functions”</a> — I always welcome more maths into CSS, even though I don’t use it very often. But I know a lot of others do, and sometimes maths can unlock some interesting effects!</p>
</li>
<li>
<p><a href="https://kizu.dev/scroll-driven-state-transfer/">“Scroll-Driven State Transfer”</a> — My fourth article about scroll-driven animations, where I explore how we can transfer the state of one element to a completely different place on a page by connecting them with a unique identifier in CSS via a timeline-scope.</p>
</li>
</ul>
<h2 id="non-css-web-platform-stuff">Non-CSS Web Platform Stuff</h2>
<ul>
<li><a href="https://techno-barje.fr/post/2023/10/20/history-of-edition-and-publishing-in-web-browsers/">“The History of editing and publishing in web browsers”</a> by <a href="https://techno-barje.fr/">Alexandre Poirot</a> — a bit of web browser history that I did not really know of or remembered.</li>
</ul>
<h2 id="not-exactly-new-but-noteworthy">Not Exactly New, but Noteworthy</h2>
<ul>
<li>
<p>Some links from <a href="https://front-end.social/@kizu/111258253160862526">a short Mastodon Thread about multicol</a> by me:</p>
<ul>
<li><a href="https://github.com/web-platform-tests/interop/issues/520">“CSS Multi-Column Layout block element breaking”</a> by <a href="https://scottkellum.com/">Scott Kellum</a> — a “focus area proposal” for Interop 2024. I recommend voting for this issue — any improvements to multicol would be really awesome, it is a highly overlooked area in CSS.</li>
<li><a href="https://www.smashingmagazine.com/2019/11/css-things-cant-yet-do/">“Things We Can’t (Yet) Do In CSS”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> — a 5 years old, but still actual article about various missing CSS multicol features. Curiously, some of them might be possible with the help of some of the newer CSS specs, though in a rather hacky way. I might write about this relatively soon.</li>
<li><a href="https://github.com/w3c/csswg-drafts/issues/2923">“Overflow in the block direction for continuous media”</a> also by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> — a CSSWG issue about one of these issues which is almost impossible to do without a native support for it. From what I can remember, there are a lot of issues with fragmentation in CSS, and I think there was some work going on to improve it in general? Hopefully, one day, this would be sorted.</li>
</ul>
</li>
<li>
<p><a href="https://drafts.csswg.org/css2/">“CSS 2”</a> — if you can’t find something obvious in the specs, try looking in CSS2.</p>
<p>A lot of things did not move to the new levels of specs, so a lot of basics and their nuances are still only there in CSS2.</p>
</li>
<li>
<p><a href="https://drafts.csswg.org/indexes/">“CSS Indexes”</a> shared by <a href="https://github.com/AmeliaBR/">Amelia Bellamy-Royds</a> as <a href="https://front-end.social/@AmeliaBR/111251112262899307">a response</a> to me sharing the previous tip on mastodon — a listing of every term defined by CSS specs.</p>
</li>
</ul>
<h2 id="my-bug-reports">My Bug Reports</h2>
<ul>
<li>
<p><a href="https://github.com/web-platform-tests/wpt/pull/42676">“Tests for <code>round()</code>, <code>mod()</code>, and <code>rem()</code> that has a percentage only for one value”</a> — my first PR to <a href="https://web-platform-tests.org/">Web-Platform Tests</a>. I wanted to try doing this for a while — write WPT tests as an alternative to just filling up the bugs in the browser bug trackers. I was told these, when merged, could automatically create these bug reports for the browsers that fail them? I’m very curious to see how the workflow would be with them.</p>
</li>
<li>
<p><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1493339">“Regression: size value for box-shadows did stop working”</a> — a rather weird issue in Chrome Canary which I can see on my work MacBook (and at least one of my colleague can as well), but I cannot reproduce it on my home MacBook. Maybe some weird environment issue? Hmm.</p>
</li>
</ul>
<h2 id="upcoming-events">Upcoming Events</h2>
<p>Usually, I’m staying at home, slowly working on my CSS articles and experiments, but this time I’ve decided to travel a bit. I did plan to attend <a href="https://fronteersconf.org/">Fronteers Conference</a> this year, but it was cancelled — so I decided to visit the <code>border: none</code> instead.</p>
<ul>
<li>
<p>October 26–27, 2023, <a href="https://border-none.net/2023/">“<code>border: none</code> 2023”</a> — a non-profit conference in Nuremberg, Germany. I’m planning to attend it in-person, so if you’d be there — say hi! Otherwise, they’re planning to stream the talks, with the ticket starting from €30.</p>
</li>
<li>
<p>October 28–29, 2023 <a href="https://indieweb.org/2023/Nuremberg">“IndieWebCamp Nuremberg 2023”</a> — will be my first IndieWebCamp. Right after the <code>border: none</code>, hopefully I won’t be too exhausted after the conference itself.</p>
</li>
<li>
<p>October 30, 2023, <a href="https://www.meetup.com/css-cafe/events/296354512/">“Weird Things You Missed About CSS”</a> by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — a free online CSS Café event. I’ll be in a train back from <code>border: none</code> during it, but would try to attend if the Wi-Fi in the train will allow me!</p>
</li>
</ul>
<hr>
<p>And that’s it! I’ll be rather busy in the second half of the next week, so I hope I won’t miss posting the third post with the bookmarks. We’ll see, I guess!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111280257109407352">on Mastodon</a>!</p>IndieWebCamp Updateshttps://blog.kizu.dev/indie-web-camp-updates/https://blog.kizu.dev/indie-web-camp-updates/I did participate in the IndieWebCamp Nuremberg 2023 and made a few updates to my main site and my less polished blog.Mon, 30 Oct 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Cappuccino</dd><dt>Current location:</dt><dd>Espressolab, Theresienstraße 14, 90403 Nürnberg, Germany</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>If you were waiting for my weekly list of links, I would publish it a bit later! As I did mention in the <a href="/weekly-bookmarks-002/">previous weekly</a>, I did attend the <a href="https://border-none.net/2023/">“border: none”</a> conference, and right after it, I did participate in the <a href="https://indieweb.org/2023/Nuremberg">“IndieWebCamp Nuremberg 2023”</a>. So, I did not have too much time to work on the weekly post — but I did gather some links and would try to compile them eventually.</p>
<p>I’ll omit most of what I learned during IWC’s first day; I think most of it would go into the weekly links post, and in this post I would just list things that I did add to my websites.</p>
<h2 id="microformats">Microformats</h2>
<p>I did add <a href="https://microformats.org/wiki/h-card"><code>h-card</code></a> and <a href="https://microformats.org/wiki/h-entry"><code>h-entry</code></a> microformats to both <a href="https://kizu.dev">kizu.dev</a> and <a href="https://blog.kizu.dev">blog.kizu.dev</a>.</p>
<p>I remember having an older version of microformats years and years ago over at my core site, but I did lose them with one of the redesigns.</p>
<p>Now was a good opportunity to add them back again.</p>
<p>Here are both of my PRs that did add them to my sites:</p>
<ul>
<li><a href="https://github.com/kizu/kizu.ru/pull/239">https://github.com/kizu/kizu.ru/pull/239</a></li>
<li><a href="https://github.com/kizu/kizu-blog/pull/5">https://github.com/kizu/kizu-blog/pull/5</a></li>
</ul>
<p>They contain a bit more stuff than just microformats, and the code inside is not that interesting, but you’re free to peek into them.</p>
<p>You can also look at the microformats validator results:</p>
<ul>
<li><a href="https://indiewebify.me/validate-h-card/?url=https%3A%2F%2Fkizu.dev%2F">h-card at kizu.dev</a></li>
<li><a href="https://indiewebify.me/validate-h-entry/?url=https%3A%2F%2Fkizu.dev%2Fscroll-driven-state-transfer%2F">h-entry for a kizu.dev article</a></li>
<li><a href="https://indiewebify.me/validate-h-card/?url=https%3A%2F%2Fblog.kizu.dev%2F">h-card at blog.kizu.dev</a></li>
<li><a href="https://indiewebify.me/validate-h-entry/?url=https%3A%2F%2Fblog.kizu.dev%2Fweekly-bookmarks-001%2F">h-entry for a blog.kizu.dev article</a></li>
</ul>
<p>There were a few notes I took while doing this:</p>
<ul>
<li>When validating things via the validator on <a href="https://indiewebify.me">indiewebify.me</a>, I noticed a potential XSS issue and <a href="https://github.com/indieweb/indiewebify-me/issues/115">reported it on their GitHub</a>.</li>
<li>I decided against using the outdated formats like <a href="https://microformats.org/wiki/hcard">hCard 1.0</a> (<code>vcard</code>, <code>fn</code>, etc), at least for now.</li>
<li>It is not always easy to add microformats <em>after the fact</em>:
<ul>
<li>On my main site, I’m using a CSS grid for the article’s layout, and when I was implementing it, there were no subgrids (and even no good <code>display: contents</code> support), so everything inside my article is a flat list of elements. A bunch of microformats require wrappers, like the <code>e-content</code> for the <code>h-entry</code>. Maybe when I redesign or rewrite the site once again, I’ll take this into consideration.</li>
<li>There seems to be no good way to provide data in microformats without actual elements in HTML. For example, I’ll be ok with providing my photo as a part of the consumed microformats but not as something visible on the site. Adding actual elements and <em>hiding</em> them did not sound good. I wonder if there might be better solutions, like involving <code><template></code> tag or something similar. Or maybe there is one, but I don’t know about it.</li>
<li>I think it could be nice to have some ways to “connect” elements via some id references, like I’d want to have my <code>h-card</code> outside an <code>h-entry</code>, but mention it for the author field. The pattern I have noticed (and ended up using) is that very often the whole page becomes a <code>h-card</code> or <code>h-entry</code>, allowing nesting everything inside them and creating a semantic connection. However, I think there are enough cases to be able to connect entities that are located in different parts of a page.</li>
</ul>
</li>
</ul>
<h2 id="syndicating-myblog-tomysite">Syndicating My Blog to My site</h2>
<p>One of the ideas of the Indie Web is to own all your content and display it on your site in some form. I already publish my articles and my less polished posts on my own sites, but until now I did not have any connection between them.</p>
<p>In the time I had to work on it, I did manage to implement fetching my blog posts into my main site and display the most recent five posts as a simple list. I did not spend too much time on this list’s design; I just wanted the content to be there. After all, I’ll be redesigning my home page eventually and will try to incorporate these links in a better way.</p>
<p>How I ended up implementing this:</p>
<ul>
<li>I output the metadata of the five latest articles on my blog in a <code>JSON</code>, creating it automatically when building the site.
<ul>
<li>As I’m using <a href="https://astro.build/">Astro</a>, I did add a <code>src/pages/latest.json.ts</code> file.</li>
<li>I struggled a bit looking at what this file should return for Astro to properly output the JSON. Basically, [it needs to - Then, on my main site, I’m using the Hugo’s <a href="https://gohugo.io/functions/data/getjson/">getJSON</a> to retrieve this data and use it for creating this list.</li>
</ul>
</li>
</ul>
<p>That’s it!</p>
<h2 id="planned-for-the-future">Planned for the future</h2>
<p>I think there are still a lot of ways microformats could be added and improved, but until I stumble across a need for something to <em>consume</em> them, I’ll leave them mostly be. Though, I think it could be a good idea to add some kind of test to my build pipeline that would parse the built pages and make sure microformats are present and result in the data I would expect. This way, any site refactoring won’t result in it breaking.</p>
<p>For the “self-syndicating” articles, I’ll need to implement the reverse: show the latest articles from my core site over at my blog. A few things to note:</p>
<ul>
<li>I think I don’t want to get every article, maybe only “featured”? Though maybe, with me now having this additional blog, there is no need to make anything featured.</li>
<li>I want to make the websites rebuild automatically when one of them changes. I did look into how I could set this up — the build hooks in Netlify where I’m hosting both sites seem like they could do the job, but I’m a bit afraid to set them up in a loop: I’ll need to somehow make it, so only a <em>commit</em> would result in a rebuild, but not just any rebuild triggering an outside hook.</li>
</ul>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>I always love working on my websites, and I always wish I had more time to do so. Having this dedicated time at IndieWebCamp to do just that was very nice!</p>
<p>I also met a bunch of new people and learned about a bunch of interesting things. I’ll try to compile them into the next weekly post, so stay tuned!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111323635099097300">on Mastodon</a>!</p>Calculated Fractions (Report the Bugs!)https://blog.kizu.dev/calc-fr-unit/https://blog.kizu.dev/calc-fr-unit/If you see something that you think should work in every browser, but it does not work in every browser, what would you do? When I did encounter this issue a few months ago for the first time, I thought that maybe this was some obscure CSS specs limitation that did apply to my case. I was wrong. Today I investigated this further, and in this post would tell you what I found.Thu, 23 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Peppermint tea</dd></dl><hr /><p>If you see something that you think should work in every browser, but it does not work in every browser, what would you do?</p>
<p>When I did encounter this issue a few months ago for the first time, I thought that maybe this was some obscure CSS specs limitation that did apply to my case.</p>
<p>What was that case? Using a <code>fr</code> unit inside <code>calc()</code> for CSS grids.</p>
<p>It does not work. You can check for yourself in <a href="https://codepen.io/kizu/pen/RwvyyOg">this CodePen</a> (unless you’re from the future, where this is fixed).</p>
<p>It does not work in Firefox, it does not work in Safari, it does not work in Chrome.</p>
<p>The first time I encountered this, I moved on. This, as a feature, would’ve been nice to have, but not crucial, and only as a part of an unrelated experiment. Moving on was a wrong choice!</p>
<p>Today, glancing over the <a href="https://www.joshwcomeau.com/css/interactive-guide-to-grid/">“An Interactive Guide to CSS Grid”</a> by <a href="https://www.joshwcomeau.com/">Josh W. Comeau</a>, I randomly remembered that I couldn’t use the fractions inside a calculation. Why was that again? Should I write an observation about this absence of a feature? I investigated.</p>
<p>Things I found:</p>
<ol>
<li>
<p>There was already <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=993136">a bug filled in Chromium</a> from August 2019 by <a href="https://github.com/xiaochengh">Xiaocheng Hu</a>.</p>
</li>
<li>
<p>At the beginning of 2022, <a href="https://lea.verou.me/">Lea Verou</a> did already bring this up to CSSWG in a <a href="https://github.com/w3c/csswg-drafts/issues/6989">“Should <code>calc(1fr)</code> be invalid?” issue</a> asking if that is per spec, or a misunderstanding of <a href="https://drafts.csswg.org/css-grid/#ref-for-typedef-flex%E2%91%A8">a particular note in the spec</a>.</p>
<p><a href="https://xanthir.com/">Tab Atkins-Bittner</a> replied. Here is what they said:</p>
<blockquote>
<p>Definitely a bug; <code>fr</code> units should be math’able just fine. That note is, indeed, just observing that <code>fr</code> is not a <code><length></code> so <code>calc(1px + 1fr)</code> is invalid, but <code>calc(1fr / 3)</code> should be just fine.</p>
</blockquote>
</li>
<li>
<p>While there were tests covering some <code>fr</code> cases, like properly disallowing it when used with the <code><length></code> units (like <code>calc(1fr + 100px)</code>), there were no tests assuring that just the <code>calc(1fr)</code> and similar would work.</p>
</li>
</ol>
<p>So, per spec, this should work. It was even clarified by one of the spec editors! What does this mean?</p>
<p>That means that this is a good case, where filling up the bugs in other browsers, and writing WPT tests should be trivial and, hopefully, won’t be challenged.</p>
<p>That’s what I did!</p>
<ul>
<li>I opened <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1866236">a Firefox bug</a>.</li>
<li>I opened <a href="https://bugs.webkit.org/show_bug.cgi?id=265276">a WebKit bug</a>.</li>
<li>I opened <a href="https://github.com/web-platform-tests/wpt/pull/43322">my third Web Platform Tests PR</a> (open at the moment of writing this).</li>
<li>I cross-linked everything together, just in case (I like backlinks, and I think there should be more two-way connected pages on the web).</li>
</ul>
<p>Writing this post probably took longer than doing the above (excluding the research time).</p>
<p>Now, one day, hopefully, we could use flexible lengths inside CSS calculations, and maybe what I did today did bring this closer to reality, even if a tiny bit.</p>
<h2 id="open-the-bugs">Open the Bugs!</h2>
<p><a href="https://front-end.social/@kizu/111460085317096031">I did ask today in Mastodon</a> what people do when they encounter a bug in CSS, in a form of a poll. So far, 61% (out of 164 persons) did choose the “ignore or work around it; continue with your day”.</p>
<p>That was what I did initially when I encountered this issue. It is easy to assume that something that does not work anywhere is “working as intended”. Every so often, it is not. Believe in your feelings! Try to question yourself less. Yes, you might be confused about something, and the issue is on your side.</p>
<p>However! My experience tells me that any confusion can be a very helpful flag for the spec writers and implementers that something could be improved, either in the specs, or in the implementation.</p>
<p>Whenever you encounter something weird, try asking about it. The <code>#CSS</code> hashtag works really well on Mastodon, for example: there are plenty of people who’re ready to help.</p>
<p>And, if you have time — I highly recommend reading the specs, looking if there are bugs filled, CSSWG issues, and WPT tests about what you’ve stumbled upon. Looking deeper into the problems is an excellent way to learn.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111461349427812542">on Mastodon</a>!</p>Weekly Bookmarks 1https://blog.kizu.dev/weekly-bookmarks-001/https://blog.kizu.dev/weekly-bookmarks-001/In an attempt to start writing more in my blog, I am gathering some of the bookmarks I found important in this weekly post.Sun, 15 Oct 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Surrealist — Lux</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>How funny — in July I did start my blog but have not posted since then. Isn’t that the fate of most blogs?</p>
<p>As an attempt to have <em>something</em> to write about at least on a weekly basis, here is what I think I’ll do: gather some of the interesting stuff I noticed during the week and just post these with minimal comments. Some of it I shared in <a href="https://front-end.social/@kizu">my Mastodon</a> already, but I think it could be useful, even if for myself, to have a compilation here as well.</p>
<p>Let’s go!</p>
<h2 id="css-techniques-and-news">CSS Techniques and News</h2>
<ul>
<li>
<p><a href="https://codepen.io/leaverou/pen/gOZZQZb?editors=1100">“Emulate basic relative color syntax with <code>color-mix()</code> + the <code>none</code> keyword”</a> by <a href="https://lea.verou.me/">Lea Verou</a>. Given <code>color-mix()</code> is already supported in all major browsers, this is a really important find: it brings some of the relative color syntax abilities closer to us — if you can use this with proper fallbacks in a progressive enhancement manner, you can already do it!</p>
</li>
<li>
<p><a href="https://dev.to/janeori/css-type-casting-to-numeric-tanatan2-scalars-582j">“CSS Type Casting to Numeric: <code>tan(atan2())</code> Scalars”</a> by <a href="http://propjockey.io/">Jane Ori</a>. A very cool workaround for the absence of an ability to remove units from the lengths in CSS calculations. Works (with some hacks) in Chrome and Safari, not yet in Firefox (as it requires <code>@property</code>). Given the trick is very simple, I might try it in some of my experiments. If you want this natively — vote for <a href="https://github.com/web-platform-tests/interop/issues/513">this interop 2024 focus area proposal</a> by <a href="https://scottkellum.com/">Scott Kellum</a>.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/9456">“[css-backgrounds] background-clip: border-area”</a> — a proposal in CSSWG issues by <a href="https://lea.verou.me/">Lea Verou</a>. I think it makes a lot of sense, though it might be a bit tricky to use correctly due to the necessity to make sure the fallbacks would work and would not result in unreadable text.</p>
</li>
<li>
<p><a href="https://robinrendle.com/the-cascade/">“The Cascade is a newsletter about the past, present, and future of CSS”</a> by <a href="https://robinrendle.com/">Robin Rendle</a>. Two issues are already there and are also available on Robin’s website in a non-newsletter format if you prefer it this way.</p>
</li>
</ul>
<h2 id="not-exactly-new-but-noteworthy">Not Exactly New, but Noteworthy</h2>
<ul>
<li>
<p><a href="https://www.igalia.com/24-7/chats">“Igalia Chats”</a> — a podcast by <a href="https://bkardell.com/">Brian Kardell</a> and <a href="https://meyerweb.com/">Eric Meyer</a> about the web, its history, browsers and standards. I just finished listening to all the currently available recordings, and I wish there were more in-depth discussions about the web of this kind.</p>
</li>
<li>
<p><a href="https://imageoptim.com/changelog.html#v1.9.1">“ImageOptim 1.9.1”</a> by <a href="https://kornel.ski/">Kornel Lesiński</a> — a very useful macOS app for image optimization, now native for Apple Silicon.</p>
</li>
<li>
<p><a href="https://browser.kagi.com/">“Orion Browser”</a> and <a href="https://sigmaos.com/">“SigmaOS”</a> — interestingly, there are now new browsers that are based on WebKit, which is refreshing compared to most of them being based on Chromium recently. Similarly, the <a href="https://duckduckgo.com/duckduckgo-help-pages/get-duckduckgo/get-duckduckgo-browser-on-mac/">“DuckDuckGo”</a> browser, which exists on different systems, just uses the built-in engine, so on macOS it also uses WebKit.</p>
</li>
<li>
<p><a href="https://github.com/preactjs/preact-custom-element">“<code>preact-custom-element</code>”</a> — a Preact helper that allows it to be used with web components. I tried it for a tiny thing I’m working on, and it works okay. There are a bunch of bugs here and there, but otherwise I’m pretty happy with how web components, <a href="https://preactjs.com/">Preact</a> and <a href="https://github.com/developit/htm">HTM</a> can work together. No transpiler needed, small footprint.</p>
</li>
</ul>
<h2 id="my-bug-reports">My Bug Reports</h2>
<ul>
<li>
<p><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1492209">“Scroll-margin does not work for an element with a parent that has a non-visible overflow”</a> — a bug I reported in Chromium. There are actually so many more issues with <code>scroll-margin</code> and overflow… I’ll need to find time to extensively research it, as I think there is a very big gray area in both specs and implementations.</p>
</li>
<li>
<p><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1858786">“No transitions of inherited properties when the change is triggered by animations”</a> — another bug I reported this week, this time for Firefox. Also, it is slightly in a gray area, where specs are not 100% clear about how it should behave, but the way Chrome and Safari handle it are much more useful for developers. This might be required for a lot of techniques based on scroll-driven animations to work in the future, but it could still be useful even without them.</p>
</li>
</ul>
<hr>
<p>That’s it! I’m doing this today, so maybe there are not as many links as I could’ve gathered if I would note them as the week goes… We’ll see if the next post in the series will have as many or more — maybe not, given how this time there were two very nice CSS techniques shared by Jane and Lea, and this does not always happen, haha.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111239897330575957">on Mastodon</a>!</p>Calculation Indentationhttps://blog.kizu.dev/calc-indent/https://blog.kizu.dev/calc-indent/For some time, I struggled with some of the more complicated calculations in CSS. Not with their contents, but with how I would like to see them formatted.Sat, 11 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>For some time, I struggled with some of the more complicated calculations in CSS. Not with their contents, but with how I would like to see them formatted.</p>
<p>Let’s say we have some CSS like this (taken from the styles of this blog):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --content-padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">+</span><span style="color:#79B8FF"> clamp</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">100</span><span style="color:#F97583">vw</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-WIDTH</span><span style="color:#E1E4E8">), </span><span style="color:#79B8FF">2</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">, </span><span style="color:#85E89D">ol</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">2</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--content-padding</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>It is not the most complex CSS, but it is already difficult to read and maintain.</p>
<h2 id="how-prettier-handles-it">How Prettier Handles It</h2>
<p>Let’s imagine we’d use <a href="https://prettier.io/">Prettier</a> for this. As I’m going to display it here in my blog, by default it has around 54 symbols available with the <code>tab-size: 2</code>. Putting these settings in Prettier gives us this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --content-padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">+</span></span>
<span class="line"><span style="color:#79B8FF"> clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> 100</span><span style="color:#F97583">vw</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-WIDTH</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583">rem</span></span>
<span class="line"><span style="color:#E1E4E8"> )</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#85E89D">ol</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">-</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--content-padding</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Well, I guess, better, but I don’t really like Prettier’s way of bumping the indentation when wrapping a line of calculations.</p>
<p>And I never liked how Prettier formatted many other things in CSS, so I would probably never want to use it for my styles.</p>
<h2 id="how-iended-upwriting-it">How I Ended Up Writing It</h2>
<p>And here is what, after many thoughts, I ended up doing:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --content-padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#79B8FF"> clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> 100</span><span style="color:#F97583">vw</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-WIDTH</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583">rem</span></span>
<span class="line"><span style="color:#E1E4E8"> )</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">, </span><span style="color:#85E89D">ol</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--MIN-CONTENT-PADDING</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> -</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--content-padding</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>A few things to note there.</p>
<ul>
<li>Main feature I really liked doing: placing the <code>+</code> or <code>-</code> on separate lines. It is now much easier to spot different arguments of the calculations, and to spot what exactly is happening inside.</li>
<li>I think I prefer to keep the multiplication/division on the same line. Maybe even one day we would get <a href="https://github.com/w3c/csswg-drafts/issues/7379">the syntax sugar of using custom properties as custom units</a>? Then it would be even more simple.</li>
<li>Yes, the code grows vertically, but I’m perfectly fine with that if that means things are easier to read. And, for more complicated calculations, that could give even better results.</li>
</ul>
<h2 id="another-example">Another Example</h2>
<p>Here is another (again, rather simple) example, this time from my <a href="https://kizu.dev/anchor-positioning-experiments/#using-the-connections">“Using the Connections”</a> experiment of my <a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a> article.</p>
<p>How I did write it in the article:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.tree-item-label::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">) + </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.tree-item-label::after</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>How Prettier formats it:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.tree-item-label::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">) + </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.tree-item-label::after</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Verbose, but does not really help.</p>
<p>How I would now prefer to write it:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.tree-item-label::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> +</span></span>
<span class="line"><span style="color:#79B8FF"> 0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.tree-item-label::after</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> anchor(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--to</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> -</span></span>
<span class="line"><span style="color:#79B8FF"> 0.5</span><span style="color:#E1E4E8"> * </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--lh</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now it is much easier to spot the main difference of the <code>+</code> vs the <code>-</code>, as well as distinguish between the calculation arguments.</p>
<h2 id="its-all-subjective">It’s All Subjective</h2>
<p>That’s just the way I, at the present day, decided to write my CSS. Maybe it won’t fit you! Perhaps I would change it later! Or there would be things I reconsider and add to this method! We will see.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111392529101753808">on Mastodon</a>!</p>Observation: Clamp to Infinityhttps://blog.kizu.dev/clamp-to-infinity/https://blog.kizu.dev/clamp-to-infinity/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?Mon, 13 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="min-and-max">Min and Max</h2>
<p>A confession: I constantly get confused by <a href="https://drafts.csswg.org/css-values/#comp-func"><code>min()</code> and <code>max()</code> comparison functions</a> — 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 <code>min()</code> for the “upper” bound, and <code>max()</code> for the “lower”.</p>
<p>Overall, it frequently takes me a few moments to parse any code that contains these mins and maxes.</p>
<p>That’s why I really like the <a href="https://drafts.csswg.org/css-values/#funcdef-clamp"><code>clamp()</code> function</a> for defining the bounds — I find it much easier to understand and parse in my head.</p>
<h2 id="a-problem-with-clamp-in-css">A Problem with <code>clamp()</code> in CSS</h2>
<p>After another time of me using <code>min()</code> (or was it <code>max()</code>?), I wondered: could I just always use <code>clamp()</code>, even if I need to have only the lower or the upper bound?</p>
<p>The function itself does not provide a simple way to omit one of the bounds — all the arguments are required, and there is no <code>none</code> value that could be used instead of a value.</p>
<h3 id="update-from-2024-02-19">Update from 2024-02-19</h3>
<ul>
<li>On December 15, 2023, <a href="https://lea.verou.me/">Lea Verou</a> <a href="https://github.com/w3c/csswg-drafts/issues/9713">proposed</a> a <code>none</code> keyword that could be used to achieve the same result that I’m referring to in this article.</li>
<li>On February 14, 2024, CSSWG <a href="https://github.com/w3c/csswg-drafts/issues/9713#issuecomment-1944449961">resolved</a> to add it to the specs!</li>
</ul>
<h3 id="looking-for-a-solution">Looking for a Solution</h3>
<p>The first thought is to use a massive value, like <code>99999px</code> 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.</p>
<p>My second thought was: hey, didn’t we get the <a href="https://drafts.csswg.org/css-values/#valdef-calc-infinity"><code>infinity</code></a> in CSS recently?</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> style="</span></span>
<span class="line"><span style="color:#E1E4E8"> border: solid clamp(-infinity, 1em, infinity);</span></span>
<span class="line"><span style="color:#E1E4E8">"</span><span style="color:#F97583">></span><span style="color:#E1E4E8">test</</span><span style="color:#85E89D">div</span><span style="color:#F97583">></span></span></code></pre>
<p>Ah, but it does not work:</p>
<figure>
<div style="
border: solid clamp(-infinity, 1em, infinity);
">test</div>
<figcaption>
A live example that shows just an unstyled word “test”.
</figcaption>
</figure>
<p>Of course, because <code>infinity</code> is a <code><number></code>, and <code>clamp()</code> requires all arguments to be of the same type.</p>
<p>My third thought was to divide by zero. A perfectly normal thought for me!</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> style="</span></span>
<span class="line"><span style="color:#E1E4E8"> border: solid clamp(-1px/0, 1em, 1px/0);</span></span>
<span class="line"><span style="color:#E1E4E8">"</span><span style="color:#F97583">></span><span style="color:#E1E4E8">test</</span><span style="color:#85E89D">div</span><span style="color:#F97583">></span></span></code></pre>
<p>This works:</p>
<figure>
<div style="
border: solid clamp(-1px/0, 1em, 1px/0);
">test</div>
<figcaption>
A live example that shows a thick border around the word “test”.
</figcaption>
</figure>
<p>Then I started to write this post and gather the links to specs, as I often do. And guess what, there is <a href="https://drafts.csswg.org/css-values/#ref-for-number-value%E2%91%A2%E2%91%A3">a note in the specs</a>:</p>
<blockquote>
<p>As these keywords are <code><number></code>s, to get an infinite length, for example, requires an expression like <code>calc(infinity * 1px)</code>.</p>
</blockquote>
<p>Of course, this works as well:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8"> style="</span></span>
<span class="line"><span style="color:#E1E4E8"> border: solid</span></span>
<span class="line"><span style="color:#E1E4E8"> clamp(1px </span><span style="color:#85E89D">*</span><span style="color:#E1E4E8"> -infinity, 1em, 1px </span><span style="color:#85E89D">*</span><span style="color:#E1E4E8"> infinity);</span></span>
<span class="line"><span style="color:#E1E4E8">"</span><span style="color:#F97583">></span><span style="color:#E1E4E8">test</</span><span style="color:#85E89D">div</span><span style="color:#F97583">></span></span></code></pre>
<figure>
<div style="
border: solid
clamp(1px * -infinity, 1em, 1px * infinity);
">test</div>
<figcaption>
A live example that shows a thick border around the word “test”.
</figcaption>
</figure>
<p>I did use <code>1px * -infinity</code> instead of <code>-1px * infinity</code> just to test that it works as it should.</p>
<p>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 <a href="https://drafts.csswg.org/css-values/#css-infinity">defined in the specs as a valid way to get the infinity</a>:</p>
<blockquote>
<p>Dividing a value by zero produces either <code>+∞</code> or <code>−∞</code>, according to the standard sign rules.</p>
</blockquote>
<h2 id="use-cases">Use Cases</h2>
<p>Would I use this in the future? I don’t know. I think it is still a good idea to think of using the <code>clamp()</code> instead of the <code>min()</code> or <code>max()</code> right away — very often you’d still have to add the other bound later, and with <code>clamp()</code> it would be so much easier!</p>
<p>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 <em>optionally</em>, where the default values for both boundaries would be infinities, but could be provided via CSS variables.</p>
<h2 id="aside-starting-to-record-observations">Aside: Starting to Record Observations</h2>
<p>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 <a href="https://kizu.dev/">my main site</a>. However, how many interesting things I did stumble upon and did not share in pursuit of perfectionism?</p>
<p>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.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111402891311203006">on Mastodon</a>!</p>Observation: color-mix and currentColorhttps://blog.kizu.dev/color-mix-current-color/https://blog.kizu.dev/color-mix-current-color/Today I’ll share my observation that I initially wanted to work more on, but just had to get out sooner rather than later: we can use the `currentColor` inside `color-mix()`! And with that, we could modify an alpha channel of a color only with CSS.Wed, 29 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Karkade with raspberries</dd></dl><hr /><p>This post is sponsored by the second-to-last day of the month, and me not knowing what to write.</p>
<p>In frantic search for a topic, I remembered one thing I was keeping slightly under wraps — mostly because I wanted to do more experiments with it, probably fill more bugs, and, as usual, polish-polish-polish. But the whole idea of me trying to write more “observations” is to get away from it!</p>
<p>So, today I’ll share my observation: we can use the <code>currentColor</code> inside <code>color-mix()</code>! But only after I’ll share how we can modify the alpha channel of a color by using them.</p>
<p>Sounds simple enough and, maybe, obvious, but it works, look:</p>
<p><a href="https://blog.kizu.dev/color-mix-current-color/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.context</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hotpink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.test</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">color-mix</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#FFAB70"> in</span><span style="color:#79B8FF"> srgb</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> currentColor</span><span style="color:#79B8FF"> 50</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> transparent</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"context"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>This is a very pink text.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">>And this one has 50% opacity.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Right away, before I would explain what’s going on, I need to link to two things:</p>
<ol>
<li>
<p>The <a href="https://codepen.io/leaverou/pen/gOZZQZb?editors=1100">“Emulate basic relative color syntax with <code>color-mix()</code> + the <code>none</code> keyword”</a> by <a href="https://lea.verou.me/">Lea Verou</a> — I did already mention it twice on this blog. This is the third time!</p>
</li>
<li>
<p><a href="https://social.lol/@anniegreens/111480483490758075">This Mastodon post</a> by <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a>, in which she did, inadvertently, solved an issue I was trying to work around for some time.</p>
</li>
</ol>
<p>Lea’s CodePen was about how we can use <code>color-mix()</code> and mix colors that have <code>none</code> for some color stops.</p>
<p>For a while, I was trying to do the same, but only for adjusting the alpha component of a color, like this:</p>
<p><a href="https://blog.kizu.dev/color-mix-current-color/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.test-broken</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">color-mix</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#FFAB70"> in</span><span style="color:#79B8FF"> srgb</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> currentColor</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> rgba</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">none</span><span style="color:#79B8FF"> none</span><span style="color:#79B8FF"> none</span><span style="color:#E1E4E8"> / </span><span style="color:#79B8FF">50</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"context"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>This is a very pink text.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-broken"</span><span style="color:#E1E4E8">>And this one should have 50% opacity.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>But that doesn’t work anywhere, really (I’ve yet to fill a bug for one of the cases). Or this:</p>
<p><a href="https://blog.kizu.dev/color-mix-current-color/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.test-broken2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">color-mix</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#FFAB70"> in</span><span style="color:#FFAB70"> oklch</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> currentColor</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> oklch</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">none</span><span style="color:#79B8FF"> none</span><span style="color:#79B8FF"> none</span><span style="color:#E1E4E8"> / </span><span style="color:#79B8FF">50</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"context"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>This is a very pink text.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-broken2"</span><span style="color:#E1E4E8">>And this one should have 50% opacity.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This works in Firefox, works in Safari, but doesn’t in Chrome.</p>
<p>I even went to write web platform tests for that one (it was before I found out about the above issue), and they were merged, but! That’s still an ongoing thing, I’ll probably write about it at some point later.</p>
<p>Regardless. Now we can do this!</p>
<p><a href="https://blog.kizu.dev/color-mix-current-color/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.test</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">color-mix</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#FFAB70"> in</span><span style="color:#79B8FF"> srgb</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> currentColor</span><span style="color:#79B8FF"> 50</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> transparent</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"context"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>This is a very pink text.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">>And this one has 50% opacity.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>It is the same example as the first one, and it should work everywhere.</p>
<p>The crucial parts:</p>
<ol>
<li>
<p>We should use <code>srgb</code>. Other color spaces do not work the same for some reason (again — would probably need to investigate further — do you see how I’d want to spend more time on this instead of just writing about it?)</p>
</li>
<li>
<p>We should use <code>transparent</code>, and instead of having the alpha component there, we use the percentage with the first color!</p>
</li>
</ol>
<p>Now — we can use this method to adjust (srgb) colors, and get their versions with alpha channel modified! All thanks to Lea and Anne!</p>
<h2 id="wait-about-currentcolor">Wait About CurrentColor?</h2>
<p>I think I did sidetrack a bit. The other thing I wanted to share: that we can do this not just with some color, even if it comes from a CSS variable, but with a <code>currentColor</code>, even when used with <code>color</code> property!</p>
<p>Long story short: this works the same way as <code>font-size: 2em</code>. The <code>em</code> mentioned inside <code>font-size</code> is the <em>inherited</em> value of the font-size, and in the same way, <code>currentColor</code> mentioned inside the <code>color</code> is the <em>inherited</em> color.</p>
<p>I would really want to play with this a bit more, maybe involve <code>@property</code> in some way to see how things would behave with it, but I did promise myself that I need to learn when to stop — and here I am, doing this.</p>
<hr>
<p>The browser support for <code>color-mix()</code> might seem pretty good, <em>however</em>, as you could see from all the issues around color spaces and mixing — it might not be <em>as stable as we might think</em>. I’ll be cautious before using this in production seriously, there will need to be a lot of testing, and a lot of cross-browser testing.</p>
<p>A <a href="https://codepen.io/kizu/pen/LYqBZXB">quick test</a> that I did with this shows that Safari, Firefox and Chrome all render something in it differently except for the <code>srgb</code> with <code>transparent</code> method, which, I think, we <em>could</em> cautiously start trying.</p>
<p>But even if this is still unstable — I really encourage you to experiment with this. Try other color modes, try other ways to mix things up — and give your feedback to browsers! <code>color-mix()</code> is very powerful, and the sooner it will become stable, the better for everyone.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111495956645664377">on Mastodon</a>!</p>Fixing the Custom Ident Docshttps://blog.kizu.dev/custom-ident-mdn/https://blog.kizu.dev/custom-ident-mdn/Two days ago, I published a post named “Dashed Idents for Everything”, in which I did say that we could just use dashed idents in place of custom idents in CSS. In one of the replies, Taylor Hunt did mention that on the MDN page for custom idents it did state that we _cannot_ use dashed idents instead. I did my research and created a PR for MDN content, which did fix this.Mon, 20 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>Two days ago, I published a post named <a href="/dashed-idents-for-everything/">“Dashed Idents for Everything”</a>, in which I did say that we could just use dashed idents in place of custom idents in CSS.</p>
<p>In <a href="https://mastodon.social/@tigt/111434096284304777">one of the replies</a>, <a href="https://ti.gt/">Taylor Hunt</a> did mention that on <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident">the MDN page for custom idents</a> it did state that we <em>cannot</em> use dashed idents instead:</p>
<blockquote>
<p>A <code><custom-ident></code> must not be placed between single or double quotes[…]. Moreover, the first character must not be a decimal digit, nor a hyphen (-) followed by a decimal digit or another hyphen.</p>
</blockquote>
<p>Well, I just had to go do some more research: did I miss something in the specs? But no, wherever I did look, everything did seem to be ok with the dashed idents usage for custom idents. Browser testing did not also show any discrepancies.</p>
<p>So, I did go and fixed this on MDN via a <a href="https://github.com/mdn/content/pull/30374">pull request</a>. It is now merged, and my post does no longer contradict MDN.</p>
<p>Docs are not always correct — even when they’re written by humans (these written by LLMs could just go straight to the trash bin). If something seems weird, like if you notice a perceived difference between what is written in the docs and what you experience in practice — the best course of action is to do your own research and go and fix the docs. Or, at least, report this to the project. If I did not have opportunity to contribute this time, just filling an issue for MDN content would’ve been enough.</p>
<p>Anyway: contribute in any way you can! Report the bugs, write the tests, do the research, send the PRs. As with everything, at the start you might not know what to do, but when you’re used to it — this is the best way to interact with the web platform.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111444406117335714">on Mastodon</a>!</p>Dashed Idents for Everythinghttps://blog.kizu.dev/dashed-idents-for-everything/https://blog.kizu.dev/dashed-idents-for-everything/What do you think when you see --foo in CSS? Is this a custom CSS property? Maybe, but not necessary. It is a “dashed ident”, which is a variation of a “custom ident” (an author-defined identifier). In this post, I would explain why I’ve decided to always use one, but not the other, and would recommend you to do so as well.Sat, 18 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>What do you think when you see <code>--foo</code> in CSS? Is this a custom CSS property? Maybe, but not necessary.</p>
<p>It is a <a href="https://www.w3.org/TR/css-values-4/#dashed-idents">“dashed ident”</a>, which is a variation of a <a href="https://www.w3.org/TR/css-values-4/#custom-idents">“custom ident”</a> (an author-defined identifier).</p>
<p>You can read why we have these in the specs by the links above, but the main difference is: in the dashed ident there are two dashes at the start. That’s it, that’s the whole difference. At least in how it looks.</p>
<p>But there is a big difference in how it works.</p>
<p><strong>Not all places that accept a dashed ident would accept a custom ident</strong>.</p>
<p>If something wants a “dashed” one explicitly, for example, <a href="https://drafts.csswg.org/css-anchor-position-1/#name"><code>anchor-name</code></a> in anchor positioning, or a <a href="https://drafts.csswg.org/css-anchor-position-1/#name"><code>view-timeline-name</code></a> in scroll-driven animations — they won’t accept a regular ident.</p>
<p>When first encountering this difference, it might be challenging to adjust initially — and I did actually mention this in <a href="https://kizu.dev/anchor-positioning-experiments/">my article about anchor positioning</a>:</p>
<blockquote>
<p>One common mistake I initially had in my experiments — using the names without the double dashes in the beginning. The spec defines the names as <code><dashed-ident></code>, so they won’t be your usual idents, like with animation names or grid areas, but more like a CSS custom property’s name.</p>
</blockquote>
<p>My solution to this problem? See the title of this post. We can just use dashed idents for any author-defined identifiers. Yes, not all places would accept a custom ident, but <strong>any place that accepts custom idents, would also accept a dashed one</strong>.</p>
<p>By doing this, we achieve the following:</p>
<ul>
<li>We don’t have to remember if something accepts a custom ident or a dashed one.</li>
<li>We make it easier to understand that these idents are <em>author-defined</em> — the main reason to have them was to be able to distinguish them for the parser in places where there might be both author-defined identifiers present and other CSS keywords. There will never be a conflict between a dashed ident and a CSS keyword, this is guaranteed.</li>
</ul>
<p>Yes, the syntax is a bit more verbose, and yes, you might get used to dashed idents only being used for CSS variables. But that is changing, and I suspect more and more specs would allow only dashed idents, just because this makes writing the properties’ syntax definitions much easier.</p>
<p>What are the properties that we could start dashed idents for now?</p>
<ul>
<li>
<p>The counter name in <a href="https://drafts.csswg.org/css-lists/#auto-numbering">CSS counters</a>:</p>
<ul>
<li><code>counter-reset: --foo 1;</code>,</li>
<li><code>content: counter(--foo);</code>, and so on.</li>
</ul>
</li>
<li>
<p>Keyframes’ names in <a href="https://drafts.csswg.org/css-animations/#keyframes">CSS animations</a>:</p>
<ul>
<li><code>@keyframes --foo {}</code>,</li>
<li><code>animation: --foo 1s linear infinite;</code>, and so on.</li>
</ul>
</li>
<li>
<p><a href="https://drafts.csswg.org/css-view-transitions/#view-transition-name-prop">View transitions names</a> (I was a bit surprised that these were not required to be dashed):</p>
<ul>
<li><code>view-transition-name: --foo;</code>.</li>
</ul>
</li>
<li>
<p>Named grid lines and areas in <a href="https://drafts.csswg.org/css-grid/">CSS grids</a>. Ok, this one might be controversial, just because the definitions that are already rather verbose could become even more verbose. However! A usual mistake I do with CSS grids is using a string for the area name when doing something like <code>grid-column: 'foo'</code>, which, obviously, won’t work. I think this can often happen if you’d define the <code>grid-template-areas</code> as an ASCII string — it is logical to follow-up with it with a string usage as well. Using a dashed ident could remove this issue.</p>
<ul>
<li><code>grid-template-areas: "--start --content --end"</code>, or even</li>
<li><code>grid-template-rows: [--header-top] auto [--header-bottom --main-top] 1fr [--main-bottom]</code></li>
</ul>
<p>But yes, it can get verbose. But I think it is still worth it.</p>
</li>
</ul>
<p>Did I miss something? Maybe!</p>
<p>I have been using this notation for a while, and so far, I’m happy with it. If you’re attentive, you could’ve noticed it in my <a href="/snappy-scroll-start/">previous post</a>, where I used it for the keyframes’ name! One thing I wanted to try: create a stylelint rule that would enforse this. Maybe one day.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111431027836252836">on Mastodon</a>!</p>Extra Nesting Specificityhttps://blog.kizu.dev/extra-nesting-specificity/https://blog.kizu.dev/extra-nesting-specificity/Exactly a month ago, I started a thread on Mastodon about unlayered styles, which led to me bumping the corresponding CSSWG issue a bit more than two weeks ago. There was one CSS hack I did share in this thread which I did not yet write about in this blog, which I’m going to do now!Fri, 24 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>Exactly a month ago, I started <a href="https://front-end.social/@kizu/111291721848435193">a thread on Mastodon</a> about unlayered styles, which led to me bumping <a href="https://github.com/w3c/csswg-drafts/issues/6323">the corresponding CSSWG issue</a> a bit more than two weeks ago (<a href="/unlayered-styles-issue/">here is my short post about this</a>).</p>
<p>There was <a href="https://front-end.social/@kizu/111291771872519128">one CSS hack I did share in this thread</a> which I did not yet write about in this blog, which I’m going to do now!</p>
<p>Say welcome to… whatever this is:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">*</span><span style="color:#B392F0">:not</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">#a#b</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> & .</span><span style="color:#79B8FF">whatever</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> …</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>So, what we’re looking at? I present you a <em>kind of</em> workaround for the inability to use layers when there are unlayered styles present.</p>
<p>With CSS nesting <a href="https://caniuse.com/css-nesting">now available in all major browsers</a> (at the time of writing, I would still not recommend using it in production), we can easily add almost any selectors to our code as a wrapper, making it very convenient to write code without remembering that we have to mention something for every rule.</p>
<p>The <code>& .whatever</code> part in the above example is not interesting — there might be any nested rules, with almost any selectors nested right inside our root selector.</p>
<p>The point is: our root <code>*:not(#a#b)</code> would bump the specificity of anything nested inside by exactly two ID selectors.</p>
<p>The best part: this selector will always apply, is fast, and should never fail.</p>
<p>In the case of our <code>.whatever</code> class, we can think of the final selector as</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">*</span><span style="color:#B392F0">:not</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">#a#b</span><span style="color:#E1E4E8">) </span><span style="color:#B392F0">.whatever</span><span style="color:#E1E4E8"> {}</span></span></code></pre>
<p>This selector should match for an element with the class <code>whatever</code> if any (regardless of type, explicitly represented by a <code>*</code> for clarity) of its ancestors <strong>does not</strong> contain both an <code>id</code> with the value <code>a</code> <strong>and</strong> an <code>id</code> with the value <code>b</code>.</p>
<p>Obviously, an element cannot have two different IDs at the same time, but the selector is nevertheless valid, and, because it uses <code>:not()</code>, it would match for <em>anything</em>.</p>
<p>The only case where we’d have to be careful: if we’d want to match the <code>:root</code> or <code>html</code> (and maybe in some other rare cases), in which case we’d have to write <code>&:root</code> or <code>&:is(html)</code> inside the nesting. If we don’t have a parent to check — the selector would fail, so when we know of this, we’d add this selector directly to our root elements.</p>
<p>Did I mention that this selector will be fast? Browser engines match the selectors from right to left, so in this case they will first match the <code>.whatever</code>, then will look at this element’s direct parent, see that it does not contain two IDs, and stop. Only one parent node to check! And, because it is guaranteed that we’d stop matching on the first parent, it is not necessary to use the child combinator like <code>& > .whatever</code>.</p>
<p>It is also rather easy to fake “layers” with this method: just keep adding IDs inside the <code>:not()</code> to bump the specificity up, as a way to separate one group of rules from another!</p>
<p>I find this method very useful for custom website CSS overrides, as it is very rare that a site would have more than one <code>id</code> in a selector. The bigger problem is if there is an <code>!important</code> somewhere, and that’s why it would be nice to have a proper way to handle unlayered styles, and put another layer on top of them.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111467163950206314">on Mastodon</a>!</p>Observation: Range Input’s Thumb and Emerging CSShttps://blog.kizu.dev/input-range-thumb/https://blog.kizu.dev/input-range-thumb/Today would be a quick “observation”, but a longer prelude. I did stumble upon what I’ll elaborate on today back in June, but for several reasons I did not share or write about this. Today, I saw Adam Argyle’s CodePen, and first forked it, using that technique, and now I’m writing about it as a way to share my observations more widely.Wed, 15 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="a-long-prelude">A Long Prelude</h2>
<p>Today would be a quick “observation”, but a longer prelude. I did stumble upon what I’ll elaborate on today back in June, <a href="https://codepen.io/kizu/details/yLQVvdq">see this CodePen</a>, but for several reasons I did not share or write about this. These reasons:</p>
<ol>
<li>Fun fact: I never did really work with range inputs, so before I could do more experiments, I would need to learn much more about them.</li>
<li>I have no idea about their cross-browser compatibility, and the way they and their styles are specified. What are the differences? How likely my experiment could apply to other browsers when they’d get the features I’m using?</li>
<li>I did not have good use cases which to present. Usually, my experiments are very technical: I either achieve some effect, or not. And later, when I’m writing an article, I struggle the most with the actual examples. Like, I have all the use cases somewhere in my head, but it is always hard for me to actually access them. And I’m terrible at design — it takes me countless iterations to come up with something nice.</li>
</ol>
<p>These reasons, and other things my perfectionism used to contribute, were why I did an experiment, found something for myself, and moved on.</p>
<p>Now that I started trying to write more regularly, write about less polished stuff, and not pursue a perfection (at least not always), I want to continue posting just these small experiments and observations.</p>
<p>I can see how just sharing a technique behind what I’m doing can help eventually.</p>
<p>Yes, perfectionism tells me: “But hey, you could do so much more! Open a CSSWG issue! Read the specs! Experiment on this for another 20 hours!”</p>
<p>I need to learn not to do the maximum, but just share the minimum. The best part: I already have <em>so many drafts</em> of things that I <em>want</em> to do in a more perfect way, unless I’ll clone myself I won’t ever get to do all of that. So, a compromise of just throwing a seed of an observation when I know I cannot grow it fully is something I’m trying right now.</p>
<h2 id="to-the-point">To the Point</h2>
<p>If you did not yet look at <a href="https://codepen.io/kizu/pen/yLQVvdq">the CodePen I mentioned before</a>, now is the time! Ah, and look at it in Chrome, ideally in Chrome Canary with the Experimental Web Platform feature flag on.</p>
<p>This CodePen shows two things:</p>
<ol>
<li>We can define a <a href="https://drafts.csswg.org/scroll-animations/#view-timeline-shorthand"><code>view-timeline</code></a> on a <code>::-webkit-slider-thumb</code>, and then use this timeline to get the slider’s position!</li>
<li>We can define an <a href="https://drafts.csswg.org/css-anchor-position-1/#propdef-anchor-name"><code>anchor-name</code></a> on the same pseudo-element, and target it with anchor positioning!</li>
</ol>
<p>Ah, and as a bonus, I did also use another method to pass the hovered state from the thumb to the label outside. We cannot use <code>:has()</code> with pseudo-elements, so this is the only way I know we could do something like that.</p>
<p>Can this unlock numerous possibilities for styling the range input? Allowing us to use it to control things outside without JS? Maybe!</p>
<p>But, as I mentioned in the prelude, — I’m not optimistic that this technique would work in other browsers when scroll-driven animations and anchor positioning would get implemented in them. But maybe?</p>
<h2 id="anoccasion-toshare">An Occasion to share</h2>
<p>If I first experimented with this in June, is there a reason I’m sharing this particular example now? Yes.</p>
<p>This morning I saw <a href="https://codepen.io/argyleink/pen/XWOaazZ">this CodePen</a> by <a href="https://nerdy.dev/">Adam Argyle</a>, <a href="https://fosstodon.org/@codepen/111411277781075170">shared on Mastodon</a> by <a href="https://chriscoyier.net/">Chris Coyier</a>.</p>
<p>In this CodePen, Adam demonstrates how we can create an image comparison widget using a range input and just a tiny snippet of JavaScript to apply the current input’s value as a CSS variable, which is then used in all calculations.</p>
<p>Me, remembering my summer experiment, instantly went and <a href="https://codepen.io/kizu/pen/RwvLBqM">forked this CodePen</a> (view in Chrome), replacing this JS with this method using scroll-driven animations to pass the current range input’s state.</p>
<p>It is nice to have a good use case to apply a technique!</p>
<h2 id="future-observation">Future Observation</h2>
<p>In the Mastodon thread about this, <a href="https://www.bram.us/">Bramus</a> did also share his solution for this, also using scroll-driven animations, but in a different way. I did share <em>another observation</em> later, but I’ll save it for a future blog post. After all, I’m trying to post less polished things, right? And having an already decided topic for a future post is nice as well!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111416471974714218">on Mastodon</a>!</p>My First “Fediversary”https://blog.kizu.dev/first-fediversary/https://blog.kizu.dev/first-fediversary/Technically, I tried Mastodon for the first time on April 06, 2017, and tried again a few times over the next few years, but it did not stick with me at the time. I have some hobbies, but I’m not that deep into them. Not as deep as I’m in CSS and front-end, and, at the time, it was rather lonely to not have the people I enjoyed following for years around. That did change when Miriam Suzanne opened the front-end.social instance, and my presence there is what I’m celebrating today.Mon, 06 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Sigur Rós — Ágætis Byrjun</dd><dt>Current drink:</dt><dd>Sweet herbal tea (it is camomile and honey, but I don’t sense it)</dd></dl><hr /><p><em>Technically</em>, I tried <a href="https://joinmastodon.org/">Mastodon</a> for the first time on April 06, 2017, and tried again a few times over the next few years, but it did not stick with me at the time.</p>
<p>I have some hobbies, but I’m not that deep into them. Not as deep as I’m in CSS and front-end, and, at the time, it was rather lonely to not have the people I enjoyed following for years around.</p>
<p>That did change when <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> opened the <a href="https://front-end.social/about">front-end.social</a> instance, and <a href="https://front-end.social/@kizu">my presence there</a> is what I’m celebrating today.</p>
<p>I can say that, right now, almost everyone I care about in the front-end world is present either on this instance or in its neighborhood — having a dedicated place for active, sensible people made the whole experience good enough. Critical mass, all of that.</p>
<p>Since the time the LiveJournal started to lose people due to all the social networks pulling people out into their nets, I always had this thought that it is not the place that is important but the people there. Sadly, at the time, people did not really move to just one social network — some moved to twitter, some to facebook, to instagram, somewhere else.</p>
<p>LiveJournal was mostly pseudonymous, allowing you to create connections with people you would never meet in real life and who had completely different lives from you. The real-name policies of most social networks and the absence of control over your community led to people dissipating into the air. I could follow some of my older friends to one place, but not to another.</p>
<p>Even though most of the people I follow on Fediverse now are on Mastodon, I really like the idea that it is possible to have <em>different types</em> of networks, all connected, where you would not need to go and create another separate account in order to follow and connect with someone.</p>
<p>Like, there are things like <a href="https://pixelfed.org/">Pixelfed</a>, <a href="https://joinbookwyrm.com/">Bookwyrm</a>, and the whole IndieWeb way of connecting your website as almost a first-class citizen to the Fediverse (see <a href="https://fed.brid.gy/">Bridgy Fed</a> for example).</p>
<p>Now, even if something happened to <a href="https://front-end.social/about">front-end.social</a> in the worst-case scenario, I believe things would still be ok. People would move to other places in the Fediverse, could keep following almost everyone they did previously, and ideally could move all the followers along with them (though I wish Mastodon did provide some backup mechanism in case the server goes black, and you’re unable to set up the migration).</p>
<p>All in all, I’m very happy to be on Mastodon and a part of the Fediverse as a whole. To the next anniversary!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111365587215205894">on Mastodon</a>!</p>Layer Overrides Updatehttps://blog.kizu.dev/layer-overrides-update/https://blog.kizu.dev/layer-overrides-update/Two days ago, I wrote an “Unlayered Styles Issue” post, where I shared a link to my comment in a GitHub issue about unlayered styles. Since then, there was a brief discussion, after which the issue was reopened — yay!Thu, 09 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>Two days ago, I wrote an <a href="/unlayered-styles-issue/">“Unlayered Styles Issue”</a> post, where I shared a link to my comment in <a href="https://github.com/w3c/csswg-drafts/issues/6323">a GitHub issue about unlayered styles</a>.</p>
<p>Since then, there was a brief discussion, after which the issue was reopened — yay!</p>
<p>Now, the question is: what should be the direction the issue would move towards. There were a few different proposals over how to allow putting styles after the unlayered ones, the best one was <a href="https://github.com/w3c/csswg-drafts/issues/6323#issuecomment-939655516">first proposed</a> by <a href="https://github.com/FremyCompany">François REMY</a>:</p>
<blockquote>
<p>Another possibility is to add another layer that is not the unstyled layers but is one just after it. Then confusion drops a lot I guess, especially if we give it a better name.</p>
<p>Something like <code>@layer !important.xyz { ... }</code> where the <code>!important</code> layer is a special layer that is above the unstyled styles.</p>
</blockquote>
<p>I did not first see this proposal, but after some thinking did propose essentially the same in <a href="https://github.com/w3c/csswg-drafts/issues/6323#issuecomment-1804503198">my most recent comment there</a>:</p>
<blockquote>
<p>After some thoughts, my idea: what if we’d have a <em>single, system layer</em> which could be used to place other layers <em>after</em> the unlayered styles?</p>
<p>Let’s say this system layer would be named <code>!overrides</code>. Then, let’s say it places nested styles after the unlayered styles <em>only</em> within the same parent layer (if any).</p>
<p>What this would mean:</p>
<ol>
<li>We cannot create an arms race, as we have only one entry point for every layer that can be used to put styles into an “overrides” part.</li>
<li>As we can put other layers inside this layer, we could continue to write our new styles using layers in any way.</li>
<li>We don’t need to handle any specific syntax or complexity outside adding this one specific named layer.</li>
</ol>
</blockquote>
<p>See — basically a repeat of what François wrote.</p>
<p>I really think this is the best out of all proposals there. And, I think I could even use it inside the other layered styles I could write, as a way to first write some unlayered defaults:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@layer</span><span style="color:#E1E4E8"> my-component {</span></span>
<span class="line"><span style="color:#B392F0"> .my-component</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* some styles */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &:is(:hover, :focus-visible) {}</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> & {}</span></span>
<span class="line"><span style="color:#6A737D"> /* some other styles with any specificity */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Then, if I would want to add some <em>modifiers</em> to this component (let’s put aside if we actually want to have a layer per component), but would like these modifiers to go <em>over</em> the component’s styles, I could do this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@layer</span><span style="color:#E1E4E8"> my-component {</span></span>
<span class="line"><span style="color:#B392F0"> .my-component</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* some styles */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &:is(:hover, :focus-visible) {}</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> & {}</span></span>
<span class="line"><span style="color:#6A737D"> /* some other styles with any specificity */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @layer</span><span style="color:#E1E4E8"> !overrides {</span></span>
<span class="line"><span style="color:#E1E4E8"> &</span><span style="color:#B392F0">:disabled</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* Some styles, now guaranteed over any</span></span>
<span class="line"><span style="color:#6A737D"> default styles. */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>If I wanted to add multiple different layers as overrides, then I could either use the same dot notation to make each of them <code>@layer !overrides.disabled</code> etc., or I could nest (or import!) these as their layers inside our overrides:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@layer</span><span style="color:#E1E4E8"> my-component {</span></span>
<span class="line"><span style="color:#B392F0"> .my-component</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* some styles */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &:is(:hover, :focus-visible) {}</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> & {}</span></span>
<span class="line"><span style="color:#6A737D"> /* some other styles with any specificity */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @layer</span><span style="color:#E1E4E8"> !overrides {</span></span>
<span class="line"><span style="color:#F97583"> @layer</span><span style="color:#E1E4E8"> disabled {</span></span>
<span class="line"><span style="color:#E1E4E8"> &</span><span style="color:#B392F0">:disabled</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* Some styles, now guaranteed over any</span></span>
<span class="line"><span style="color:#6A737D"> default styles. */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @layer</span><span style="color:#E1E4E8"> something-else {}</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>But, of course, the main profit would come from an ability to add any styles after unlayered styles in the <em>topmost</em> unlayered context, where there is no a single parent layer surrounding our content. All these cases would become possible:</p>
<ul>
<li>Adding custom browser style overrides in browser extensions like <a href="https://addons.mozilla.org/en-US/firefox/addon/styl-us/">Stylus</a> — now without any need to care about the specificity of the selectors on the sites we override!</li>
<li>Adding custom styles for Mastodon instances: it would be much easier to write them with this, as it would be possible to write some kind of reset for everything. And then <em>have this reset be in its layer</em>, allowing to write new layers with simple styles using only what is necessary in their selectors.</li>
<li>Writing layered styles for anything new in legacy environments: like, let’s say you have an older website, where you don’t want to wrap all the existing styles in a layer, as you would rather not reduce the browser support for all the existing styles. Now we would be able to write new styles that are guaranteed to override the old styles, with layers. This is especially crucial for older sites, where non-BEM (and not idiomatic in any way) selectors could contain multiples ID selectors in them, and just be very unpleasant to work with.</li>
</ul>
<p>There are so many cases where I would already start using CSS layers, but can’t because there are some unlayered styles getting in the way. I really hope we would get the ability to do something about this sooner rather than later.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111382549013254083">on Mastodon</a>!</p>Moving to Firefoxhttps://blog.kizu.dev/moving-to-firefox/https://blog.kizu.dev/moving-to-firefox/I tried the Arc browser for a few months, and finally decided that I don’t really like it that much. Now, I’m starting to migrate (slowly) to Firefox Nightly.Wed, 08 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="what-i-had-before">What I Had Before</h2>
<p>I tried the <a href="https://arc.net/">Arc browser</a> for a few months, and finally decided that I don’t really like it that much.</p>
<p>The main thing that I would miss is the “little arc”: the temporary window for new tabs and for the tabs from external applications.</p>
<p>Other than this, I tried using a lot of its features, but was frustrated at a lot of small bugs here and there. And it did seem like with each release things got worse and worse. Most of my issues were related to window management and multiple monitor set up: not remembering the window size and position, boosts window opening weirdly, incorrect behavior of maximize button and double-clicking on browser window edges among other things.</p>
<p>The last straw was when I saw how it applies the custom styles from its “boosts” feature — as <em>user agent origin</em>! You could ask why this is an issue. This makes it, so any overrides <em>require</em> adding <code>!important</code> — without it, they would always be lower in the cascade compared to any styles on any elements.</p>
<p>I suspect this was a decision based on “oh, but the important styles from the user agent would win over anything!”, but yeah, this makes things much less convenient to override. I wish we had <a href="/unlayered-styles-issue/">the ability to use CSS layers for overrides</a>!</p>
<p>Anyway.</p>
<h2 id="what-im-moving-to">What I’m Moving To</h2>
<p>Now, I’m starting to migrate (slowly) to <a href="https://www.mozilla.org/en-US/firefox/nightly/notes/">Firefox Nightly</a>.</p>
<p>Why “Nightly”? A lot of my custom styles require <code>:has()</code> support, and — yay! — Nightly already supports it well enough.</p>
<p>Here is a small list of add-ons I’m currently trying (thanks, <a href="https://pepelsbey.dev/">Vadim</a>, for some of your recommendations!), in alphabetical order:</p>
<ul>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/awesome-rss/">Awesome RSS</a> — Show the “RSS” button in the address bar for the sites that have it.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/">Firefox Multi-Account Containers</a> — I think I had some cases where I would use this, but as I’m just migrating, I have not had a chance to use it yet.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/languagetool/">LanguageTool</a> — The grammar checker I’m using.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/styl-us/">Stylus</a> — Adding CSS overrides to the websites.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/tree-style-tab/">Tree Style Tab</a> — I like the idea of displaying tabs as a tree when doing some research. I wish there was a simple way to just hide the existing tabs, though.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/">uBlock Origin</a> — Content blocker.</li>
</ul>
<h2 id="recommend-me-stuff">Recommend Me Stuff!</h2>
<p>As I’ve just started, I have no idea how things work, what the best settings are, or how to customize things further (I know that you can do a lot with CSS, which is awesome).</p>
<p>If you’ve got any preferences, add-on or setting suggestions, or just life hacks, throw them at me!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111376720437974927">on Mastodon</a>!</p>My First Web Platform Testshttps://blog.kizu.dev/my-first-web-platform-tests/https://blog.kizu.dev/my-first-web-platform-tests/I wanted to start contributing to the Web Platform Tests for a while, and a few weeks ago I finally got to read the documentation and push my first commit there, with another one following suit today.Fri, 03 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — breath on one night</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>I wanted to start contributing to the Web Platform Tests for a while, and a few weeks ago I finally got to read <a href="https://web-platform-tests.org/">the documentation</a> and push my <a href="https://github.com/web-platform-tests/wpt/pull/42676">first commit</a> there, with <a href="https://github.com/web-platform-tests/wpt/pull/42940">another one</a> following suit today.</p>
<p>I found it easy in some ways and hard in others, so I decided to share what I had to do in order to contribute, along with some links you might find helpful.</p>
<h2 id="why-contribute-to-wpt">Why Contribute to WPT?</h2>
<p>Like bug reporting itself, contributing to WPT might seem daunting and rather bothersome at first glance. However, the best thing: do it once, understand how things work, and the next time it will be much smoother.</p>
<p>By following all the steps, like properly reducing the bug (this in itself is probably worth a separate post), understanding the issue, and reading the specs, you’ll learn so much! It is much better to understand what you’re doing and not just throw things at a wall, waiting until something sticks.</p>
<p>By reporting the issues you find, you contribute to fixing the problems at their core. It is useful to find workarounds and share them, but it is even better to report the issues (and the actual bug reports are a good place to mention your workarounds as well!).</p>
<p>And by writing the tests for the Web Platform, you make it even more likely that the issue will be fixed. If the problem is in the Interop initiative, it could get picked up much quicker. And some browsers monitor the new failures in WPT, for example, Firefox opens new bugs in its tracker automatically.</p>
<h2 id="the-docs">The Docs</h2>
<p>The place to start would be the official documentation site: <a href="https://web-platform-tests.org/">https://web-platform-tests.org/</a></p>
<p>There is <em>a lot</em>, but overall, I found most of the information I needed.</p>
<p>As I’m mostly interested in writing CSS tests, I had no need to read all the documentation; I only needed to read the parts required for what I wanted to do. This is the approach I’d recommend for any docs— unless you’re really interested in <em>everything</em>, usually it makes sense to only go into sections that you need <em>now</em> and try not to read anything that would not help you solve the problem at hand.</p>
<p>For example, I only updated the tests using <a href="https://web-platform-tests.org/writing-tests/testharness.html">testharness</a>; for these, I have no need to use the <code>run</code> command, only the <code>serve</code> one.</p>
<h2 id="my-contributions">My Contributions</h2>
<p>In this section, I’ll just put links to the WPT PRs I did open, so you could look at how I wrote them and the PR description:</p>
<ul>
<li><a href="https://github.com/web-platform-tests/wpt/pull/42676">Tests for <code>round()</code>, <code>mod()</code>, and <code>rem()</code> that has a percentage only for one value</a>
<ul>
<li><a href="https://bugs.webkit.org/show_bug.cgi?id=263711">Bug in the bug tracker</a> (open).</li>
</ul>
</li>
<li><a href="https://github.com/web-platform-tests/wpt/pull/42940">Tests for <code>color-mix()</code> with a single component change</a></li>
</ul>
<p>Note that neither adding tests nor opening bug reports guarantees that the problem will get fixed soon. But by doing this, you’re making the fix more likely, and this helps everyone in the long run.</p>
<h2 id="my-workflow">My Workflow</h2>
<p>The way I contributed to the WPT was as an alternative to the first step of reporting the bugs. Usually I just went and reproduced the issue somewhere (like in CodePen) to understand the exact issue, then went into the browser’s bug tracker and tried to find the bug. Then I would create one if one was not found, post my use case into the existing one, or just star or cc myself for it.</p>
<p>With WPT, there are a few extra steps.</p>
<h3 id="initial-investigation">Initial Investigation</h3>
<ol>
<li>
<p>Make sure you can reproduce the issue in the latest version of the browser (s) you see the bug in. Very often, it might be something that is already known and already has a fix on its way. If you cannot see the issue in the latest version, then there is a big chance that it is already fixed. The latest versions I’m usually checking things in are (don’t forget to update them before checking):</p>
<ul>
<li>
<p><a href="https://www.google.com/chrome/canary/">Chrome Canary</a></p>
</li>
<li>
<p><a href="https://developer.apple.com/safari/technology-preview/">Safari Technology Preview</a></p>
</li>
<li>
<p><a href="https://www.mozilla.org/en-US/firefox/nightly/notes/">Firefox Nightly</a></p>
</li>
</ul>
</li>
<li>
<p>Make sure there <em>is</em> a bug: usually it is enough if there is a difference between browsers, and this difference is there because of the vagueness of the specs. Yes, you’ll probably need to read some specs to see what the intended effect is. After all, you might find out that the browser-outlier is actually the one rendering things correctly, and you’d need to file a bug against two other browsers.</p>
</li>
<li>
<p>Check if this is a known issue. Before, I only checked the bug trackers, now this consists of two steps:</p>
<ul>
<li>
<p>Go to <a href="https://wpt.fyi/">https://wpt.fyi/</a> and try to find the test suite for the feature you want to report the issue to. It is likely there is already a related test that fails — sometimes it might have a “bug” icon near it, leading to the browser’s bug tracker. If there is a failing test but no bug mentioned, you might want to check the bug tracker to see if there is a place you could put your use case or help prioritize the fix.</p>
</li>
<li>
<p>Go to the browser’s bug tracker and try to find the issue you’re having. Usually, I’m looking only at the open bugs, but sometimes, if you do not find anything open that fits your case, it might make sense to look at the duplicates as well, as they could point towards more generic open bugs that you did not think fit your case. Links to the browser bug trackers:</p>
<ul>
<li>
<p><a href="https://bugs.webkit.org/">Safari/WebKit</a></p>
</li>
<li>
<p><a href="https://bugzilla.mozilla.org/index.cgi">Firefox/Gecko/Mozilla</a></p>
</li>
<li>
<p><a href="https://bugs.chromium.org/p/chromium/issues/list">Chrome/Chromium/Blink</a></p>
<p>Note that in January 2024 Chromium tracking <a href="https://developer.chrome.com/blog/chromium-issue-tracker-migration/">will migrate</a> to the <a href="https://developers.google.com/issue-tracker">Google Issue tracker</a>.</p>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p>Now, if you did not find the existing bug, or if you did find one, but it did not have WPT tests for it, or the existing tests did not cover your specific case, this would be the time to go and attempt to contribute to WPT.</p>
</li>
</ol>
<h3 id="writing-the-test">Writing The Test</h3>
<p>Note: for now, I only contributed to the <a href="https://web-platform-tests.org/writing-tests/testharness.html">testharness</a> unit tests by modifying the existing test suits. Writing a new test (and <a href="https://web-platform-tests.org/writing-tests/reftest-tutorial.html">writing reftests</a>) is a slightly different beast; when I do that, I’ll try to update this post. However, a lot of what I’ll mention should apply to the new tests as well.</p>
<p>At this point, you should already have a minimally reproducible case. If not, now is the time to finally remove things from your example code to find the point where the bug becomes obvious.</p>
<h4 id="cloning-the-repo-and-setting-things-up">Cloning the Repo and Setting Things Up</h4>
<p>I’ll write what <em>I</em> did — I’m on macOS, for you, the setup could be different.</p>
<p>Usually, it is recommended to first fork the repo, but I found it worked better for me to clone the repo first and then add a fork as an additional remote.</p>
<ol>
<li>Clone the repo: <code>git clone [email protected]:web-platform-tests/wpt.git</code>.</li>
<li>Fork it through GitHub UI.</li>
<li>Add the fork as a remote, in my case, it was <code>git remote add fork [email protected]:kizu/wpt.git</code> (obviously, use your own URL there).</li>
<li>Set up the hosts file: <code>./wpt make-hosts-file | sudo tee -a /etc/hosts</code> (note that there is a <code>sudo</code> command — if you’re cautious, you could go into the repo and see what this would do).</li>
<li>Run the dev server: <code>./wpt serve</code>.</li>
<li>Find the port where it did open it: basically, one of the <code>https on port …</code> entry, for example, one with <code>Starting https server on https://web-platform.test:8443</code>. There might be multiple of them, all working. I’m not sure what the difference is, to be honest.</li>
<li>Open the URL in your browser — it should work (though it might complain about the certificates). Now you could navigate inside to any test and check it out, or you could find the relative URL for the test you want to find and go to it there directly.</li>
</ol>
<p>The main problem you probably have now is finding <em>where</em> to place the test.</p>
<h4 id="where-to-place-the-test">Where to Place the Test</h4>
<p>In my case, it was these places:</p>
<ul>
<li><code>css/css-values/round-mod-rem-computed.html</code></li>
<li><code>css/css-color/parsing/color-computed-color-mix-function.html</code></li>
</ul>
<p>There are multiple ways to look up an appropriate place:</p>
<ul>
<li>Use <a href="https://wpt.fyi/">https://wpt.fyi/</a> to find the place that seems like it fits.</li>
<li>Use the <a href="https://github.com/search?q=repo%3Aweb-platform-tests%2Fwpt%20&type=code">GitHub code search</a> at <a href="https://github.com/web-platform-tests/wpt">https://github.com/web-platform-tests/wpt</a> with some parts of the code you did find a bug in to find a place that looks similar to what you want to add.</li>
<li>Use the search in your editor of choice for the cloned repo to do basically the same.</li>
</ul>
<p>When you first read about the reftests, it might seem that they could be the best way to add tests — but, in my opinion, it is better to first try and find a testharness place to add a smaller unit test.</p>
<p>These run much faster and are much easier to test automatically. I suspect that if I wanted to test the reftests automatically (outside manual comparison in the browsers — a valid way in itself), you’d need to set up the <code>./wpt run</code> command (which I did not).</p>
<h3 id="add-your-test">Add Your Test</h3>
<p>The testharness tests usually test a bunch of different combinations and permutations of things.</p>
<p>As they run fast, it might make sense to add a lot of them, but only if the cases make sense. The problem of “what exactly to add as unit tests” is a much bigger issue, and I do it rather intuitively, based on my experience. Not too little, not too much — just enough to cover most of the cases I can think of at once. There is no need to do the same thing with different input unless the difference is obvious.</p>
<h3 id="commit--push-the-code-toyour-branch-open-apr">Commit & Push the code to your branch, open a PR</h3>
<p>I won’t provide a <code>git</code> tutorial on how to create a branch and all, main thing is not to forget to push your branch into your remote fork, like <code>git push -u fork my-branch</code>.</p>
<p>Similarly, in this post I won’t describe how to open a PR or what to write there — I think I already wrote a bit too much for what I initially thought would be a short post!</p>
<p>Maybe I’ll cover the way I tend to write PR descriptions at a different time.</p>
<h2 id="thats-it">That’s It</h2>
<p>Both my PRs were reviewed and merged rather quickly without any issues. Thanks, <a href="https://dbaron.org/">David Baron</a> and <a href="https://svgees.us/">Chris Lilley</a> for reviewing!</p>
<p>After the PRs are merged, I prefer to wait until WPT builds the tests, and it would be possible to see the new failing tests at <a href="https://wpt.fyi/">https://wpt.fyi/</a>. Then it would be time to report these bugs to the trackers.</p>
<p>Hopefully, you found this post useful! I highly encourage you to try and get into the groove of getting to the core of the bugs you encounter, reporting them and maybe even writing WPT tests yourself. It might be a bunch of work, but it is worth it, in my opinion!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111348582689564296">on Mastodon</a>!</p>One Month of Writinghttps://blog.kizu.dev/one-month-of-writing/https://blog.kizu.dev/one-month-of-writing/I did post for every day of this month. In the spirit of this challenge, this is a short post, in place of something larger. A proper “wrap-up” will be at some later date — I’ll need to take some time off to think about all of this!Thu, 30 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>Here I am, writing my last post of this month.</p>
<p>I did, in fact, write in this blog for every day of November.</p>
<p>I probably won’t do this ever again!</p>
<p>As an ultimate conclusion for the idea of this month — and this blog — I won’t spend time wrapping everything up, making a neat list of everything I wrote (though I did update the <a href="/">main page</a>, just experimenting with the style of all articles’ list). I don’t want to rush it, and I want to think more about what I actually did achieve or not.</p>
<p>One thing is certain: for some reason, I did succeed in this weird challenge. Maybe some of the things I shared were helpful for someone? I don’t know.</p>
<p>I guess, after this post, I could take a bit of a rest from these daily posts. Well, I’ll continue the “weekly” series, or perhaps I’ll take one week off — we’ll see!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111501149906517458">on Mastodon</a>!</p>Personal Site Anniversary & Historyhttps://blog.kizu.dev/personal-site-anniversary/https://blog.kizu.dev/personal-site-anniversary/Today is the 22nd anniversary of my first HTML page on the web: November 4th, 2001. Quite a long time going! Initially, I wanted to post a longer history of my personal website(s), but looking at all the archives, that would be a much longer task, especially if I would like to show the screenshots and examples of what I had. For now, I’ve decided to write a shorter post.Sat, 04 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Smother</dd><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Today is the 22nd anniversary of my first HTML page on the web: November 4th, 2001. Quite a long time going!</p>
<p>Initially, I wanted to post a longer history of my personal website(s), but looking at all the archives, that would be a much longer task, especially if I would like to show the screenshots and examples of what I had. For now, I’ve decided to write a shorter post.</p>
<h2 id="some-interesting-notes">Some Interesting Notes</h2>
<p>In the beginning, it was a non-technical, childish site; I moved from one free hosting provider to another in 2001 and “redesigned” that site, I think, eight times? Not counting the not-finished designs.</p>
<p>In 2008, I purchased my first domain and started a technical blog, which evolved over time into what we can currently see at <a href="https://kizu.dev">https://kizu.dev</a></p>
<p>Here is the beginning of the timeline for my personal site and my history with the web.</p>
<h3 id="2001">2001</h3>
<ul>
<li>
<p>Before I did start working on my site (I think on November 1st, so it was done rather quickly), I did touch HTML <em>a little</em> during the summer school in June the same year. There was a project for a photo gallery to burn on a CD, with the gallery being made with JS. I think I did mostly content management there, but that exposure was probably what led to me creating my website (as well as a website dedicated to Baldur’s Gate from a school friend).</p>
</li>
<li>
<p>My first site was on the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frameset">framesets</a>!</p>
</li>
<li>
<p>Here is the full HTML of the <code>index.htm</code> that I had:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">html</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">head</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">>Kizmarh's Cave</</span><span style="color:#85E89D">title</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">head</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#FDAEB7;font-style:italic">frameset</span><span style="color:#B392F0"> rows</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"74,*"</span><span style="color:#FDAEB7;font-style:italic"> border</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">0</span><span style="color:#E1E4E8">><</span><span style="color:#FDAEB7;font-style:italic">frame</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"menu.htm"</span><span style="color:#B392F0"> name</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"menu"</span><span style="color:#B392F0"> noresize</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#FDAEB7;font-style:italic">frame</span><span style="color:#B392F0"> src</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"news.htm"</span><span style="color:#B392F0"> name</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"document"</span><span style="color:#B392F0"> noresize</span><span style="color:#E1E4E8">></</span><span style="color:#FDAEB7;font-style:italic">frameset</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">html</span><span style="color:#E1E4E8">></span></span></code></pre>
</li>
<li>
<p>I won’t show you the content of the frames themselves, but there were <em>tables</em>. As in, using tables for the page layout. This would stay for the whole journey of my nontechnical site (I stopped working on it somewhere around 2006).</p>
</li>
<li>
<p>There was no CSS, not even inline styles.</p>
</li>
</ul>
<h3 id="2002">2002</h3>
<ul>
<li>
<p>My first redesign and hosting change!</p>
</li>
<li>
<p>Framesets were gone, but tables did stay.</p>
</li>
<li>
<p>I used JS to implement images changing on hover via inline events:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">onmouseover='document.qqq.src="mpic2.gif"' onmouseout='document.qqq.src="mpic.gif"'</span></span></code></pre>
</li>
<li>
<p>Later the same year, I rewrote that site to be an SPA. Yes. Just one page, where I did change the content of the sections via JS. But hey, I did also write my first line of CSS: <code>overflow:auto</code> as an inline style!</p>
</li>
<li>
<p>That version of the site had “Best viewed in Internet Explorer”.</p>
</li>
<li>
<p>I think this version of the site did participate in a contest and won first place. I would not give <em>that</em> the first place today.</p>
</li>
</ul>
<h3 id="2003">2003</h3>
<ul>
<li>
<p>I ditched SPA and kept things simple.</p>
</li>
<li>
<p>Every page had a different design, and I used <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map">image maps</a> in a few places!</p>
</li>
<li>
<p>There was still no new CSS on the personal site itself.</p>
</li>
<li>
<p><em>However</em>, looking through the archives of my files, I found some of my earlier experiments with CSS, from October 26. Here is how I wrote an external stylesheet, then. It’s pretty, isn’t it?</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">body</span><span style="color:#E1E4E8"> {</span><span style="color:#79B8FF">background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#000000</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> font</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">11</span><span style="color:#F97583">pt</span><span style="color:#E1E4E8">/</span><span style="color:#79B8FF">14</span><span style="color:#F97583">pt</span><span style="color:#79B8FF"> Serif</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#FFFFFF</span><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">a</span><span style="color:#E1E4E8"> {</span><span style="color:#79B8FF">text-decoration</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#BBBBBB</span><span style="color:#E1E4E8">}</span></span></code></pre>
</li>
<li>
<p>And here is, as you could tell, my first <em>CSS experiment</em>: masking an e-mail against spambots (with a more modern e-mail):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"font:11pt/0pt Courier"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">k</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">z</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">a</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">h</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">g</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">a</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">l</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">c</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">m<</span><span style="color:#85E89D">br</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">i</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">m</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">r</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">@</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">m</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">i</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">o</span><span style="color:#79B8FF">&nbsp;</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>It still works!</p>
<figure>
<p style="font:11pt/0pt Courier">k z a h g a l c m<br> i m r @ m i . o </p>
<figcaption>
A live example that _looks_ like normal text, but actually contains gibberish, like when trying to copy it, or access in any non-visual way.
</figcaption>
</figure>
<p>I don’t think I ever used this in production — at some point I just started using the unmasked e-mails and did not notice a bump in the volume of spam.</p>
</li>
<li>
<p>Later in December, I did create my LiveJournal account.</p>
</li>
</ul>
<h3 id="2004">2004</h3>
<ul>
<li>
<p>Two more redesigns of the personal site, still nothing new there.</p>
</li>
<li>
<p>I think I did work a bit on a website for my Mom’s job. I don’t remember any context, and there is a chance I first did it in 2001, but I don’t believe the file timestamps, as the site did already contain some CSS, which did not look like something I would write in 2001. But it looks more fitting for 2004.</p>
</li>
<li>
<p>I started doing my first LiveJournal themes, customizing them via <a href="https://www.livejournal.com/support/faq/124.html">S1 overrides</a>. You could add custom HTML and CSS to your “social network profile” then!</p>
</li>
</ul>
<h3 id="2005">2005</h3>
<ul>
<li>
<p>I redesigned my personal site once again, but it was still using tables.</p>
</li>
<li>
<p>However, I made the design of the pages fully responsive! Before that, I used fixed layouts, now it was a <code><table></code> with <code>width=100% height=100%</code>.</p>
</li>
<li>
<p>I started practicing a bit more with CSS, probably closer to the end of the year. One thing I did was rewrite one random web page’s layout from tables to floats and absolute positioning. It also had text-shadows made by using duplicate content and <code>z-index</code>.</p>
</li>
</ul>
<h3 id="2006">2006</h3>
<ul>
<li>
<p>I did not update my personal site.</p>
</li>
<li>
<p>I was mostly doing the themes for LiveJournal.</p>
</li>
<li>
<p>December 26: I decided to read the CSS2.1 specs in full.</p>
</li>
</ul>
<h3 id="2007">2007</h3>
<ul>
<li>January: I started working officially as a full-time front-end web developer.</li>
</ul>
<h3 id="2008">2008</h3>
<ul>
<li>February: I published my first technical website on a personal domain.</li>
</ul>
<h2 id="to-be-continued">To Be Continued!</h2>
<p>Sadly, it seems that while for some older files the timestamps are intact, for anything starting from 2006 there are not a lot of correct ones. Maybe if I could find a proper archive somewhere that did retain everything…</p>
<p>In 2006, I was not in a good place closer to the end of the year, quitting the university and feeling quite worthless overall. I was lucky to finally land a job and start working as a developer full-time. Things have gotten much better since then for me. I’m happy where I am now (internally; externally… not so much).</p>
<p>Maybe one day I will revisit this post — or write a new one — and update this timeline, adding new notes and maybe adding examples of some of my earlier experiments or LiveJournal themes. Sharing funny snippets of code here and there.</p>
<p>If you have your own personal website, when did you start it? How did it evolve? I think it might be interesting to revisit your old code and your old self sometimes. I would be interested in reading more people’s stories about how they started their journey with the web platform.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111353775964827171">on Mastodon</a>!</p>Posting on a Schedulehttps://blog.kizu.dev/posting-on-a-schedule/https://blog.kizu.dev/posting-on-a-schedule/I did not have an opportunity to write something useful today. So, I’ll write something random? After all, this is my less polished blog, in which I, at least initially, wanted to start posting less technical things. Well, did not do well on the “less technical” part, but so far, I actually managed to post every day of November. Surprised myself with this! In this post, I’m sharing some observations from this experience so far.Tue, 21 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Peppermint tea</dd></dl><hr /><p>I did not have an opportunity to write something <em>useful</em> today. So, I’ll write something random? After all, this is my less polished blog, in which I, at least initially, wanted to start posting less technical things. Well, did not do well on the “less technical” part, but so far, I actually managed to post every day of November. Surprised myself with this!</p>
<p>Some observations:</p>
<ol>
<li>
<p>The later it gets in the day, the harder it is to start writing, especially if that is something technical. Like, even while publishing less polished things, I still want them to have <em>some</em> quality. That means that if I have a certain thing I want to share, I still need to do a bit of research, write at least one example, and so on. All this takes time, and even if it won’t take much time in reality, when it is late, I guess I’m just afraid that <em>what if it would take too long</em>.</p>
</li>
<li>
<p>That brings me to the next thought: I won’t probably attempt something like that in the future. Posting every day is exhausting! I never liked deadlines, never liked <em>habits</em> and <em>traditions</em>. It might be fun to try something like <a href="https://indieweb.org/National_Blog_Posting_Month">NaBloPoMo</a> once in a while. I can see how practicing this makes it easier to just go and write something not as polished, I just don’t think the compromises I do with myself to pursue it are worth it. I think I’m capable enough to learn the things that are useful to me, and throw away what does not work.</p>
</li>
<li>
<p>Having things prepared in advance would help! I could go and write N small posts about different things in one day, and then just post them every other day. For some reason, I feel that as cheating. After all, that would be <em>an effort</em> to do all of that in one go. And, so far, I think I managed to choose topics relatively spontaneously, maybe from a list of things that I already wanted to write about, but occasionally, there were topics that randomly came into existence just on a certain day.</p>
</li>
<li>
<p>I think the best thing would be for me to just try and at least start writing in the morning, have some rough draft. Then, during the day, finish it. I know it about myself that it is very for me to <em>start</em> things. Once I get going, things go smoothly, the problem is usually to begin. So, yes, that would be probably the main lesson: just start writing as early as possible, and with whatever nonsense, I want. This post did not exist until I started writing it, before — head empty. Just an anxiety that I did not yet write a post today.</p>
</li>
<li>
<p>I don’t like lists with an even number of items, apparently. Though, 10 would be a nice number? I’ll need to think about this. But maybe not in this post.</p>
</li>
</ol>
<p>That’s it for today.</p>
<p>Except for one final thought outside the above list: I think writing every day did also help me to just <em>do something</em> every day as well, outside the blog. I have a few article drafts in progress, a few <em>projects</em> in progress (ooh, what are they? Hmm!), and I managed to do at least something for all of them. Which is nice.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111450552161454287">on Mastodon</a>!</p>Interop Priority Gamehttps://blog.kizu.dev/priority-game/https://blog.kizu.dev/priority-game/Today, Brian Kardell posted a question in his blog, in an entry named “Let’s Play a Game”. In the post, he asks to try to sort a list of the proposed focus and investigation areas to our liking, alongside some commentary. That’s what I’ll do!Thu, 16 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Today, <a href="https://bkardell.com/">Brian Kardell</a> posted a question in his blog, in an entry named <a href="https://bkardell.com/blog/PriorityGame.html">“Let’s Play a Game”</a>, let me quote it:</p>
<blockquote>
<p>It’s Interop 24 planning time! Let’s play a game: Tell me what you prioritize, or don’t and why?</p>
</blockquote>
<p>In the post, he asks to try to sort a list of the proposed focus and investigation areas to our liking, alongside some commentary. That’s what I’ll do!</p>
<p>There are more than 90 proposals! I can’t cover them all, and I lack expertize in many areas (sure, <a href="https://github.com/web-platform-tests/interop/issues/430">JPEG XL</a> sounds cool! I have no idea about image compression, how it compares to other formats and so on, so I cannot weight on it; if you can — go ahead!).</p>
<p>I will order things from those I need right now, needed them yesterday, and probably needed them 10 years ago, to things that would be nice to have. Likewise, I think almost all the proposals make sense and are things I’d want to see — the “game” is not trying to tell what is good or not, but to <em>prioritize</em>, after all. If I don’t mention something, that means that I don’t have enough to say about it, at least at the current moment.</p>
<h2 id="top-ten-interop-proposals-assorted-byme">Top Ten Interop Proposals, as Sorted by Me</h2>
<h3 id="1-scroll-driven-animations">1. <a href="https://github.com/web-platform-tests/interop/issues/439">Scroll-driven Animations</a></h3>
<p>I <em>am</em> biased: I wrote <a href="https://kizu.dev/tags/scroll_driven_animations/">multiple articles about them</a>, describing the weirder use cases which become possible when using scroll-driven animations.</p>
<p>As I mentioned in <a href="https://www.igalia.com/chats/power-of-css">Igalia Chats</a>, when I first saw the scroll-driven animation specs, I did not think I would write all these articles. I did not understand at the time how powerful it is to get access to the elements’ positions and dimensions in CSS in the way scroll-driven animations allows us.</p>
<p>But here we are — with them unlocking so many effects and use cases! And now that <a href="/scroll-driven-animations-in-stable-chrome/">they’re in Chrome Stable</a>, let’s prioritize shipping them <em>everywhere</em>.</p>
<p>And — in an interoperable way.</p>
<p>There is one fear I have — with so many techniques I (and others) come up with, what are the chances they would work even when other browsers would implement scroll-driven animations? There are so many moving pieces: <code>@property</code>, interactions of custom CSS properties with animations, and more.</p>
<p>But, without shipping the scroll-driven animations in the first place, we couldn’t even come closer to all these techniques, and with them in place, arguing towards interop for <code>@property</code> and custom CSS properties would be easier.</p>
<h3 id="2-css-style-container-queries-custom-properties">2. <a href="https://github.com/web-platform-tests/interop/issues/433">CSS style container queries (custom properties)</a></h3>
<p>Ugh, I still need to write a proper article about style container queries. In my first initial experiments around their workarounds I stumbled upon the <a href="https://kizu.dev/cyclic-toggles/">“cyclic toggles” technique</a>, and during <a href="https://cssday.nl/2023">“CSS Day 2023” conference</a> many speakers did mention, and did provide very real use cases for style container queries. Having them available everywhere would unlock <em>so much</em>.</p>
<p>Maybe one reason why I’m not writing this article is that it would expose so many things I’ll need <em>right now</em>, that the style container queries absence would hurt even more.</p>
<h3 id="3-unit-division-and-multiplication-for-mixed-units-of-the-same-type-within-calc">3. <a href="https://github.com/web-platform-tests/interop/issues/513">Unit division and multiplication for mixed units of the same type within <code>calc()</code></a></h3>
<p>This is such a powerful thing! Stripping a unit from length values in CSS calculations is something I wanted <em>for ages</em>. This would unlock countless use cases.</p>
<p>Today, we have only wild hacks like the <a href="https://dev.to/janeori/css-type-casting-to-numeric-tanatan2-scalars-582j"><code>tan(atan2())</code> hack</a> by <a href="https://propjockey.io/">Jane Ori</a>, or have to define our values unitless. But we really require this as a native feature, available in all browsers at the same time. It might be complicated to work around interop issues in calculations, as the current <code>atan2()</code> issues show.</p>
<h3 id="4-attr-support-extended-capabilities">4. <a href="https://github.com/web-platform-tests/interop/issues/521"><code>attr()</code> support extended capabilities</a></h3>
<p>An ability to get an HTML attribute, and use it not as a string, but as any other CSS value is something that would also unlock so many use cases!</p>
<p>Yes, it can be worked around by using custom properties, but they are much more cumbersome, especially if we’d want to just reuse the existing attributes on regular HTML tags.</p>
<p>And irregular as well: with custom elements, we can name our attributes as anything. Imagine if we could use them directly in CSS, as proper values? Instead of <code><my-component style="--foo: 10; --bar: 5"></code> we could do just <code><my-component foo="10" bar="5"></code>. In addition to just added convenience, this would remove the potential CSS variables clashes, where right now we have to namespace them, but with attributes on custom elements we won’t have this issue.</p>
<h3 id="5-css-element-function">5. <a href="https://github.com/web-platform-tests/interop/issues/442">CSS <code>element()</code> function</a></h3>
<p>I only recently <a href="/moving-to-firefox/">started using Firefox</a>, so I did not yet experiment with <code>element()</code>, but it was for sure on my radar for a while. An ability to reuse the visuals of some element on the page? Huh? This can be so powerful! And it is almost impossible to work around otherwise (except for some very specific cases where we could use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-box-reflect"><code>-webkit-box-reflect</code></a>).</p>
<h3 id="6-popover">6. <a href="https://github.com/web-platform-tests/interop/issues/423">Popover</a></h3>
<p>Ok, I need to confess: this element of the list is that high only because it’s related to <a href="https://kizu.dev/anchor-positioning-experiments/">anchor positioning</a>. Moving the Popover API forward would mean more use cases and need for anchor positioning, which is in a much earlier stage to be present in the Interop 2024, <em>but</em> I want to do everything possible to move towards it.</p>
<p>And the Popover API is cool by itself, of course. But it would be so much cooler with anchor positioning! I just can’t stop mentioning anchor positioning. Sorry. By the way, my next article on <a href="https://kizu.dev/">my main site</a> would be about them, for once, and not about scroll-driven animations! Stay tuned! That article won’t even be the last time I’ll write about anchor positioning this year, can you imagine?</p>
<h3 id="7-css-multi-column-layout-block-element-breaking">7. <a href="https://github.com/web-platform-tests/interop/issues/520">CSS Multi-Column Layout block element breaking</a></h3>
<p>I will take any improvements to multi-column layout, to be honest. One dream I have is to have <a href="https://github.com/w3c/csswg-drafts/issues/2923">Overflow In The Block Dimension For Multicol</a>. Please? Of course, handling the element breaking is something <em>required</em> for mutlicol to be viable as well. Improving interop for them, giving more developer hands for multicol layout, fragmentation, all of that, would be so good!</p>
<h3 id="8-relative-color-syntax">8. <a href="https://github.com/web-platform-tests/interop/issues/426">Relative Color Syntax</a></h3>
<p>We now have <code>color-mix()</code> which <a href="https://codepen.io/leaverou/pen/gOZZQZb?editors=1100">can cover <em>some</em> relative color syntax use cases</a> (CodePen by <a href="https://lea.verou.me/">Lea Verou</a>), but from all of them.</p>
<p>Functions like <code>fade()</code>, <code>darken()</code>, <code>lighten()</code> and so on in preprocessors are sometimes the last reason to continue using them. Being able to dynamically adjust colors, by <em>modifying</em> some components, and not just replacing them, would be invaluable, especially for design systems.</p>
<h3 id="9-text-box-trim">9. <a href="https://github.com/web-platform-tests/interop/issues/422"><code>text-box-trim</code></a></h3>
<p>And, <code>text-box-edge</code> and other related properties, of course. I’ll take anything that allows us to improve typography and aligning things around text. The <code>cap</code> unit is almost here, and while it will cover <em>some</em> use-cases (like vertical alignment of icons near text), <code>text-box-trim</code> would allow for so much more precise control over how things look in relation to text.</p>
<h3 id="10-declarative-shadow-dom">10. <a href="https://github.com/web-platform-tests/interop/issues/501">Declarative Shadow DOM</a></h3>
<p><a href="/shadows-separately/">I did briefly write recently</a> about one use case for the Declarative Shadow DOM. As with many other items in this list, I look at this issue as a part of something bigger. In this case, as a path towards <a href="https://github.com/WICG/webcomponents/issues/1009">Declarative Custom Elements</a> which would be so nice to have! But, yes, I’ll take Declarative Shadow DOM as well, especially given I now have at least one use case for it, with the <a href="https://codepen.io/kizu/pen/LYqRRMQ?editors=1100">“fully transparent” elements</a>.</p>
<h3 id="participation-award">Participation Award</h3>
<p>I could continue writing and writing, scoring and sorting the proposals, but hey, I’m doing this in my less polished blog, so I need to stop at some point! Some other notable mentions that could get into a top 15, if I’d get to write more about them:</p>
<ul>
<li><a href="https://github.com/web-platform-tests/interop/issues/437">View Transitions Level 1</a></li>
<li><a href="https://github.com/web-platform-tests/interop/issues/486">CSS box-decoration-break</a></li>
<li><a href="https://github.com/web-platform-tests/interop/issues/429">margin-trim</a></li>
<li><a href="https://github.com/web-platform-tests/interop/issues/517">CSS background-clip</a></li>
<li><a href="https://github.com/web-platform-tests/interop/issues/440">css fill/stroke</a></li>
</ul>
<p>And so many more other things. So many things I did not even mention, only from the CSS proposals, and there were even more…</p>
<h2 id="final-words">Final Words</h2>
<p>I really hope at least some of the things I did mention will get into the Interop 2024. I encourage everyone to go, read the proposals, vote for what you’ll find interesting, and provide your use cases in the issues if you have some.</p>
<p>Very often browser vendors do not know if developers really want the features, or if existing workarounds are enough, if the use cases were covered by something else, and so on.</p>
<p>I believe that by writing about what <em>you</em> care about, you move things forward, give a signal that that thing you wrote about is something you still need.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111422604740639240">on Mastodon</a>!</p>Scope Selector Nuancehttps://blog.kizu.dev/scope-selector-nuance/https://blog.kizu.dev/scope-selector-nuance/In yesterday’s “weekly” I shared a new MDN docs page for @scope — a new CSS feature currently only available in Chromium-based browsers. Looking at it made me remember one issue that I had with the @scope, which was actually intended. I imagine this might be something many people would stumble upon, so here I am, sharing it.Mon, 27 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Coffee</dd></dl><hr /><p>In <a href="/weekly-bookmarks-006/">yesterday’s “weekly”</a> I shared the new <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@scope">MDN docs page for <code>@scope</code></a> — a new CSS feature currently only available in Chromium-based browsers.</p>
<p>Looking at it made me remember one issue that I had with the <code>@scope</code>, which was actually intended. I imagine this might be something many people would stumble upon, so here I am, sharing it.</p>
<p>The issue might appear if you’d try to use a selector that would have a mention of a wrapper that exists outside the scope, like this:</p>
<p><a href="https://blog.kizu.dev/scope-selector-nuance/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@scope</span><span style="color:#E1E4E8"> (.my-scope) {</span></span>
<span class="line"><span style="color:#B392F0"> .inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> .outer</span><span style="color:#B392F0"> .inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">>Hello?</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>The <code>.inner</code> element now has the pink background — not green. It might be easy to think that it would match if you’d think of scope as of something similar to a media or container query: we really care only about the <em>target</em> element, and the <code>.inner</code> is both inside our scope, <em>and</em> inside the <code>.outer</code>, right?</p>
<p>But the issue is: scopes behave closer to native CSS nesting: anything inside would be as if it were nested inside an implicit <code>:scope</code> element!</p>
<p>Let me quote <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@scope#the_scope_pseudo-class">the corresponding section from the abovementioned MDN docs</a>:</p>
<blockquote>
<p>In the context of a <code>@scope</code> block, the <code>:scope</code> pseudo-class represents the scope root — it provides an easy way to apply styles to the scope root itself, from inside the scope.</p>
<p>In fact, <code>:scope</code> is implicitly prepended to all scoped style rules. If you want, you can explicitly prepend <code>:scope</code> or prepend the nesting selector (<code>&</code>) to get the same effect if you find these representations easier to understand.</p>
</blockquote>
<p>So what we get in the end is <code>:scope .outer .inner</code> — and, of course, we don’t have the <code>.outer</code> inside our scope! But we can easily confirm this by modifying HTML:</p>
<p><a href="https://blog.kizu.dev/scope-selector-nuance/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">>Hello!</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Now, the <code>.inner</code> element has the green background.</p>
<p>How can we fix this? There are, actually, multiple ways to do so, all using different ways we can create selectors:</p>
<p><a href="https://blog.kizu.dev/scope-selector-nuance/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner1"</span><span style="color:#E1E4E8">>With an ampersand</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner2"</span><span style="color:#E1E4E8">>With a :scope</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner3"</span><span style="color:#E1E4E8">>Using nesting</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner4"</span><span style="color:#E1E4E8">>Using :is()</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@scope</span><span style="color:#E1E4E8"> (.my-scope) {</span></span>
<span class="line"><span style="color:#B392F0"> .outer</span><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner1</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0"> .outer</span><span style="color:#B392F0"> :scope</span><span style="color:#B392F0"> .inner2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> .inner3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#79B8FF">outer</span><span style="color:#E1E4E8"> & {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#6A737D"> /* Not entirely correct */</span></span>
<span class="line"><span style="color:#B392F0"> .inner4:is</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">.outer</span><span style="color:#85E89D"> *</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The “proper” way to fix this is to just explicitly mention the scope — either by <code>&</code> or <code>:scope</code>. This way there won’t be anything implicit added, similar to how <code>&</code> works in native CSS nesting!</p>
<p>The third example is something that works because the <code>:scope</code> would be added to the topmost selector, so when the native CSS nesting would expand, it would become <code>.outer :scope .inner3</code> essentially.</p>
<p>The fourth case is interesting, and not entirely a substitute to others. While it works, it is actually <em>wider</em> than you might think: it would also include the case when the <code>.outer</code> is <em>inside</em> the <code>.my-scope</code> or even if both classes are present on the same element:</p>
<p><a href="https://blog.kizu.dev/scope-selector-nuance/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner4"</span><span style="color:#E1E4E8">>Outside</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner4"</span><span style="color:#E1E4E8">>Inside</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-scope outer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner inner4"</span><span style="color:#E1E4E8">>Mixed</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This is because of how what is inside the <code>:is()</code> does not really care about any nesting that the element already has — it just checks if the target element is also nested inside the <code>.outer</code> element.</p>
<p>While this is not a one-to-one to what we intended, knowing this behavior can be useful in other cases.</p>
<p>We cannot use CSS scopes right now, only play with them in Chromium-based browsers, but when they would become more widely available, hopefully knowing this nuance will help you.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111482671852073364">on Mastodon</a>!</p>Shadow DOM on Regular Elementshttps://blog.kizu.dev/shadows-separately/https://blog.kizu.dev/shadows-separately/For some reason, I had this misconception that Shadow DOM could not be used with regular elements, I only ever tried it with the custom ones.Thu, 02 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>For some reason, I had this misconception that Shadow DOM could not be used with regular elements, I only ever tried it with the custom ones. But — thanks to <a href="https://blog.dwac.dev/">Doug Parker</a>, <a href="https://techhub.social/@develwithoutacause/111337559322080302">who did point it out to me on Mastodon</a>, — now I know that we can actually do that.</p>
<p>I knew that custom elements (or <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Components">Web Components</a>) <em>without</em> Shadow DOM were a thing (see also a related article <a href="https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the-light-dom/">“Blinded By the Light DOM”</a> by <a href="https://meyerweb.com/">Eric Meyer</a> from yesterday), but it never occurred to me that in the same way we could attach a Shadow DOM to a web component, we could do it just for a regular element. Sometimes it is very easy to overlook simple things!</p>
<p>Curiously, if only I had read the MDN docs about <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM">“Using shadow DOM”</a> (the link Doug gave me), then I would’ve learned that.</p>
<aside>
<p>As a sidenote, my friend and ex-colleague <a href="https://pepelsbey.dev/">Vadim Makeev</a> <a href="https://mastodon.social/@pepelsbey/111335222766787213">did join MDN today as a technical writer</a>! Say congratulations to him!</p>
<p>And another sidenote to myself, I need to implement sidenotes in this blog as well, so I can add sidenotes <em>properly</em>. <strong>Sidenotes</strong>. They’re neat.</p>
</aside>
<h2 id="declarative-shadow-dom">Declarative Shadow DOM</h2>
<p>Even more, in another Mastodon post, Doug shows how the <a href="https://developer.chrome.com/articles/declarative-shadow-dom/">Declarative Shadow DOM</a> can also be used with regular elements. If only Firefox would support it! (It actually will, rather soon — they <a href="https://github.com/mozilla/standards-positions/issues/335#issuecomment-1714182997">did state that the implementation will start soon</a>! Follow <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1712140">this bugzilla ticket</a> if you’d like to track this).</p>
<h2 id="the-context">The Context</h2>
<p>Where would I want to use Shadow DOM on a regular element? The case that resulted in this post was me wishing for a particular thing in HTML. Let me quote <a href="https://front-end.social/@kizu/111336793193155739">my own mastodon post</a>:</p>
<blockquote>
<p>What if we had an #HTML attribute that would make an element “invisible” for #CSS selectors?</p>
<p>Like <code>display: contents</code>, but for DOM.</p>
<p>Like,</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"foo"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> i-am-not-here</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bar"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>And then <code>.foo > .bar</code> would actually select the inner <code>.bar</code>?</p>
<p>I can see something like this being very useful for #WebComponents, among other things, as right now it is not possible to use them as generic wrappers without impact.</p>
</blockquote>
<p>Playing with Shadow DOM and custom elements, I found two ways to achieve what I wanted.</p>
<p>Here are both CodePens:</p>
<ul>
<li><a href="https://codepen.io/kizu/pen/XWOjdWa">Custom Element Node Juggling</a></li>
<li><a href="https://codepen.io/kizu/pen/abXmNOq">Transparent Element vis Declarative Shadow DOM</a></li>
</ul>
<p>The one using a custom element is a bit weird. But it works! But I probably won’t use it in production, as it looks very fragile, requires JavaScript, and is hard to make a fallback from.</p>
<p>The second one, with the Declarative Shadow DOM, is much nicer. It is still a bit verbose — I think I would still prefer some way of doing this kind of “transparent” element just via an attribute — but it is much less weird. If only we had Firefox support… Maybe I’ll look into using <a href="https://www.npmjs.com/package/@webcomponents/template-shadowroot">a ponyfill</a> for this?</p>
<p>But what I did like is that the fallback is very gracious: the only difference outside the Shadow DOM applying is that the <code>template</code> stays in the DOM, impacting CSS selectors like <code>:nth-child()</code> etc. But any other selectors like the <code>.foo > .bar</code> from the CodePen would continue working.</p>
<h2 id="why-do-i-want-this">Why Do I Want This</h2>
<p>In short: to be able to use Web Components as something like “Higher-Order Components”, where they could provide their functionality (JS or via custom CSS properties that would get inherited into the light DOM, as seen in the example) to the nested elements, but without any impact on layout (when using <code>display: contents</code>) or selectors (the thing that I wanted it to be originally).</p>
<p>Here is <a href="https://codepen.io/kizu/pen/LYqRRMQ?editors=1100">another CodePen with a bit more expanded use case</a>, though I understand that it might still not be “practical”.</p>
<p>But hey, this is just a quick article in which I wanted to share my observation — this is a thing that I want to start doing more of. Maybe when I play with this further, I will write another post with better examples!</p>
<p>Or, maybe what I shared today would inspire you to do something interesting. Let me know!</p>
<h2 id="by-the-way">By the Way</h2>
<p>So far, I have posted for every day in November! “Is this a <a href="https://indieweb.org/National_Blog_Posting_Month">‘NaBloPoMo’</a>?” — He asks, pointing at a butterfly. We will see! I doubt I could keep it up through the whole month, but maybe? I just need to choose a tiny topic and not be a perfectionist about polishing it completely. “Just”. See you in the next post, be it tomorrow or later!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111342614119582772">on Mastodon</a>!</p>Slightly Updated Blog Designhttps://blog.kizu.dev/slightly-updated-blog-design/https://blog.kizu.dev/slightly-updated-blog-design/Sorry again for not posting the weekly links — I’m not feeling myself well, so decided to write a shorter post today. I did update this blog’s design slighly!Sun, 05 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>Sorry again for not posting the weekly links — I’m not feeling myself well, so I decided to write a shorter post today.</p>
<p>I did update this blog’s design slightly!</p>
<p>If you’re reading this post via <a href="/rss.xml/">RSS</a> — you can visit the site itself.</p>
<p>(Note to self: It would be cool to have some way to add content that is visible only in RSS.)</p>
<p>The update is very simple this time (though there have been more updates since the last time I wrote about my blog’s CSS, in <a href="/not-an-ideal-start/">the first post here</a>/): mostly colors and a few spacing ones.</p>
<p>I’m lazy enough to provide the before/after — but before what you can find now, I did not really have any colors, relying on the system’s default white&black colors for the text and background (though, customizing the link colors, as in Safari, in the dark mode, but with the <code>color-scheme: light dark; </code> the links did not change color, resulting in a bad contrast).</p>
<p>(Maybe I will add the before/after at a later point.)</p>
<p>Let me know if you spot any issues with the new design; it was very quick to implement, and I’m sure I forgot to check something.</p>
<p>I’m not sure when I could gather the next weekly links — probably when I would feel myself better. For the time being, I will probably continue posting these “simple” posts.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111359299462155744">on Mastodon</a>!</p>Observation: Snappy Scroll-Starthttps://blog.kizu.dev/snappy-scroll-start/https://blog.kizu.dev/snappy-scroll-start/Two days ago, I published my previous observation: “Range Input’s Thumb and Emerging CSS”, where I promised to share another observation later. Here it is! In it, I would share how we can work around the absence of the scroll-start property.Fri, 17 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Robert Dallas Gray — Quartal Reels</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="context">Context</h2>
<p>Two days ago, I published my previous observation: <a href="/input-range-thumb/">“Range Input’s Thumb and Emerging CSS”</a>.</p>
<p>At the end of this post, I did write:</p>
<blockquote>
<p>In the Mastodon thread about this, <a href="https://www.bram.us/">Bramus</a> did also share his solution for this, also using scroll-driven animations, but in a different way. I did share <em>another observation</em> later, but I’ll save it for a future blog post.</p>
</blockquote>
<p>Here is this blog post!</p>
<h2 id="the-problem">The Problem</h2>
<p>I’ll quote Bramus, from the end of <a href="https://front-end.social/@bramus/111414355820949700">his Mastodon message</a> that I mentioned above:</p>
<blockquote>
<p>(My demo begs for <code>scroll-start</code>, a new property to set a non-zero starting scroll position BTW)</p>
</blockquote>
<p>Two quick related links:</p>
<ul>
<li>Here is <a href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-start">a spec for <code>scroll-start</code></a>.</li>
<li>And here is <a href="https://github.com/w3c/csswg-drafts/issues/6986">the original proposal for <code>scroll-start</code></a> by <a href="https://nerdy.dev/">Adam Argyle</a>.</li>
</ul>
<p>As usual, when I see something that sounds good, I always think about how we can work around the absence of this feature <em>now</em>.</p>
<p>I remember, I did already think about this at some point, but did not really try, so no <em>old</em> CodePen to show this time. Given I was already in the mood of sharing stuff, I shared <a href="https://codepen.io/kizu/pen/gOqGBow">a modified CodePen</a> where I demonstrated my idea for a workaround.</p>
<h2 id="the-scroll-start-workaround">The <code>scroll-start</code> Workaround</h2>
<p>My thought process was: ok, we need to have a scroll to be at a certain position. Do we have something that controls the scroll position?</p>
<p><strong>Scroll Snap.</strong> (I recommend Adam’s talk about it — <a href="https://www.youtube.com/watch?v=34zcWFLCDIc">“Oh Snap!”</a>)</p>
<p>The problem: it would always apply, interfering with the scrolling.</p>
<p>Potential solution: one-time animation or a <code>@starting-style</code>? Trying the latter in Chrome, it didn’t work. Trying the former — it did! I’ve tested only in Chrome, and for the purpose of this exact demo, which already did work only in it due to the scroll-driven animations, it was enough.</p>
<p>Now, however, I’d want to see if it is possible to use this workaround in a cross-browser way.</p>
<p>Ooops. It did not work in Firefox and Safari. Why? <a href="https://caniuse.com/css-snappoints">Scroll Snap support is actually decent</a>. Debugging time!</p>
<ol>
<li>
<p>In Firefox, the issue was that in order to scroll-snap to work, I had to add the dimensions to an element with it. It had to be at least 1×1 pixel.</p>
</li>
<li>
<p>In Safari, the issue is less pleasant: for some reason, the scroll-snap does not want to work when applied from inside an animation.</p>
</li>
</ol>
<p>I’ve tried many things! The solution I found in the end was… to add container queries?</p>
<p><a href="https://codepen.io/kizu/pen/JjxMLVG">Here is the final CodePen</a></p>
<p>And here is most of the code for this CodePen:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"scroller"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--scroll-start: 10em;"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"scroll-start"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.scroller</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">10</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">10</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> scroll-snap-type</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">y</span><span style="color:#79B8FF"> mandatory</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.scroll-start</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">absolute</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--scroll-start</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: size;</span></span>
<span class="line"><span style="color:#79B8FF"> visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> animation</span><span style="color:#E1E4E8">: --snap </span><span style="color:#79B8FF">0.01</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> both</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.scroll-start::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">""</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@container</span><span style="color:#E1E4E8"> (width: 1px) {</span></span>
<span class="line"><span style="color:#B392F0"> .scroll-start::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> scroll-snap-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">start</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@keyframes</span><span style="color:#FFAB70"> --snap</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> to</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The trick was to apply the <code>scroll-snap-align</code> not from an animation directly, but conditionally through a container query, which changes based on an animation that runs once.</p>
<p>Our helper element starts with <code>1px</code> width, and at this point the <code>scroll-snap-align</code> applies.</p>
<p>The animation changes the width of the helper to <code>0px</code>, and the container query no longer matches, removing the <code>scroll-snap-align</code>.</p>
<p>That’s it! We get our <code>scroll-start</code> position, and after it applies, we can freely scroll the container.</p>
<h2 id="follow-ups">Follow-ups</h2>
<p>If this was an article on my main site, I would feel obliged to go and look up both the Firefox and Safari issues, check what the specs did mean, are there web platform tests, are there open bugs… Posting this as an observation here is liberating: I could still do it later (unless someone would get to do it first — you’re welcome, by the way), but for now, I could just share this, not postponing it until I’ll sort <em>everything</em>.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111427621257832112">on Mastodon</a>!</p>Space Variable Placeholdershttps://blog.kizu.dev/space-toggle-placeholders/https://blog.kizu.dev/space-toggle-placeholders/I already posted this week once about space toggles, but today I did use a variation of the technique, where it is not strictly space toggles, but something like space placeholders. The idea is: sometimes we want to make some properties extensible, which can be very useful for properties that do not have longhands, or for properties which can accept an unlimited number of values. CSS variables can be very helpful for coming up with your API, which allows controlling these properties in some very precise ways. In this post, I present one way how I like to do it.Sat, 25 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>I already <a href="/space-toggle-scoping/">posted this week once about space toggles</a>, but today I did use a variation of the technique, where it is not strictly space <em>toggles</em>, but something like <em>space placeholders</em>. I’m not sure if I have previously seen any specific articles about this, so I decided to write about it (if you know of other articles about this — please let me know, I’ll mention them here).</p>
<p>The idea is: sometimes we want to make some properties <em>extensible</em>, which can be very useful for properties that do not have longhands like <code>box-</code> and <code>text-shadow</code>, or for properties which can accept an unlimited number of values like the same <code>text-</code> and <code>box-shadow</code>, but also <code>content</code>, <code>background-image</code>, <code>filter</code>, <code>transform</code> (which recently got an ability to specify values separately, but it might still be useful to do this with the original property) and so on.</p>
<p>CSS variables can be very helpful for coming up with your API, which allows controlling these properties in some very precise ways.</p>
<p>Here is one way I like to do this:</p>
<p><a href="https://blog.kizu.dev/space-toggle-placeholders/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--em-shadow-top: var(--shadow-border),;"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>First pill</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"</span></span>
<span class="line"><span style="color:#9ECBFF"> --em-shadow-mid: var(--shadow-basic),;</span></span>
<span class="line"><span style="color:#9ECBFF"> "</span><span style="color:#E1E4E8">>Second pill</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"</span></span>
<span class="line"><span style="color:#9ECBFF"> --em-shadow-top: initial;</span></span>
<span class="line"><span style="color:#9ECBFF"> --em-shadow-low: var(--shadow-glow),;</span></span>
<span class="line"><span style="color:#9ECBFF"> "</span><span style="color:#E1E4E8">>Third pill</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"</span></span>
<span class="line"><span style="color:#9ECBFF"> --em-shadow-mid: var(--shadow-basic),;</span></span>
<span class="line"><span style="color:#9ECBFF"> --em-shadow-low: var(--shadow-glow),;</span></span>
<span class="line"><span style="color:#9ECBFF"> "</span><span style="color:#E1E4E8">>Fourth pill</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --shadow-border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> 0</span><span style="color:#79B8FF"> 0</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --shadow-basic</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 5</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> -2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> blue</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --shadow-glow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> 5</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> lightgreen</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example</span><span style="color:#85E89D"> em</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">#000</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#79B8FF"> box-shadow</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--em-shadow-top</span><span style="color:#E1E4E8">,)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--em-shadow-mid</span><span style="color:#E1E4E8">,)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--em-shadow-low</span><span style="color:#E1E4E8">,)</span></span>
<span class="line"><span style="color:#79B8FF"> 0</span><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>There are a few interesting things going on in there which might look weird at the first glance, but allow me to explain!</p>
<ol>
<li>
<p>In CSS, we can see the weird comma at the end of the variable name: <code>var(--em-shadow-top,)</code> — this is a valid way to define an <em>empty</em> fallback, or a <em>space</em>, often used in the space toggles.</p>
<p>I wrote a bit more extensively about this part in <a href="https://kizu.dev/cyclic-toggles/#omit-the-space">my article on cyclic toggles</a>, but in short: whenever the variable in question has its initial value (or — it is <em>not defined</em>, or it is <em>invalid at computed-value time</em>), it would result in just an empty space, which is a valid thing to have in any part of any value in CSS. This is a very compact way of saying, “we can put something here, but it is also ok to just skip it”. If we don’t use the comma, the “initial” value of the variable would make the whole property invalid, so we have to have <em>some</em> fallback here.</p>
</li>
<li>
<p>The <code>box-shadow</code> definition ends with <code>0 0</code>. If you’d look at the HTML we have, you might already guess why: we define our variables like this: <code>--em-shadow-top: var(--shadow-border),; </code> — note the comma at the end. Because CSS does not allow trailing commas in lists, and we don’t know in advance which variables we could define and in which order, we want to make sure any combination of them would work.</p>
<p>The easiest way to achieve this is by adding the comma either to our token definition (like to the <code>--shadow-border</code>), or to the places where we use the tokens (as in the example). With the <code>0 0</code> at the end of our <code>box-shadow</code>, we can be sure that if we’d add a comma for any of the values, things would still render properly. And the <code>0 0</code> is just the smallest valid shadow that does not really do anything. Other properties could have other ways of handling this, but often they would not even require this comma stuff, like for the <code>content</code> or <code>transform</code> values which are just separated by spaces.</p>
</li>
</ol>
<p>The rest should be relatively obvious: we’re using tokens so we won’t need to define their values all the time, we can define the “default” values on the ancestors (on the <code><p></code> in our case), and then override them back to nothing (see <code>--em-shadow-top: initial;</code>).</p>
<p>This is also just one of the ways something like this can be handled, and there are various other cases where we could use CSS variables in this manner. Custom properties are powerful!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111472279972218841">on Mastodon</a>!</p>Space Toggles for Scopinghttps://blog.kizu.dev/space-toggle-scoping/https://blog.kizu.dev/space-toggle-scoping/Today I did encounter a bug, for which I would really want to use CSS Scopes, or Style Container Queries. But they’re not yet available in any cross-browser way. But the bug won’t wait! Thankfully, space toggles did save the day.Wed, 22 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Peppermint tea</dd></dl><hr /><p>Today I did encounter a bug, for which I would really want to use <a href="https://drafts.csswg.org/css-cascade-6/#scoped-styles">CSS Scopes</a>, or <a href="https://drafts.csswg.org/css-contain-3/#style-container">Style Container Queries</a>. But they’re not yet available in any cross-browser way. But the bug won’t wait!</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-issue">The Issue</h2>
<p>This is a rather common issue which can resurface for very complex components. Prerequisites:</p>
<ol>
<li>A wrapper, on which we handle the modifications via toggling classes.</li>
<li>Some descendant element, which depends on these styles, with an unknown deepness of nesting inside our wrapper.</li>
<li>Ability to nest this component inside itself.</li>
</ol>
<p>Here is a simplified example:</p>
<p><a href="https://blog.kizu.dev/space-toggle-scoping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.section</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">max-content</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> box-sizing</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">border-box</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> 0</span><span style="color:#79B8FF"> 8</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.section.isPretty</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example1</span><span style="color:#B392F0"> .section.isPretty</span><span style="color:#B392F0"> .section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section isPretty"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Section Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Subsection Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some content</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>The intent of the styles above was for the <code>.section-header</code> to have the modified styles only when it is inside the <code>.isPretty</code> section. But, because the selector is selecting <em>any</em> descendant header inside, it also matches the header inside our nested section.</p>
<p>You might say: oh, but just use the child combinator! Yes, in this simplified example, <code>.section.isPretty > .section-header</code> would immediately resolve the issue.</p>
<p>However, remember when I mentioned “very complex components” and “with an unknown deepness of nesting”?</p>
<p>The child combinator is handy when we know the structure of our components. Ideally, we should. But in some cases, that might be complicated! Imagine we’d have a table inside our component, and we’d want to nest some element inside one of the cells. We would not want to write something like <code>.section > table > tbody > tr > td > .our-element</code>. Especially, if the structure could change, and the element could be present on different nesting levels, so we couldn’t even do something like <code>.section > * > * > * > * > .out-element</code>, as this won’t guarantee that we will select the proper element, or if we’d over-reach into a nested section this way.</p>
<p>Potentially, we could handle this via HTML: duplicate the modifier on every element that needs it. So, we’d have a <code>class="section-header isPretty"</code>. This means, we will have too much logic for handling HTML. This will unnecessarily overcomplicate things.</p>
<h2 id="scopes">Scopes</h2>
<p><a href="https://drafts.csswg.org/css-cascade-6/#scoped-styles">CSS Scopes</a> could help us with this!</p>
<p><a href="https://blog.kizu.dev/space-toggle-scoping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@scope</span><span style="color:#E1E4E8"> (.example2 .section.isPretty) to (.section-content) {</span></span>
<span class="line"><span style="color:#B392F0"> .section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section isPretty"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Section Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Subsection Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some content</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>(HTML for this and the following examples is the same)</p>
<p>If you’ll look at the above example in Chrome or most other Chromium-based browsers, you’ll see that it actually works! What we did is utilize the donut scoping: defining a scope boundary, beyond which the styles won’t be applied.</p>
<p>We used the <code>.section-content</code>, but there are multiple ways we could’ve solved this, like stopping the scope on the next <code>.scope</code> element, or maybe not even using the donut scoping, and relying on the “closest scope” mechanism, defining two scoped styles: for non-modified styles, and modified. I did not play with the scopes enough to properly research which method would be the best, so for now, I’ll omit them.</p>
<h2 id="style-container-queries">Style Container Queries</h2>
<p><a href="https://drafts.csswg.org/css-contain-3/#style-container">Style Queries</a> could also help us!</p>
<p><a href="https://blog.kizu.dev/space-toggle-scoping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example3</span><span style="color:#B392F0"> .section</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3</span><span style="color:#B392F0"> .section.isPretty</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@container</span><span style="color:#E1E4E8"> style(--is-pretty) {</span></span>
<span class="line"><span style="color:#B392F0"> .section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section isPretty"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Section Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Subsection Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some content</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Again, if you’ll look at this in Chrome or most other Chromium-based browsers, you’ll see that this works. Because of the way CSS variables are inherited, we can use this to scope things in a way similar to the native CSS scopes!</p>
<p>One thing I think I need to mention right away: even though those two methods look similar, we need both. In many other aspects, scopes and style container queries are very different, and this is not a place where we should choose only one over another.</p>
<p>But the issue with both methods — so far, they were only implemented in Chromium… Can we do something with what we have in every browser today?</p>
<h2 id="space-toggles">Space Toggles</h2>
<p>We can! I did come across this method when playing with the style query alternatives when going back from <a href="https://cssday.nl/2023">CSS Day 2023</a>. The actual method I discovered is <a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a>, and is a variation on regular space toggles (about <a href="https://kizu.dev/cyclic-toggles/#was-this-always-possible">the history of which</a> you can also read in my article).</p>
<p>For this post, I’ll demonstrate regular space toggles — after all, cyclic toggles are just a variation of them when we want to have more than just a binary state, and it could be applied for this as well.</p>
<p><a href="https://blog.kizu.dev/space-toggle-scoping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example4</span><span style="color:#B392F0"> .section</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: ;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example4</span><span style="color:#B392F0"> .section.isPretty</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example4</span><span style="color:#B392F0"> .section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section isPretty"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Section Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Subsection Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some content</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Yay, it now works everywhere! Of course, the usage is much more cumbersome than with scopes or style queries. And right now, when the <code>--is-pretty</code> is not defined, the corresponding properties would revert to their initial values. If we’d want to set some alternative values, we’d have to define an additional variable:</p>
<p><a href="https://blog.kizu.dev/space-toggle-scoping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example5</span><span style="color:#B392F0"> .section</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: ;</span></span>
<span class="line"><span style="color:#FFAB70"> --is-not-pretty</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example5</span><span style="color:#B392F0"> .section.isPretty</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --is-pretty</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --is-not-pretty</span><span style="color:#E1E4E8">: ;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example5</span><span style="color:#B392F0"> .section-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#79B8FF"> hotpink</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-not-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is-not-pretty</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">4</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section isPretty"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h2</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Section Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-header"</span><span style="color:#E1E4E8">>Subsection Header</</span><span style="color:#85E89D">h2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"section-content"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some content</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This method did allow me to untangle some overrides which were really difficult to work around differently without introducing some complex dynamic HTML output logic. All because of how custom properties work in CSS!</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you did not yet dig into how to use space toggles — I will highly recommend it! They can be a bit tricky to set up, but we’re using them for around a year in production, and so far, no complaints. And, as this post shows, they can be used to solve some complex cases, a proper solution for which we will only get with the more advanced solutions like scopes or style container queries.</p>
<p>But oh how I would prefer to use a more proper solution, and not a hack!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111456177546169987">on Mastodon</a>!</p>Unlayered Styles Issuehttps://blog.kizu.dev/unlayered-styles-issue/https://blog.kizu.dev/unlayered-styles-issue/I did write a lengthy comment in a surprisingly (for me) closed issue about allowing authors (and users) to explicitly place unlayered styles in the cascade layer order. I won’t reproduce the comment here, so I invite everyone to read it on GitHub and participate in the discussion, provide your use cases, and so on.Tue, 07 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>I did write a lengthy comment in a surprisingly (for me) closed issue about allowing authors (and users) to explicitly place unlayered styles in the cascade layer order. I won’t reproduce the comment here, so I invite everyone to <a href="https://github.com/w3c/csswg-drafts/issues/6323#issuecomment-1799983584">read it on GitHub</a> and participate in the discussion, provide your use cases, and so on.</p>
<p>(As a sidenote, I think I’ll continue sharing my bigger comments/issues in CSSWG as separate posts here, whenever I feel that they’re something that is more important/invites a discussion)</p>
<p>(Maybe I’ll need to add the ability to mark a post as an “external link/bookmark”? I’ll need to think about this.)</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111371229221250841">on Mastodon</a>!</p>My VS Code Monaspace Font Setuphttps://blog.kizu.dev/vs-code-monaspace-setup/https://blog.kizu.dev/vs-code-monaspace-setup/In the last “weekly” I did share a link to the “The Monaspace type system”. For a few weeks, I was trying one of its fonts in VS Code. There were a few things that did not go very smoothly, so I have decided to share them in this post.Tue, 28 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Darjeeling tea</dd></dl><hr /><p>In the last <a href="/weekly-bookmarks-006/">“weekly”</a> I did share a link to <a href="https://monaspace.githubnext.com/">“The Monaspace type system”</a>. For a few weeks, I was trying one of its fonts in VS Code. There were a few things that did not go very smoothly, so I have decided to share them in this post.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="my-configuration">My Configuration</h2>
<p>Below is what I have configured for the font in the editor and its integrated terminal.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="json"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF"> "editor.fontFamily"</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> "Monaspace Neon Var, Fira Code, Monaco, monospace"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "editor.fontSize"</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "editor.fontVariations"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"'wght' 350"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "editor.fontLigatures"</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> "'calt', 'liga', 'ss03', 'ss04', 'ss06'"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "editor.tokenColorCustomizations"</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF"> "textMateRules"</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> "scope"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"comment"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "settings"</span><span style="color:#E1E4E8">: { </span><span style="color:#79B8FF">"fontStyle"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"italic"</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> "scope"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"storage,entity,variable"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "settings"</span><span style="color:#E1E4E8">: { </span><span style="color:#79B8FF">"fontStyle"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">""</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> ]</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#79B8FF"> "terminal.integrated.fontFamily"</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> "Monaspace Neon Var, Fira Code, Monaco, monospace"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "terminal.integrated.fontSize"</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">14</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "terminal.integrated.fontWeight"</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">500</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> "terminal.integrated.fontWeightBold"</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">800</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>As you can see, I’m using the “Neon” font, and the variable font version, and also using the <a href="https://github.com/tonsky/FiraCode">“Fira Code”</a> font by <a href="https://tonsky.me/">Niki Tonsky</a> as the fallback font — this is helpful for when the terminal has the special characters set up, like the git branch symbol and so on.</p>
<h2 id="font-weight-weirdness">Font-Weight Weirdness</h2>
<p>You might notice that for the editor font, I’m setting the font-weight via <code>"editor.fontVariations": "'wght' 350"</code>, and not via <code>fontWeight</code>. For me, the <code>fontWeight</code> did result in the incorrect results for the “regular” font-weight. There is <a href="https://github.com/githubnext/monaspace/issues/1">a similar issue on GitHub</a> similar to mine.</p>
<p>But using the <code>fontVariations</code> and specifying the variable font’s value for the <code>wght</code> axis did work correctly for me. It seems that maybe the built-in instances for the font-weight were not set up properly? When uploading the font to <a href="https://wakamaifondue.com/">“Wakamai Fondue”</a> (a web service for analyzing fonts by <a href="https://pixelambacht.nl/">Roel Nieskens</a>), it does not even show if the font contains any built-in mappings for the regular font-weights. But I’m not an expert, and perhaps there is something else at play.</p>
<p>Thankfully, at least for the editor, it is possible to set up things, the integrated terminal, sadly, does not provide an ability to override the <code>fontVariations</code>.</p>
<p>As a sidenote, there is also a small issue with the minimal font width — it is a bit too wide. Would’ve been nice if it was possible to make the font narrower.</p>
<h2 id="ligatures">Ligatures</h2>
<p>At first, I did try using more than three stylistic sets I ended up using; however, some ligatures were not set up properly, breaking the caret navigation and selection (“merging” the symbols into one). Thankfully, many other ligatures seem to work fine, so I found those from <code>'ss03', 'ss04', 'ss06'</code> work well for me.</p>
<p>Basically, I did choose to keep only those ligatures that did not change how the characters displayed very drastically. Otherwise, it might be very challenging to navigate from the keyboard through the symbols when you can’t tell on which symbol you’re currently on, for example when the <code>!==</code> is converted into a wide <code>≠</code>.</p>
<p>But those ligatures where things are just looking slightly different — I, for the most part, don’t mind.</p>
<h2 id="customizing-tokens">Customizing Tokens</h2>
<p>Sadly, while the Monaspace’s promo site did show how cool it would be if we could set up entirely different fonts for different semantic entities on the page, this is not supported in VS Code (apart from using some extensions that allow for more customization). The only thing we can control via <code>editor.tokenColorCustomizations</code> is basically only if something is italic or no (and some other very minor things).</p>
<p>I did, at least, set up to use italic for all code comments, <em>except</em> for the code bits inside <a href="https://jsdoc.app/">JSDoc</a> — the <code>storage, entity, variable</code> tokens.</p>
<p>But I really wish VS Code did provide more ways to customize the fonts, including all the font features for the editor and its specific highlighted tokens, and for the integrated terminal.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu">on Mastodon</a>!</p>Weekly Bookmarks 3: IndieWebCamp Editionhttps://blog.kizu.dev/weekly-bookmarks-003/https://blog.kizu.dev/weekly-bookmarks-003/I learned a lot from IndieWebCamp and gathered a lot of links from the sessions I did participate in.Wed, 01 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Some plain water in the trains; Yunnan at home</dd><dt>Current location:</dt><dd>Started: Nuremberg → Paris; then finished at Home</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>As I shared in my <a href="/indie-web-camp-updates/">previous post about the things I did during IndieWebCamp</a>, I did not have enough time to compile a list of bookmarks for the last week. I have some, but I was mostly paying attention to what was happening at the conference and the IndieWeb event. I’ll include these links in the next weekly bookmarks.</p>
<p>However, IndieWebCamp, especially the sessions during the first day, was full of information, which I tried to distill into a list of links that I found interesting.</p>
<h2 id="building-block-icons">Building Block Icons</h2>
<p>I participated in <a href="https://indieweb.org/2023/Nuremberg/block-icons">a session about having an imagery for the indie web “building blocks”</a>, initiated by <a href="https://paulrobertlloyd.com">Paul Robert Lloyd</a>, in which we discussed if there should be a cohesive design language for various IndieWeb thingies.</p>
<ul>
<li><a href="https://paulrobertlloyd.com/2023/298/a1/indieweb_identity/">“A cohesive and unified identity for IndieWeb protocols”</a> by Paul — the original post that did initiate the discussion, where he proposes a starting point for a cohesive design language for the IndieWeb.
<ul>
<li><a href="https://www.theverge.com/2023/10/23/23928550/posse-posting-activitypub-standard-twitter-tumblr-mastodon">“The poster’s guide to the internet of the future”</a> by <a href="https://www.theverge.com/authors/david-pierce">David Pierce</a> — an article mentioned in the post.</li>
<li>He also links to a lot of pages for various IndieWeb and related technologies, visit his post to get them! (Seriously, there are <em>many</em> interesting links in his post, I am myself planning to read a lot of them later.) I think both this post and the Verge article could be considered a good introduction to the IndieWeb.</li>
</ul>
</li>
<li><a href="https://indieweb.org/posts#Types_of_Posts">“Types of Posts”</a> — a section of the “posts” page of the IndieWeb wiki that tries to gather and categorize different types of content that might be present on personal websites.</li>
<li><a href="https://indieweb.org/Building_block_icons">“Building block icons”</a> — a wiki page created by Paul after the session.
<ul>
<li><a href="https://indieweb.org/Category:Branding">“Category:Branding”</a> — a wiki category page with some other interesting linked pages.</li>
</ul>
</li>
</ul>
<p>Overall, I really like the Paul’s proposal, especially how the icons for specific microformats look.</p>
<h2 id="link-rot">Link Rot</h2>
<p>I participated in <a href="https://indieweb.org/2023/Nuremberg/linkrot">a session about the “link rot”</a>, initiated by <a href="https://adactio.com/">Jeremy Keith</a>, in which we did discuss various ways to check, fix or work around the broken links that could exist in various personal blog archives.</p>
<p>I’m gathering the links to things mentioned in the session and outside of it into one list, providing some of my commentary:</p>
<ul>
<li><a href="https://remysharp.com/2023/09/26/no-more-404">“No more 404”</a> by <a href="https://remysharp.com/">Remy Sharp</a> — the original article that did initiate the discussion.</li>
<li><a href="https://web.archive.org/">“The Wayback Machine”</a> by <a href="https://archive.org">Internet Archive</a> — the best way to get the content of a link that did disappear.</li>
<li><a href="https://www.jeremycherfas.net/blog/stop-the-linkrot">“Stop the Linkrot”</a> by <a href="https://www.jeremycherfas.net/">Jeremy Cherfas</a> — a short post about the session we had, and how Jeremy did fix problems he had with inbound links via <code>.htaccess</code>.
<ul>
<li><a href="https://ahrefs.com/broken-link-checker">“Broken Link Checker”</a> — mentioned by <a href="https://www.jeremycherfas.net/">Jeremy</a>. I found six broken links with it (it reported 7, but one of them was one I already fixed previously, so it seems to cache these in some way).</li>
</ul>
</li>
<li><a href="https://sebastiangreger.net/2023/10/link-rot-and-schrodingers-url">“Link-rot and Schrödinger’s URL”</a> by <a href="https://sebastiangreger.net/">Sebastian Greger</a> — a post about the session we had, where he looks at how he could approach this issue on his site (he uses Kirby CMS and PHP).
<ul>
<li><a href="https://linkchecker.github.io/linkchecker/">“LinkChecker”</a> — a free GPL website validator (requires Python 3.8 or later) mentioned by Sebastian in his post.</li>
<li>He also mentions a bunch of other links to various APIs he is using, if you’re interested, visit his post!</li>
</ul>
</li>
<li><a href="https://micro.blog/">Micro.blog</a> — a blogging service that, as a part of its premium plan, includes achieving the bookmarks. <a href="https://www.youtube.com/watch?v=1uevgQYsR9g">A YouTube video about this feature</a>.</li>
<li><a href="https://www.hanselman.com/blog/410-gone-thoughts-on-mark-diveintomark-pilgrims-and-whys-infosuicides">“410 Gone - Thoughts on Mark ‘diveintomark’ Pilgrim’s and _why’s infosuicides”</a> by <a href="https://www.hanselman.com/">Scott Hanselman</a> — a post about the <code>410 gone</code> HTTP status that we briefly discussed during the session.</li>
<li><a href="https://chriscoyier.net/2023/11/01/0-kb-social-media-embeds/">“0 KB Social Media Embeds”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a short post about how it is a viable way to just “embed” any short-form posts as blockquotes, and thus both have a snapshot of the content in time and no chance it would disappear. We did mention this type of embed during the session, but, of course, it is only viable for anything short enough to not be annoying.</li>
</ul>
<p>Overall, this is a very interesting and multi-faceted topic. I’ve started thinking about how <em>I</em> would want to implement something that helps with this on my site, and also about whether this is something that could be facilitated by the web browsers and/or browser extensions. It should be easy enough to do the “did we land on 404? Let’s look in the Internet Archive” as a feature, though this won’t work for the “zombies”.</p>
<h2 id="how-tostop-rewriting-your-site-and-write-more">How to stop rewriting your site and write more</h2>
<p>I participated in <a href="https://indieweb.org/2023/Nuremberg/write">a session about actually writing in your blogs</a>, initiated by <a href="https://sarajaksa.eu/">Sara Jakša</a>, where we did discuss what is stopping us from writing in our blogs, be it perfectionism or something else.</p>
<ul>
<li><a href="https://indieweb.org/2023/Nuremberg/write#After_session_Additional_Notes">“After session Additional Notes”</a> by Sara — after the session, she did write down the summary and some ideas of what we were talking during the session, sharing some nice links as well.</li>
<li><a href="https://en.wikipedia.org/wiki/Extended_mind_thesis">“Extended mind thesis”</a> shared in these notes is something I’ve already been doing for years, though not publicly: putting every idea into some notes, removing them from my head, and “freeing” some space for new ideas.</li>
<li><a href="https://indieweb.org/digital_garden">“digital garden”</a> article stub over at IndieWeb wiki — a concept that I encounter more and more, though maybe not the one I’ll use for publishing my thoughts publicly. I’m using Obsidian for my notes now, and it is less like a garden and more like overgrown ruins. However, I think this might be a neat concept for gathering information about some topic, learning and so on.</li>
<li>There were some other thoughts and links in these additional notes; I highly recommend reading them, especially if you struggle with finding what to write in your blog or with the writing process in general.</li>
</ul>
<p>If I took one thing from this session, it was that I needed to worry less about how things would be received and try to fight my perfectionism, at least in some ways.</p>
<h2 id="other-sessions">Other Sessions</h2>
<p>I was also present at two other sessions: <a href="https://indieweb.org/2023/Nuremberg/a11y">“Accessible web”</a> by <a href="https://calumryan.com/">Calum Ryan</a> and <a href="https://indieweb.org/2023/Nuremberg/posse">“POSSE How To & Best Practices + Fediverse”</a> by <a href="https://tantek.com/">Tantek Çelik</a>, but I don’t think I want to add any links here, as I’m less familiar with these particular topics, and would need to read much more on them in order to share something reasonable.</p>
<p>The “Accessible web” session was more of a free-form discussion without any specific topic; the <a href="https://indieweb.org/POSSE">“POSSE”</a> is a concept that I’m not entirely sold on yet, though I really liked how <a href="https://fed.brid.gy/">“Bridgy Fed”</a> sounds like — a way to easily connect Mastodon with your IndieWeb-powered website.</p>
<p>I’ll keep an eye on the various IndieWeb concepts in the future, so it is likely my other weekly bookmarks will get more links from this area as well.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111337446980831129">on Mastodon</a>!</p>Weekly Bookmarks 4: CSS Editionhttps://blog.kizu.dev/weekly-bookmarks-004/https://blog.kizu.dev/weekly-bookmarks-004/On one hand, I did miss two weeks of this “weekly” series. On the other, I did post every day from the start of the month. With the backlog through all these past weeks, I have maybe too much on my plate. So, this time, I’m only posting links related to CSS, as well as a quick list of everything I did write in this blog since the last weekly.Sun, 12 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Neavh — Knothole</dd><dt>Current drink:</dt><dd>Yunnan</dd></dl><hr /><p>On one hand, I did miss two weeks of this “weekly” series. On the other, I <em>did</em> post every day from the start of the month.</p>
<p>With the backlog through all these past weeks (<a href="/weekly-bookmarks-003/">last “weekly”</a> had only IndieWeb bookmarks, so the <a href="/weekly-bookmarks-002/">last time I actually posted regular ones</a> was on October 22), I have maybe too much on my plate.</p>
<p>So, this time, I’m only posting links related to CSS, as well as a quick list of everything I did write in this blog since the last weekly. That means that the next weekly would have some more non-CSS links to share!</p>
<h2 id="css-techniques-articles-and-news">CSS Techniques, Articles, and News</h2>
<ul>
<li>
<p><a href="https://brm.us/css-scroll-detection">“Solved by CSS Scroll-Driven Animations: Style an element based on the active Scroll Direction and Scroll Speed”</a> by <a href="https://www.bram.us/">Bramus</a> — a <em>very</em> wild hack around scroll-driven animations, utilizing the inheritance of values set by animations from a parent to children, <em>with transitions</em>, allowing to detect the velocity and direction of the scrolling.</p>
</li>
<li>
<p><a href="https://jamesbasoo.com/blog/scroll-driven-pixel-art-sprite/">“Control Pixel Art Sprites With CSS Scroll-Driven Animations”</a> by <a href="https://jamesbasoo.com/">James Basso</a> — a nice application of the above technique, used to adjust the direction of the sprites based on the scroll direction.</p>
</li>
<li>
<p><a href="https://ashleemboyer.com/blog/why-you-should-use-px-units-for-margin-padding-and-other-spacing-techniques">“Why You Should Use <code>px</code> Units for <code>margin</code>, <code>padding</code>, & Other Spacing Techniques”</a> by <a href="https://ashleemboyer.com/">Ashlee M Boyer</a> — an article comparing the relative and absolute units when applied to spacing. I, personally, was convinced to start doing this, but, as a rule of thumb, only for the inline direction. Block direction is trickier, in my opinion, and not as important. But real testing is the thing everyone should do to check which units to apply in their cases.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/use-cases-for-display-contents">“Some use cases for <code>display: contents</code>”</a> by <a href="https://www.mayank.co/">Mayank</a> — a nice look at the <code>contents</code> value of the <code>display</code> property. Applying it to custom elements is one thing I was thinking for a while about. And while I don’t think we’d get something like the “Light DOM slots” through CSS in the way they suggest, there is a chance we’d get <a href="https://github.com/w3c/csswg-drafts/issues/2406">a <code>::contents</code> pseudo-element</a> one day. I wanted to compile a list of my use cases for it and post it to this issue, maybe I will find time to do this finally.</p>
</li>
<li>
<p><a href="https://www.nicchan.me/blog/view-transitions-and-stacking-context/">“View transitions and stacking context: Why does my CSS View Transition ignore z-index?”</a> by <a href="https://www.nicchan.me/">Nic</a> — an interesting exploration of some view transitions’ nuances. I’ve yet to seriously try them, so it is nice to already have people looking into them and gathering workarounds to the potentially common issues.</p>
</li>
<li>
<p><a href="https://keithjgrant.com/posts/2023/11/problematic-color-gradients-and-workarounds/">“Workarounds for buggy gradients”</a> by <a href="https://keithjgrant.com/">Keith J. Grant</a> — the new color spaces in CSS are cool, but there are still numerous issues in various browsers in how they’re applied and interpolated. This article provides a workaround to some of such issues. It is also a nice example of how writing about the issues you encounter, as well as your workarounds, can help everyone — <a href="https://nerdy.dev/">Adam Argyle</a> <a href="https://front-end.social/@argyleink/111382710954484131">did use this article as something to motivate the engineers to look into this issue</a>.</p>
</li>
<li>
<p><a href="https://www.learnwithjason.dev/blog/oklch-better-color-css-browser">“OKLCH for better color in the browser”</a> by <a href="https://jason.energy/">Jason Lengstorf</a> — a brief look at the <code>OKLCH</code> color space, with some examples and helpful links to some resources related to it.</p>
</li>
<li>
<p><a href="https://simevidas.github.io/css-prefs/">“What are my CSS user preferences?”</a> by <a href="https://%C5%A1ime.eu/">Šime Vidas</a> — a tiny test page that can help in understanding which of the CSS-detectable user preferences are currently applied in your browser.</p>
</li>
<li>
<p><a href="https://groups.google.com/a/mozilla.org/g/dev-platform/c/oacuvZ2_hLg/m/4o28pFLkAwAJ">“Intent to Ship: <code>:has</code> Selector”</a> by Mozilla — finally! I’m delighted that the <code>:has()</code> pseudo-class is already available in Firefox Nightly, as <a href="/moving-to-firefox/">now that I moved to it</a>, I can use my CSS overrides. <a href="https://nicolaschevobbe.com/">Nicolas Chevobbe</a> did also <a href="https://front-end.social/@[email protected]/111330044743627218">share on Mastodon</a> that they would also provide some nice touches in the Firefox DevTools, warning about the performance impact of the unconstrained <code>:has()</code> selectors.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/4770#issuecomment-1802342332">“RESOLVED: The CSSWG supports this CG’s efforts in defining levels for CSS as a way for the community to understand batches of CSS features”</a> in the issue by <a href="https://jensimmons.com/">Jen Simmons</a> — nice to see attempts to make CSS more “marketable”. I’m not entirely sure that the numeric naming is the best approach there, but it is good that there is at least some movement.</p>
</li>
</ul>
<h2 id="my-blog-posts">My Blog Posts</h2>
<p><a href="/weekly-bookmarks-003/">My previous “weekly”</a> was on the November 1st, and I did post every day since… And I did skip all the weekly posts afterward. So, here is everything I wrote in this blog after the previous weekly!</p>
<ul>
<li><a href="/shadows-separately/">“Shadow DOM on Regular Elements”</a></li>
<li><a href="/my-first-web-platform-tests/">“My First Web Platform Tests”</a></li>
<li><a href="/personal-site-anniversary/">“Personal Site Anniversary & History”</a></li>
<li><a href="/slightly-updated-blog-design/">“Slightly Updated Blog Design”</a></li>
<li><a href="/first-fediversary/">“My First ‘Fediversary’”</a></li>
<li><a href="/unlayered-styles-issue/">“Unlayered Styles Issue”</a></li>
<li><a href="/moving-to-firefox/">“Moving to Firefox”</a></li>
<li><a href="/layer-overrides-update/">“Layer Overrides Update”</a></li>
<li><a href="/never-use-overflow-scroll/">“Never Use ‘Scroll’ Value for Overflow”</a></li>
<li><a href="/calc-indent/">“Calculation Indentation”</a></li>
<li><a href="/calc-indent/">“Calculation Indentation”</a></li>
</ul>
<p>If you did miss any of these — given them a go! Unlike the articles over at <a href="https://kizu.dev/">my main website</a>, these are much shorter, haha.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu">on Mastodon</a>!</p>Weekly Bookmarks 5: CSS and Web Componentshttps://blog.kizu.dev/weekly-bookmarks-005/https://blog.kizu.dev/weekly-bookmarks-005/I did not have an opportunity to compile all the bookmarks I had for all the topics, so here is what I have decided to do: I’ll _try_ to post at least CSS-related stuff in every weekly. But, as long as I have a backlog of various things, I’ll group them by topic, and will add a section with things only related to this topic. This should allow me to go through the backlog without straining myself. Maybe.Sun, 19 Nov 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Helen Bell — Come Down and See</dd><dt>Current drink:</dt><dd>Gazpacho</dd></dl><hr /><p>I did not have to compile all the bookmarks I had for all the topics, so here is what I have decided to do: I’ll <em>try</em> to post at least CSS-related stuff in every weekly, but as long as I have a backlog of various things, I’ll group them by topic, and will add a section with things only related to this topic. This should allow me to go through the backlog without straining myself. Maybe.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="css-articles-and-news">CSS Articles and News</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/blog/getting-started-with-css-container-queries/">“Getting started with CSS container queries”</a> by <a href="https://michellebarker.co.uk/">Michelle Barker</a> — a nice introductory article about container queries.</li>
<li><a href="https://ishadeed.com/article/css-nesting">“CSS Nesting”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — an article about native CSS nesting with many helpful examples. Ahmad also wrote a <a href="https://ishadeed.com/article/css-nesting-ux">CSS Nesting UX in DevTools</a> article where he shares his idea on how the browser DevTools can improve their CSS nesting support.</li>
<li><a href="https://www.lenesaile.com/en/blog/about-subgrid-and-colored-grid-lines/">“About subgrid and colored grid lines”</a> by <a href="https://www.lenesaile.com/">Lene Saile</a> — an article about using CSS grids, subgrids, and some workarounds for displaying grid lines.</li>
<li><a href="https://www.youtube.com/watch?v=z8AuhLf2uxQ">“Weird Things You Missed About CSS”</a> by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — the recording of a CSS Café talk which I announced in my <a href="/weekly-bookmarks-002/">second weekly</a>, but I couldn’t attend at the time due to incredibly slow Wi-Fi on the train.</li>
<li><a href="https://bkardell.com/blog/PriorityGame.html">“Let’s Play a Game”</a> by <a href="https://bkardell.com/">Brian Kardell</a> — a post about the Interop 2024 proposals, with a proposal to read them and sort them. Or at least some of them. I did this, and shared in a <a href="/priority-game/">“Interop Priority Game”</a> post.</li>
<li><a href="https://dutchcelt.nl/posts/20-years-ago-i-had-an-idea/">“20 years ago, I had an idea”</a> by <a href="https://dutchcelt.nl/">Egor Kloos</a> — a post about creating a CSSZenGarden theme 20 years ago and reflecting on some coding decisions made at the time compared to now.</li>
<li><a href="https://www.igalia.com/chats/power-of-css">“Igalia Chats: The Power of CSS”</a>
— I was a guest on a podcast, where I chatted with <a href="https://bkardell.com/">Brian Kardell</a> and <a href="https://meyerweb.com/">Eric Meyer</a> about some CSS stuff. You can listen to it if you’d like. Or read it — the transcript is available as well.</li>
</ul>
<h2 id="web-components-and-shadow-dom">Web Components and Shadow DOM</h2>
<p>In the last few weeks, there were <em>many</em> articles about web components, custom elements and shadow & light DOMs. I won’t link to <em>all of them</em>, as that would be too much, but to a snippet of them, in chronological order. Most of these articles would have links to other related recent posts — highly recommend!</p>
<ul>
<li><a href="https://jakelazaroff.com/words/web-components-will-outlive-your-javascript-framework/">“Web Components Will Outlive Your JavaScript Framework”</a> by <a href="https://jakelazaroff.com/">Jake Lazaroff</a> — an article about how using native web components can make the code more resilient (given we won’t use any framework code inside of them).</li>
<li><a href="https://meyerweb.com/eric/thoughts/2023/11/01/blinded-by-the-light-dom/">“Blinded By the Light DOM”</a> by <a href="https://meyerweb.com/">Eric Meyer</a> — an article about how we don’t have to use Shadow DOM to use Web Components, and can just rely on light DOM, <em>progressively enhancing</em> our regular HTML. The next day after this article, I published what can be called an inverse article: <a href="/shadows-separately/">“Shadow DOM on Regular Elements”</a> — how we can do the opposite and not use custom elements, but still use shadow DOM.</li>
<li><a href="https://www.mayank.co/blog/presentational-shadow-dom/">“Presentational shadow DOM”</a> by <a href="https://www.mayank.co/">Mayank</a> — an article about how shadow DOM makes it harder to use the cascade, where they propose some hypothetical ways to improve this.</li>
<li><a href="https://adactio.com/journal/20618">“HTML web components”</a> by <a href="https://adactio.com/">Jeremy Keith</a> — an article that coins the term, and links to numerous other articles (a lot of them are not in my list).</li>
<li><a href="https://www.oddbird.net/2023/11/17/components/">“HTML Web Components are Just JavaScript?”</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> — an article exploring some aspects of web components, as well as a very curious idea of a <code>register-element</code> web component to register other web components. I really hope at one point we will get the <a href="https://github.com/WICG/webcomponents/issues/1009">Declarative Custom Elements</a>, but I really like an idea to use another web component to do this today!</li>
</ul>
<h2 id="my-blog-posts">My Blog Posts</h2>
<p>Between the <a href="/weekly-bookmarks-004/">last “weekly”</a> and this one were six days, so this section has six links today:</p>
<ul>
<li><a href="/clamp-to-infinity/">“Observation: Clamp to Infinity”</a></li>
<li><a href="/astro-mdx-components/">“Astro MDX Components”</a></li>
<li><a href="/input-range-thumb/">“Observation: Range Input’s Thumb and Emerging CSS”</a></li>
<li><a href="/priority-game/">“Interop Priority Game”</a></li>
<li><a href="/snappy-scroll-start/">“Observation: Snappy Scroll-Start”</a></li>
<li><a href="/dashed-idents-for-everything/">“Dashed Idents for Everything”</a></li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111439275359423651">on Mastodon</a>!</p>Weekly Bookmarks 6: CSS, Typography and Designhttps://blog.kizu.dev/weekly-bookmarks-006/https://blog.kizu.dev/weekly-bookmarks-006/There was not a lot of stuff this week on the CSS part, probably due to the Thanksgiving and all of that. But still something! Furthermore, continuing the “tradition” of including one more topic apart from CSS in my weekly, this time it contains some typography and design links.Sun, 26 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Carbonated water with fruit juice</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="css-articles-and-news">CSS Articles and News</h2>
<p>There was not a lot of stuff this week on the CSS part, probably due to the Thanksgiving and all of that. But still something!</p>
<ul>
<li><a href="https://www.joshwcomeau.com/css/interactive-guide-to-grid/">“An Interactive Guide to CSS Grid”</a> by <a href="https://www.joshwcomeau.com/">Josh W. Comeau</a> — I always loved the way Josh explains things, and even though I did not have an opportunity to go through his new guide completely, what I saw has all the usual good bits: interactive examples and good examples.</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@scope">“<code>@scope</code> MDN docs”</a> by <a href="https://millsdocs.com/">Chris Mills</a> — comprehensive docs about CSS scopes, talking about its various features and nuances.</li>
<li><a href="https://www.stefanjudis.com/today-i-learned/oklch-perceived-lightness/">“<code>oklch()</code> retains perceived lightness for different hue angles”</a> by <a href="https://www.stefanjudis.com/">Stefan Judis</a> — a little exploration of how OKLCH handles the change in hue, with a nice interactive demo.</li>
<li><a href="https://css-irl.info/scroll-timeline-parallax-effect/">“Scroll Timeline Parallax Effect”</a> by <a href="https://michellebarker.co.uk/">Michelle Barker</a> — a small experiment that demonstrates how we can use scroll-driven animations to achieve the parallax effect in CSS.</li>
</ul>
<h2 id="typograhy-and-design">Typograhy and Design</h2>
<p>Continuing the “tradition” of including one more topic apart from CSS in my weekly, this time it contains some typography and design links.</p>
<ul>
<li><a href="https://lea.verou.me/blog/2023/minimalist-affordances/">“Minimalist Affordances: Making the right tradeoffs”</a> by <a href="https://lea.verou.me/">Lea Verou</a> — an article about the usability of the new GitHub comment UI, where they did try to move the focus outline around the whole comment block, including other interactive elements inside. I think they might’ve gone back on this decision since? Nevertheless, the post is a pleasant read anyway, exploring the ways things become conventions.</li>
<li><a href="https://monaspace.githubnext.com/">“The Monaspace type system”</a> by <a href="https://github.com/githubnext/monaspace#contributors">Lettermatic and GitHub Next</a> — a new “monospaced type superfamily”. It uses an interesting and novel technique of “texture healing”, where the contextual alternates are used to adjust the position and form of the characters in a monospace context. The adjustment of the form is what differentiates it from the regular kerning. I first heard about the <a href="https://lettermatic.com/">Lettermatic</a> studio from their work on <a href="https://pentiment.obsidian.net/">Pentiment game</a> by <a href="https://www.obsidian.net/">Obsidian Entertainment</a>, where they did also do a lot of innovative work with the fonts. I can highly recommend both reading <a href="https://lettermatic.com/custom/pentiment">their case study about this</a> and the game itself.</li>
<li><a href="https://heather-buchel.com/blog/2023/10/why-your-web-design-sucks/">“It’s 2023, here is why your web design sucks”</a> by <a href="https://heather-buchel.com/">Heather Buchel</a> — an evocative article about how the profession of “web designer” dissolved in the industry. My experience was slightly different, but there were still enough similarities, and it is always fascinating to look at how things evolved differently in other places.</li>
<li><a href="https://practicaltypography.com/">“Practical Typography”</a> by <a href="https://matthewbutterick.com/">Matthew Butterick</a> — an online book (free, but payment is encouraged) about typography. It was recommended to me in <a href="https://front-end.social/@kizu/111471970521106424">a Mastodon thread where I asked for some typography book recommendations</a>, and going through a few sections of it, there are things to like.</li>
<li><a href="https://nevermore.rip/">“The Nevermore: The Collected Works of
Edgar Allan Poe”</a> by <a href="https://joshuamauldin.com/">Joshua
Mauldin</a> — a good example of applying typography to the web in practice. Maybe one day I’ll actually read some of it!</li>
</ul>
<h2 id="my-blog-posts">My Blog Posts</h2>
<p>Between the <a href="/weekly-bookmarks-005/">last “weekly”</a> and this one were six days, so this section has six links today (yes, this is the same paragraph text as in the previous weekly; probably for the last time, as next week the November ends, and with it my venture into posting every day):</p>
<ul>
<li><a href="/custom-ident-mdn/">“Fixing the Custom Ident Docs”</a></li>
<li><a href="/posting-on-a-schedule/">“Posting on a Schedule”</a></li>
<li><a href="/space-toggle-scoping/">“Space Toggles for Scoping”</a></li>
<li><a href="/calc-fr-unit/">“Calculated Fractions (Report the Bugs!)”</a></li>
<li><a href="/extra-nesting-specificity/">“Extra Nesting Specificity”</a></li>
<li><a href="/space-toggle-placeholders/">“Space Variable Placeholders”</a></li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111478905334858586">on Mastodon</a>!</p>CSS Scope Issueshttps://blog.kizu.dev/css-scope-issues/https://blog.kizu.dev/css-scope-issues/A week ago, a “CSS `@scope`” article by Miriam Suzanne was published at “12 Days of Web” (curated by Stephanie Eckles). This article did clarify a few things for me, but also made me think of one potential usage of the `:scope` pseudo-class: “storing” the scoping root’s selector as a reusable entity, covering the use case which is available in some of the CSS preprocessors. However, when exploring this use case, I stumbled upon a few issues: this post is about them.Thu, 21 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Mice Parade — Two, Three, Fall</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>A week ago, a <a href="https://12daysofweb.dev/2023/css-scope/">“CSS <code>@scope</code>”</a> article by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> was published at <a href="https://12daysofweb.dev/">“12 Days of Web”</a> (curated by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a>).</p>
<p>This article did clarify a few things for me, but also made me think of one potential usage of the <code>:scope</code> pseudo-class: “storing” the scoping root’s selector as a reusable entity, covering the use case which is available in some CSS preprocessors: <a href="https://sass-lang.com/documentation/at-rules/at-root/"><code>@at-root</code> in Sass</a> and <a href="https://stylus-lang.com/docs/selectors.html#root-reference">root reference in Stylus</a>. We don’t have anything like this with native CSS nesting, so the possibility to use scopes in this way seemed like a really neat feature.</p>
<p>However, when exploring this use case, I stumbled upon a few issues, one of which was the way Chromium implemented the <code>:scope</code> inside the <code>:is()</code>. I did open a PR to <a href="https://github.com/web-platform-tests/wpt/pull/43697">Web Platform Tests</a> adding a test for this.</p>
<p>It is from <a href="https://github.com/web-platform-tests/wpt/pull/43697#issuecomment-1864175647">a comment in this PR</a> by <a href="https://blog.matthieud.me/about/">Matthieu Dubet</a> that I first heard about the <a href="https://github.com/WebKit/WebKit/pull/21435"><code>@scope</code> becoming stable in WebKit</a>!</p>
<p>Of course, I couldn’t help myself from going and exploring how the <code>@scope</code> works in Safari Technology Preview.</p>
<p>Some things that I did found were nice (my use case with <code>:is(:scope *)</code> did work, unlike in Chromium!), but also some things did not work as I expected. However, my expectations for these are based more on the current Chromium implementation, rather than the specs — I think a lot of these are in the “gray area”, not yet exlicitly defined in the specs (or explained there in a not the most obvious way, allowing room for an implementation difference between Chromium and WebKit right now).</p>
<p>Some more explorations and thinking later, I did open four issues in CSSWG. I will not copy what I did write there here, but will invite you to read them yourself, and participate in case you’ll have something to contribute! Here they are:</p>
<ul>
<li><a href="https://github.com/w3c/csswg-drafts/issues/9739">[css-cascade-6] <code>:scope</code> scoping root node clarification</a></li>
<li><a href="https://github.com/w3c/csswg-drafts/issues/9740">[css-cascade-6] <code>&</code> matching inside the <code>@scope</code>, and its interaction with <code>:scope</code></a></li>
<li><a href="https://github.com/w3c/csswg-drafts/issues/9741">[css-cascade-6] clarification of <code>:scope</code> matching in nested scopes</a></li>
<li><a href="https://github.com/w3c/csswg-drafts/issues/9742">[css-cascade-6] Named scopes proposal</a></li>
</ul>
<p>I hope these issues will be clarified in one way or another, allowing me to be more sure when writing the follow-up WPT tests for the <code>@scope</code> issues I discovered.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111619097212807346">on Mastodon</a>!</p>My LiveJournal Anniversaryhttps://blog.kizu.dev/lj-20-years/https://blog.kizu.dev/lj-20-years/Twenty years ago, I created an account on LiveJournal. As I did write in my “Personal Site Anniversary & History” post, plenty of things did bloom from this. Highly likely, without LiveJournal I won’t be here as a web developer. Without it, I won’t be as good with CSS.Tue, 12 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — Eastern Glow</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><p>Twenty years ago, I created an account on LiveJournal. As I did write in my <a href="/personal-site-anniversary/">“Personal Site Anniversary & History”</a> post, plenty of things did bloom from this. Highly likely, without LiveJournal I won’t be here as a web developer. Without it, I won’t be as good with CSS.</p>
<p>From the start, LiveJournal had an ability to add custom overrides for your journal. In the <a href="https://www.livejournal.com/support/faq/250.html">“S1” system</a>, you were able to add custom HTML snippets into a few places of the page, which, thanks to absolute positioning, unlocked almost unlimited styling possibilities. In the <a href="https://www.livejournal.com/support/faq/7.html">“S2” system</a> that ability to add custom HTML was absent (unless you did pay and get an ability to do much more complicated things with S2), but there were built-in themes which were done without using tables for layouts! All CSS! And that made it possible to override them much easier.</p>
<p>Maybe one day I’ll go through my archives, and try to gather all the styles I wrote for my and my friends’ journals. It was fun, and I did learn so much, even though, occasionally, there were very wild hacks that we had to use to achieve various effects.</p>
<hr>
<p>In 2009, I joined the company that bought LiveJournal as a front-end developer. <a href="https://pepelsbey.dev/">Vadim Makeev</a>, who is now working as a technical writer in MDN, was the person who hired me.</p>
<p>Eventually, social networks overshadowed LiveJournal, but I still treasure the memories I made when I was using it, and working on it.</p>
<p>Social networks, with all their convenience, were not the same outlet for creativity as LiveJournal. No ability to provide custom <em>anything</em> outside a few pictures here and there, and <em>maybe</em> a color scheme.</p>
<p>I hope, one day, there’ll be something that could fit the same niche as LiveJournal, where regular users could experiment with CSS freely. Some IndieWeb and Fediverse progress could make this possible, though it is less on the protocols, and more on the authors of software like Mastodon to provide all the tools we, as users, could need to unleash our creativity.</p>
<p>Imagine having a custom CSS field for your Mastodon profile?</p>
<p>With the recent advancements in CSS like <a href="https://drafts.csswg.org/css-cascade-5/#layering">custom cascade layers</a> and <a href="https://drafts.csswg.org/css-cascade-6/#scoped-styles">scopes</a>, with more strict ways of handling style encapsulation via <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM">Shadow DOM</a>, especially with the <a href="https://developer.chrome.com/docs/css-ui/declarative-shadow-dom">Declarative Shadow DOM</a> in the future, alongside some other tools, an implementation of custom styles fields was never as close and as effortless. Maybe, one day…</p>
<p>Finally, as a present for myself, and as a way to bring something back from the times I was using LiveJournal (there were so many things that are yet to be back in the modern social networks and blogging platforms!), I’ve decided to do one thing: bring back the “current” fields to my blog. You might’ve noticed them at the top of this page!</p>
<p>For some time, I was adding some metadata alongside a lot of the posts here, and now is a good time to just start showing them on every page. I’ve done it via adding a <code><dl></code> at the top of each page — not sure if that’s the best tag for the job, but I’m open to suggestions! As with almost anything else in this blog, this is a place that could benefit from improvements.</p>
<p>I’m not using my journal anymore, and there is no point to linking to it, but 20 years, huh.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu">on Mastodon</a>!</p>My year in CSShttps://blog.kizu.dev/my-2023-in-css/https://blog.kizu.dev/my-2023-in-css/2023 was very productive for me in terms of experimenting with CSS and writing about it. I guess, escaping from reality by submerging yourself into your special interest can have positive results occasionally. Today, I will list everything I published about CSS this year, and write a bit of context about some of it.Sun, 31 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>tricot — Laststep (Acoustic)</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>2023 was very productive for me in terms of experimenting with CSS and writing about it. I guess, escaping from reality by submerging yourself into your special interest can have positive results occasionally.</p>
<p>Today, I will list almost everything I published about CSS this year, and write a bit of context about some of it.</p>
<ul>
<li>
<p><a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a></p>
<p><em>March 15.</em> Exploring anchor positioning was the thing that started it all. I began experimenting with it as soon as I saw its first prototypes in Chrome Canary, and spent a few months working on this article, coming up with examples, thinking about which issues to open in CSSWG, and so on.</p>
</li>
<li>
<p><a href="https://kizu.dev/scroll-driven-animations/">“Future CSS: Wishes Granted by Scroll-driven Animations”</a></p>
<p><em>May 30.</em> Another thing that I started experimenting with — scroll-driven animations. Curiously, I did not initially think that I write anything about them. I don’t really do promo sites these days, and, at first glance, this feature seemed like it was only useful for various long scrollable pages with elements flying everywhere. How was I mistaken! Scroll-driven animations ended up being powerful: allowing us to query elements’ positions and dimensions.</p>
</li>
<li>
<p><a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a></p>
<p><em>June 14.</em> Going back from <a href="https://cssday.nl/2023">CSS Day</a> on a train, I was playing with some workarounds for the container style queries when I stumbled upon what ended up being this technique. I think it is very neat!</p>
</li>
<li>
<p><a href="https://kizu.dev/fit-to-width-text/">“Fit-to-Width Text”</a></p>
<p><em>June 21.</em> I think my brain was on fire after CSS Day. Thinking <em>a lot</em> about scroll-driven animations, one day I just woke up with this idea — and wrote a post in one day. Based on the engagement in Mastodon (the only way I can track things now that I have removed any analytics from my website), it is the most popular thing I came up with this year. I have something in the works related to it, so stay tuned!</p>
</li>
<li>
<p><a href="https://kizu.dev/position-driven-styles/">“Position-Driven Styles”</a></p>
<p><em>June 28.</em> A continuation of my experiments with scroll-driven animations, exploring the whole <em>position</em> aspect of them. Many things I did explore in this article I consider foundational, and I’m planning to write at least one other similarly foundational article about a similar concept.</p>
</li>
<li>
<p><a href="https://kizu.dev/scroll-driven-state-transfer/">“Scroll-Driven State Transfer”</a></p>
<p><em>October 16.</em> Yet another article about scroll-driven animations, this time about a smaller technique. A bit more hacky than some other things I did explore, but still rather useful as a concept (and as a thing that can be applied to other similar cases like anchor positioning in the future).</p>
</li>
<li>
<p><a href="https://kizu.dev/shrinkwrap-problem/">“The Shrinkwrap Problem: Possible Future Solutions”</a></p>
<p><em>December 7.</em> My second article about anchor positioning — about how it works with inline elements. This article was maybe a bit too long in the works — among many other drafts of various experiments. The technique from this article solves an issue that is impossible to solve otherwise. Which is neat, but also makes it harder to wait for the anchor positioning.</p>
</li>
<li>
<p><a href="https://www.igalia.com/chats/power-of-css">“Igalia Chats: The Power of CSS”</a></p>
<p><em>November 13.</em> <a href="https://bkardell.com/">Brian Kardell</a> and <a href="https://meyerweb.com/">Eric Meyer</a> invited me to chat with them. My first podcast in English, I was very nervous! But I always enjoy talking about CSS and was happy that there are others I can share my love with.</p>
</li>
<li>
<p><a href="https://12daysofweb.dev/2023/anchor-positioning/">“Anchor Positioning”</a></p>
<p><em>December 14.</em> <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> did accept my submission for her <a href="https://12daysofweb.dev/">“12 Days of Web”</a> advent calendar. It was a challenging topic — due to anchor positioning specs not even being finalized yet, I had to think about how I wanted to approach an “overview” article like that. I hope the result was ok! This was also the first time I wrote for anywhere besides my website, I think.</p>
</li>
<li>
<p><a href="https://www.css.cafe/a-peek-into-the-css-lab/">“A Peek Into the CSS Lab”</a></p>
<p><em>December 14.</em> Yes, on the same day! I was invited by <a href="https://schepp.dev/">Christian Schaefer</a> to give a small talk, and I chose to show some of my older experiments and some of my not yet finished ones. As it goes, I did mention many other resources during this talk — I’m still gathering the links to them, and I’m planning to post a list of them in the following weeks.</p>
</li>
</ul>
<hr>
<p>I did omit all the posts from this blog, but you can see them all by visiting <a href="/tags/css">“CSS” tag page</a>. Maybe you missed some of these posts!</p>
<p>Other than blog posts and articles, I created numerous issues in various browser bug trackers, participated in CSSWG discussions (and was invited by <a href="https://fantasai.inkedblade.net/">Elika J. Etemad</a> to virtually attend a session dedicated to anchor positioning at TPAC), and submitted a number of my first Web Platform Tests.</p>
<p>I think it could be cool to list all of these here as well, but it is <em>a lot</em>! Maybe one day I will gather all of my external contributions, like from the above list, and link to them in one way or another.</p>
<p>I want to thank everyone who spoke with me in Mastodon, be it about CSS or not. Many people did invite me to do one thing or another, which is not something I’m used to, and I’m truly thankful.</p>
<p>I don’t know what the next year will bring, and the only thing I wish for everyone is peace and love. See you in 2024.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111677012997392045">on Mastodon</a>!</p>A Christmas Tree Selector: Prototyping the :nth-sibling() with CSS Nestinghttps://blog.kizu.dev/nth-sibling-christmas-tree/https://blog.kizu.dev/nth-sibling-christmas-tree/While working on another article, I stumbled upon a case that I never could achieve in any good way: an ability to select repeating groups of elements. Native CSS Nesting could help us, and we could even optimize it a bit, but I am arguing that we still require something like `:nth-sibling()` in CSS.Mon, 25 Dec 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>While working on another article, I stumbled upon a case that I never could achieve in any good way: an ability to select repeating groups of elements.</p>
<p>We have <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child"><code>:nth-child()</code></a>, but it only allows us to select one specific element, and while we can do things like <a href="https://alistapart.com/article/quantity-queries-for-css/">“Quantity Queries”</a> (article by <a href="https://heydonworks.com/">Heydon Pickering</a>), <code>:nth-child()</code> really allows us to only select a finite group of elements, or repeating sequences of a single selected element.</p>
<p>What I want is: to be able to select groups like A-A-A-B-B-B-A-A-A-B-B-B and so on. I’m not alone in wanting something like that: there is <a href="https://github.com/w3c/csswg-drafts/issues/3813">a CSSWG issue</a> with comments from <a href="https://github.com/AmeliaBR">Amelia Bellamy-Royds</a> and <a href="https://johannesodland.github.io/">Johannes Odland</a> thinking about a hypothetical <code>:nth-sibling()</code> pseudo-class that could allow us to achieve it.</p>
<p>But right now — we don’t have a good way to do this. However, I did spend some time trying to come up with something that could be used for prototyping it instead.</p>
<h2 id="a-list-of-nth-child-pseudo-classes">A List of <code>:nth-child()</code> Pseudo-Classes</h2>
<p>If we were to express the above A-A-A-B-B-B-… grouping with the <code>:nth-child()</code>, we will have to repeat it for every element of the group:</p>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">6</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">6</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">6</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">3</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<style>{`
.example ol {
font-size: 0.75em;
max-height: 50vh;
overflow: auto;
}
`}</style>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>It is a bit cumbersome, but it works:</p>
<ol>
<li>First, we need to determine the periodicity — at which point does our pattern repeat? In the above case, every sixth element is the same, so we’re using the <code>6n</code> inside the <code>:nth-child()</code>.</li>
<li>Then, as we want to select the first three elements of every group, we have to repeat the selector for every <code>+1</code>, <code>+2</code>, and <code>+3</code>. And if we wish to invert the logic and select the elements from the fourth to the sixth, we could just use <code>+4</code>, <code>+5</code> and <code>+6</code>.</li>
</ol>
<p>As you can guess, if we would like to have a group of ten selected elements, we would have to repeat ourselves ten times! Which is far from ideal. This is where we can introduce <a href="https://drafts.csswg.org/css-nesting-1/">native CSS Nesting</a>.</p>
<h2 id="a-christmas-tree-selector">A Christmas Tree Selector</h2>
<p>We can omit a bit of repetition if instead of using a separate <code>:nth-child()</code> we will use only one of them, but then use a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator">next-sibling combinator</a>:</p>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">6</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> & + *,</span></span>
<span class="line"><span style="color:#E1E4E8"> & + * + * {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>Two important notes:</p>
<ol>
<li>
<p>This is likely to be more performance-expensive than a regular <code>:nth-child()</code>. While performance of selectors is usually very fast these days, <code>:nth-child()</code> and sibling selectors can be potentially harmful for large DOM trees, especially when the nodes are added and removed dynamically.</p>
</li>
<li>
<p>This makes sense only with native CSS nesting: when using preprocessors, just using the repeated <code>:nth-child()</code> should be more performant (this is only speculation; actual testing should be done).</p>
</li>
</ol>
<p>Why did I call this a “Christmas Tree” selector? Let’s say we will want to select the abovementioned group of 10 elements and format our code a bit differently:</p>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">20</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*+*+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*+*+*+*+*+*</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>Yeah. Not super practical, but, in my opinion, better than a list of repeated <code>:nth-child()</code> where we have to adjust every number if we want to adjust how it is applied!</p>
<p>And it looks neat.</p>
<p>Maybe you could even spot <a href="https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/">an owl</a> hidden somewhere between the branches of this tree!</p>
<h2 id="further-optimizations">Further Optimizations</h2>
<p>When thinking about this, I thought of one optimization that we could do to reduce the number of lines of code (but not the complexity, really): combine both methods:</p>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example4</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">20</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">20</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">6</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+*</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>If the count of elements in our group is not a prime number, we can express our desired “group” as a product of two or more nested selectors! In the above case, we can use just two <code>:nth-child()</code> and a smaller Christmas tree to achieve our group of ten, as 2×5=10.</p>
<p>And if we can have our group as a product of more than two numbers, things can be simplified even more, like for selecting twelve elements it can be expressed as 2×3×2:</p>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example5</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">24</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> li</span><span style="color:#E1E4E8">:nth-child(</span><span style="color:#79B8FF">24</span><span style="color:#E1E4E8">n+</span><span style="color:#79B8FF">7</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*+*+*+* {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> &+*</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>Now we have just two happy little trees.</p>
<h2 id="the-need-for-nth-sibling">The Need for <code>:nth-sibling()</code></h2>
<p>As demonstrated by the above cases, even though we can try to optimize the selectors, they’re still a bit too complicated. I won’t use them in production, and won’t recommend doing so as well.</p>
<p>With all the goodness that we got recently in CSS, including things like CSS Scopes, CSS Nesting, <code>:nth-child(… of …)</code>, and so on, an ability to easily select these groups of selectors seems like a big missing piece.</p>
<p>Over the years, I did come upon many cases when I wanted to have something like that. If you did as well — I urge you to post them to the <a href="https://github.com/w3c/csswg-drafts/issues/3813">abovementioned CSSWG issue</a> and share your thoughts about the existing proposals and their syntax — will it apply to your cases? Is there still something missing?</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111641766725599410">on Mastodon</a>!</p>Weekly Bookmarks 7: CSS and HTMLhttps://blog.kizu.dev/weekly-bookmarks-007/https://blog.kizu.dev/weekly-bookmarks-007/Today’s “weekly” is a short one! Mostly about CSS and HTML, no bonus topics this time.Sun, 03 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Huge Shark — One Day (single version)</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>Today’s “weekly” is a short one! Mostly about CSS and HTML, no bonus topics this time.</p>
<ul>
<li><a href="https://www.htmhell.dev/adventcalendar/">“HTMHell Advent Calendar 2023”</a>, curated by <a href="https://www.matuzo.at/">Manuel Matuzović</a> — a collection of articles by different authors. I highly recommend checking them out and subscribing to <a href="https://www.htmhell.dev/feed_advent.xml">its RSS</a>. I won’t include all the articles here in my weekly, even though all of them would be worthy — the joy of such calendars is the joy of not knowing what is inside, and I won’t steal it from you. Sorry, article authors, for not mentioning you!</li>
<li><a href="https://adrianroselli.com/2023/12/web-development-advent-calendars-for-2023.html">“Web Development Advent Calendars for 2023”</a> by <a href="https://adrianroselli.com/">Adrian Roselli</a> — a round-up of many advent calendars related to web development. I did not find many things that I could relate to, but I encourage you to check the list out — maybe you’ll find something up to your liking!</li>
<li><a href="https://ericwbailey.website/published/i-restyled-my-mastodon-instance/">“I restyled my Mastodon instance”</a> by <a href="https://ericwbailey.website/">Eric Bailey</a> — a post, showing how using BEM classes (instead of some generative or abbreviated mess) and an ability to add custom styles in an admin UI allowed Eric to modify the styles for his Mastodon instance.</li>
<li><a href="https://scottjehl.com/posts/using-responsive-video/">“How to Use Responsive HTML Video (…and Audio!)”</a> by <a href="https://scottjehl.com/">Scott Jehl</a> — an article about how support for responsive audio and video returned to Chrome and Firefox, allowing us to adjust the sources based on various media features.</li>
<li><a href="https://www.sarahgebauer.com/post/day-2-drop-a-cap/">“Drop a cap?”</a> by <a href="https://www.sarahgebauer.com/">Sarah Gebauer</a> — a short blog post about using <code>initial-letter</code> in CSS, which mentions a few of the current cross-browser issues with it. In my practice, there are maybe <em>too many</em> interop issues with both <code>initial-letter</code> itself, and the <code>:first-letter</code> in general — I’ll need to find time to finish my research on this.</li>
<li><a href="https://codepen.io/daviddarnes/pen/JjxmLpb?editors=0100">“Revealing ‘back to top’ button”</a> by <a href="https://darn.es/">David Darnes</a> — a CodePen with a simple way to achieve a “back to top” button’s effect. While it is simple, it relies on the link having an <code>inline</code> display, which, interestingly, makes the margin to affect the sticky behavior, while not applying the margin in the layout itself. Quite a curious interaction in CSS.</li>
</ul>
<h2 id="myblog-posts">My Blog Posts</h2>
<p>With the November ending, I did stop writing one post per day. Still, last week included the last four days of that productive month, so here are my last four posts from it:</p>
<ul>
<li><a href="/scope-selector-nuance/">“Scope Selector Nuance”</a></li>
<li><a href="/vs-code-monaspace-setup/">“My VS Code Monaspace Font Setup”</a></li>
<li><a href="/color-mix-current-color/">“Observation: color-mix and currentColor”</a></li>
<li><a href="/one-month-of-writing/">“One Month of Writing”</a></li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111518616832699955">on Mastodon</a>!</p>Weekly Bookmarks 8: Mostly CSShttps://blog.kizu.dev/weekly-bookmarks-008/https://blog.kizu.dev/weekly-bookmarks-008/I did not have a lot of time to read stuff outside my CSS comfort zone this week, so, once again, mostly CSS-related links. Also: a small announcement about my experiments!Sun, 10 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Delta Sleep — Camp Adventure</dd><dt>Current drink:</dt><dd>White tea with litchi, pineapple, mango, and papaya</dd></dl><hr /><p>I did not have a lot of time to read stuff outside my CSS comfort zone this week, so, once again, mostly CSS-related links.</p>
<h2 id="my-experiments">My Experiments</h2>
<ul>
<li>
<p><a href="https://kizu.dev/shrinkwrap-problem/">“The Shrinkwrap Problem: Possible Future Solutions”</a> — last Thursday I published a new larger article.</p>
<p>Anchor positioning, once again, solving one of the hardest CSS problems! Not for all the cases, but enough that when we will finally get it in all browsers, this will be a really useful technique.</p>
</li>
<li>
<p><a href="https://www.meetup.com/css-cafe/events/297788668/">“A Peek Into the CSS Lab”</a> — next Thursday I’ll talk about some of my experiments at <a href="https://www.meetup.com/css-cafe/">CSS Café</a>.</p>
<p>6:00 PM CET, online, free. Everyone is welcome!</p>
</li>
</ul>
<h2 id="css-articles-and-news">CSS Articles and News</h2>
<ul>
<li>
<p><a href="https://developer.mozilla.org/en-US/blog/baseline-evolution-on-mdn/">“Baseline’s evolution on MDN”</a> by <a href="https://pepelsbey.dev/">Vadim Makeev</a> — a short article about the changes in the Baseline and how it will be displayed on MDN pages.</p>
</li>
<li>
<p><a href="https://web.dev/blog/baseline-definition-update">“A definition update for Baseline”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a>, <a href="https://github.com/atopal">Kadir Topal</a>, and <a href="https://bandarra.me/">André Cipriani Bandarra</a> — a similar post about the Baseline update by the Google team.</p>
</li>
<li>
<p><a href="https://developer.chrome.com/blog/css-wrapped-2023">“CSS Wrapped: 2023!”</a> by <a href="https://una.im/">Una Kravets</a>, <a href="https://www.bram.us/">Bramus</a>, and <a href="https://nerdy.dev/">Adam Argyle</a> — an extensive overview of many new features in CSS that Chrome did ship this year. Plenty of nice demos!</p>
</li>
<li>
<p><a href="https://adrianroselli.com/2023/12/media-queries-in-html-video.html">“Media Queries in HTML Video”</a> by <a href="https://adrianroselli.com/">Adrian Roselli</a> — a good exploration of various ways we could now use the <code><video></code> element that adapts to various media features.</p>
</li>
<li>
<p><a href="https://www.tonymottaz.com/blog/oh-no-my-json/">“Oh no! My JSON!”</a> by <a href="https://www.tonymottaz.com/">Tony Mottaz</a> — a short post, reminding that not all small “progressive enhancement”-like features like <code>hanging-punctuation</code> should be applied to <em>everything</em>. Similar to <code>text-wrap: balance</code>, it is better to scope it to places you will sure need it.</p>
</li>
<li>
<p><a href="https://meyerweb.com/eric/thoughts/2023/12/06/three-decades-of-html/">“Three Decades of HTML”</a> by <a href="https://meyerweb.com/">Eric Meyer</a> — a short post about how Eric wrote his first HTML document. I really like these kinds of posts: I did write a similar post around a month ago — <a href="/personal-site-anniversary/">“Personal Site Anniversary & History”</a>.</p>
</li>
<li>
<p><a href="https://12daysofweb.dev/">“12 Days of Web”</a> curated by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — starting from the next Wednesday, for twelve days, there will be one new article about the web platform posted every day. For now, if you’re wondering what there was in the previous years, I recommend to check out the archives: <a href="https://12daysofweb.dev/2022/">2022</a> and <a href="https://12daysofweb.dev/2021/">2021</a>.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111558402384499139">on Mastodon</a>!</p>Weekly Bookmarks 9: CSS (as Usual)https://blog.kizu.dev/weekly-bookmarks-009/https://blog.kizu.dev/weekly-bookmarks-009/I’m a bit tired after this week — I did speak about some of my CSS experiments at CSS Café on Thursday (later there’ll be a recording), so there are not as many links today, and, as usual, mostly only about CSS.Sun, 17 Dec 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>Some Baldur’s Gate 3 battle music</dd><dt>Current drink:</dt><dd>Mulled wine from an alcohol-free Cabernet Sauvignon</dd></dl><hr /><p>I’m a bit tired after this week — I did speak about some of my CSS experiments at <a href="https://www.meetup.com/css-cafe/">CSS Café</a> on Thursday (later there’ll be a recording), so there are not as many links today, and, as usual, mostly only about CSS.</p>
<ul>
<li>
<p><a href="https://12daysofweb.dev/">“12 Days of Web”</a> curated by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — I did already share a link to it in <a href="/weekly-bookmarks-008/">the previous “weekly”</a>, but now there are already a few articles to check out! I highly recommend you to check them out and follow the new ones every day. I’ll list the ones from this week inside the <code><details></code>, as a way not to spoil the topics for you.</p>
<details>
<summary><u>This week’s 12 Days of Web’s articles (5 links<span class="nou"><span>)</span></span></u></summary>
<ul>
<li><a href="https://12daysofweb.dev/2023/popover-api/">“Popover API”</a> by <a href="https://www.ryantrimble.com/">Ryan Trimble</a> — an introduction to the Popover API.</li>
<li><a href="https://12daysofweb.dev/2023/anchor-positioning/">“Anchor Positioning”</a> article by me! Coincidentally, it was published on the same day I did the CSS Café talk.</li>
<li><a href="https://12daysofweb.dev/2023/css-scope/">“CSS <code>@scope</code>”</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> — a post that lead to me finding <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1512217">an issue in the current Chromium’s <code>@scope</code> implementation</a>, and me opening <a href="https://github.com/web-platform-tests/wpt/pull/43697">a PR to WPT for the case I found</a>.</li>
<li><a href="https://12daysofweb.dev/2023/web-components/">“Web Components”</a> by <a href="https://www.mayank.co/">Mayank</a> — an introduction to web components. Next year, I predict, will be <em>a lot</em> about them. There’ll be a lot more talk about them!</li>
<li><a href="https://12daysofweb.dev/2023/animation-composition/">“CSS animation-composition”</a> by <a href="https://tylergaw.com/blog/">Tyler Gaw</a> — an introduction to the <code>animation-composition</code> property. It is a very curious feature, which allows us to do some things not really possible otherwise. See also <a href="https://mastodon.social/@Schepp/111594924223577906">a follow-up Mastodon thread</a> started by <a href="https://schepp.dev/">Christian Schaefer</a>, with participation by <a href="https://css-articles.com/">Temani Afif</a> and me, about the way the <code>accumulate</code> is calculated for the <code>scale()</code> transform.</li>
</ul>
</details>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2023/12/css-scroll-snapping-aligned-global-page-layout-case-study/">“CSS Scroll Snapping Aligned With Global Page Layout: A Full-Width Slider Case Study”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — an article about how we can use CSS variables and calculations to snap elements inside a slider that escapes the container to align the items inside with the content.</p>
</li>
<li>
<p><a href="https://flackr.github.io/web-demos/carousel/">“Carousel example”</a> by <a href="https://github.com/flackr">Robert Flack</a> — a prototype for the <a href="https://css.oddbird.net/overflow/explainer/">“CSS Overflow Extensions Explainer”</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a>, Robert, and <a href="https://www.stubbornella.org/">Nicole Sullivan</a>. It is an exploration of several interesting features that could help with creating sliders like in the above article. One of the explored parts of the proposal involving fragmentation is something I find very intriguing — I’m always for any advancements around fragmentation.</p>
</li>
<li>
<p><a href="https://shkspr.mobi/blog/2023/12/using-date-based-css-to-make-old-web-pages-look-old/">“Using date-based CSS to make old web pages <em>look</em> old”</a> by <a href="https://shkspr.mobi/">Terence Eden</a> — an article about how we could use a rarely used type of attribute selector for hyphen-separated values, as well as the <code>:has()</code> pseudo-class to style pages based on their publication date, targetting the <code><time></code>’s <code>datetime</code> attribute.</p>
</li>
<li>
<p><a href="https://knowler.dev/blog/a-mental-model-for-styling-the-shadow-dom">“A Mental Model for Styling the Shadow DOM”</a> by <a href="https://knowler.dev/">Nathan Knowler</a> — an article about one way we can think about the Shadow DOM styles, using the cascade for its purpose.</p>
</li>
</ul>
<hr>
<p>This week did also include an anniversary of my account on LiveJournal, and I wrote a short post about this: <a href="/lj-20-years/">“My LiveJournal Anniversary”</a>.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111598064109318942">on Mastodon</a>!</p>Weekly Bookmarks 10https://blog.kizu.dev/weekly-bookmarks-010/https://blog.kizu.dev/weekly-bookmarks-010/It is the last week for many advent calendars. I did not have an opportunity to follow most of them — this is why I did post links from only one of them, but I will catch up in the following weeks! Regardless, there were some good articles about CSS outside of advent calendars as well.Sun, 24 Dec 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>It is the last week for many advent calendars. I did not have an opportunity to follow most of them — this is why I did post links from only one of them, but I will catch up in the following weeks! Regardless, there were some good articles about CSS outside of advent calendars as well.</p>
<ul>
<li>
<p><a href="https://12daysofweb.dev/">“12 Days of Web”</a> curated by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — now with all articles. As previously, I will put the related links inside the <code><details></code>, as a way not to spoil the topics for you.</p>
<details>
<summary><u>This week’s 12 Days of Web’s articles (5 links<span class="nou"><span>)</span></span></u></summary>
<ul>
<li><a href="https://12daysofweb.dev/2023/view-transitions/">“View Transitions”</a> by <a href="https://chenhuijing.com/">Chen Hui Jing</a> — an introduction to view transitions. I’ve yet to properly play with them, as I’m mostly waiting for them to be available for regular page transitions. And when I did try them, I found out that they’re something that you have to design in-advance, and it might not be a good idea to try and apply them to existing web-sites without putting any thought into it.</li>
<li><a href="https://12daysofweb.dev/2023/css-nesting/">“CSS Nesting”</a> by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a> — a round-up of various aspects of native CSS nesting. It feels so good to finally use it after years of preprocessors!</li>
<li><a href="https://12daysofweb.dev/2023/css-scroll-driven-animations/">“Scroll-driven Animations”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — an introduction to some of the common use cases for the scroll-driven animations, showcasing some simple but festive examples. I did already write <a href="https://kizu.dev/tags/scroll_driven_animations/">4 articles about them</a>, and not planning to stop — though I tend to explore the less common use cases.</li>
<li><a href="https://12daysofweb.dev/2023/responsive-svgs/">“Responsive SVGs”</a> by <a href="https://ichimnetz.com/">Nils Binder</a> — a nice exploration of how we can make the SVGs responsive. There are many interesting details, some of which I had to stumble myself when doing my examples involving SVG in my <a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a> article (specifically, for the <a href="https://kizu.dev/anchor-positioning-experiments/#Toggle-anchor-positioning-2-6">last example of the “Four Quadrants”</a> section, and for the example in the <a href="https://kizu.dev/anchor-positioning-experiments/#using-the-connections">“Using the Connections”</a>).</li>
<li><a href="https://12daysofweb.dev/2023/container-style-queries/">“Container Style Queries”</a> by <a href="https://matuzo.at/">Manuel Matuzović</a> — an introduction to the style queries. During this year’s <a href="https://cssday.nl/2023">CSS Day</a> many speakers did mention style queries as something that could solve one or another problem. We need more articles about them! And we need them in all browsers as well, the sooner — the better.</li>
</ul>
<hr>
<p>Note: I did not list two posts about JS; if you’re interested in them — look for them on the website for yourself!</p>
</details>
</li>
<li>
<p><a href="https://brm.us/accumulate-scale">“The mysterious case of using CSS <code>animation-composition: accumulate</code> on a <code>scale</code> transform”</a> by <a href="https://www.bram.us/">Bramus</a> — an explanation of one curious detail from one of the last week’s “12 Days of Web” articles.</p>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2023/12/new-css-viewport-units-not-solve-classic-scrollbar-problem/">“New CSS Viewport Units Do Not Solve The Classic Scrollbar Problem”</a> by <a href="https://%C5%A1ime.eu/">Šime Vidas</a> — a deep dive into viewport units, their interactions with classic scrollbars, some other related contexts, and how we can work with them.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/css-for-js-state">“CSS-based state management”</a> by <a href="https://www.mayank.co/">Mayank</a> — an exploration of how CSS custom properties can be used to store state, utilizing the way inheritance works in CSS.</p>
</li>
<li>
<p><a href="https://developer.mozilla.org/en-US/blog/border-images-interop-2023/">“Border images in CSS: A key focus area for Interop 2023”</a> by <a href="https://github.com/dipikabh/">Dipika Bhattacharya</a> — an MDN article about <code>border-image</code>. As the title of the article says — this property was one of the focus areas for this year, and browsers did a lot of progress on fixing interop issues with it. This is still a rather challenging property to work with, but this article does a good job of talking through its fundamentals.</p>
</li>
<li>
<p><a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/YSc-ri5O32I/m/fvjllNgVAAAJ">“Intent to Prototype: CSS <code>calc-size()</code> function”</a> by <a href="https://dbaron.org/">David Baron</a>. Can’t wait to play with it! An ability to have a transition between unknown <code>width</code> or <code>height</code> is literally <a href="https://github.com/w3c/csswg-drafts/issues/626#issuecomment-1800254442">the most reacted to issues</a> in CSSWG repo. For now, there is only a <a href="https://chriscoyier.net/2022/12/21/things-css-could-still-use-heading-into-2023/#animate-to-auto">CSS Grids trick</a> from <a href="https://chriscoyier.net/">Chris Coyier</a>, but having this available natively will be wonderful.</p>
</li>
<li>
<p><a href="https://www.mozilla.org/en-US/firefox/121.0/releasenotes/">Firefox 121.0 Release Notes</a> — among others, I want to note two notable CSS-related features: addition of <code>text-wrap: balance</code>, and, more importantly — <code>:has()</code> selector, which is now available in all stable versions of major browsers! Maybe not yet a time to put it into production, but a time to start learning about it. There are many articles about it already (someone should make a round-up!), and at least two were written specifically due to the release:</p>
<ul>
<li>
<p><a href="https://www.sarahgebauer.com/post/day-19-can-i-has-stuff/">“Can I <code>:has</code> stuff?”</a> by <a href="https://www.sarahgebauer.com/">Sarah Gebauer</a> — in which she explores the basics of it.</p>
</li>
<li>
<p><a href="https://robbowen.digital/wrote-about/locking-scroll-with-has/">“Locking scroll with <code>:has()</code>”</a> by <a href="https://robbowen.digital/">Robb Owen</a> — in which he looks at one of its possible use cases: detecting when we need to “lock” the scrollbar based on some condition (I can already think of using it with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:popover-open"><code>:popover-open</code></a> from the <a href="https://open-ui.org/components/popover.research.explainer/">Popover API</a>)</p>
</li>
</ul>
</li>
<li>
<p><a href="https://webkit.org/blog/14885/release-notes-for-safari-technology-preview-185/">Safari Technology Preview 185 Release Notes</a> — again, I want to focus on just two points: <code>align-content</code> in normal flow (which was already present in Chrome Canary, and now we could test it in Safari TP thanks to <a href="https://github.com/WebKit/WebKit/pull/21522">a contribution</a> by <a href="https://fantasai.inkedblade.net/">Elika J. Etemad</a>), and a relatively stable implementation of <code>@scope</code>! Here are two related articles from this week:</p>
<ul>
<li>
<p><a href="https://css-irl.info/how-do-you-vertically-centre-an-element-in-css/">“How Do You Vertically Centre an Element in CSS? (Even More) Easily!”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — an overview of this new possibility.</p>
</li>
<li>
<p><a href="https://blog.kizu.dev/css-scope-issues/">“CSS Scope Issues”</a> by me — a post and links to four CSSWG issues I created after testing the <code>@scope</code> in Safari.</p>
</li>
</ul>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111637657102290264">on Mastodon</a>!</p>Cap-Height Vertical Alignhttps://blog.kizu.dev/cap-height-align/https://blog.kizu.dev/cap-height-align/The new year is here, and, with it, a season where people put out their CSS wishlists for the future. I did already read two of them: December’s CSS wishlist from Sarah Gebauer, and today’s “Tyler’s CSS Wish List for 2024” from Tyler Sticka. One thing caught my attention in Tyler’s list: an ability to vertically align to the middle of the font’s cap-height. I am thrilled to report that there are at least two relatively ok workarounds available in the most recent browsers, courtesy of the new `cap` unit!Wed, 03 Jan 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Ichiko Aoba — Sagu Palm’s Song</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>The new year is here, and, with it, a season where people put out their CSS wishlists for the future.
I did already read two of them: December’s <a href="https://www.sarahgebauer.com/post/day-25-css-wishlist/">CSS wishlist</a> from <a href="https://www.sarahgebauer.com/">Sarah Gebauer</a>, and today’s <a href="https://cloudfour.com/thinks/tylers-css-wish-list-for-2024/">“Tyler’s CSS Wish List for 2024”</a> from <a href="https://tylersticka.com/">Tyler Sticka</a>.</p>
<p>One thing I <em>love</em> to do when I see these wishlists is to think of all the ways we can do the things from them already. It is always a good challenge, and quite often can result in some wild experiments.</p>
<p>There are other things that I’d want to experiment on later, but one thing caught my attention in Tyler’s list: an ability to <a href="https://github.com/w3c/csswg-drafts/issues/4707">vertically align to the middle of the font’s cap-height</a>.</p>
<p>This is something I did research in the past, and I am thrilled to report that there are at least two relatively ok workarounds available in the most recent browsers, courtesy of the new <a href="https://drafts.csswg.org/css-values/#cap"><code>cap</code></a> unit!</p>
<aside class="warning">
In [“Baseline”](https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility) terms, we can treat `cap` as “Newly Available”, with Safari 17.2 being the last major browser to implement it in December (see the [full browser compatibility table for it on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/length#browser_compatibility)).
<p>While we must be careful when using it in production, we can do it with <a href="#the-fallbacks">relatively simple fallbacks</a>.</p>
</aside>
<h2 id="two-techniques">Two Techniques</h2>
<h3 id="unknown-size-negative-margin">Unknown Size, Negative Margin</h3>
<p>The simplest way we can utilize the <code>cap</code> to achieve alignment to the middle of the capital letter of the font (also known as “cap-height”) is by relying on <code>vertical-align: middle</code> and a simple calculation:</p>
<style>{`
.example {
font-size: min(2em, 9vw);
}
.example,
.example-flex {
padding: min(0.5em, 2.5vw);
}
.icon {
display: inline-block;
height: var(--size, min(2em, 10vw));
aspect-ratio: 1;
overflow: hidden;
resize: vertical;
background: var(--PINK)
}
`}</style>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#B392F0"> .icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> vertical-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">middle</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-block-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1</span><span style="color:#F97583">ex</span><span style="color:#F97583"> -</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">cap);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example1"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Nicely Aligned</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Why do we subtract cap height from the x-height? When we align things with <code>vertical-align</code> to <code>middle</code>, we’re aligning things to the <em>middle of the font’s x-height</em>. Here is an example of how things look without our technique:</p>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example-broken</span><span style="color:#B392F0"> .icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> vertical-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">middle</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example-broken"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> x</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Not Nicely Aligned</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Occasionally, this method <em>might</em> work, but in very rare cases where we’re certain that we’re aligning things over the lowercase letters only, with not many ascenders on the letters. Otherwise, predominantly, we want to align things to the cap height.</p>
<p>So, if the <code>middle</code> value aligns things to the x-height, but we want the cap height, the only thing we need to do is just move the element by its difference! That’s where the <code>1ex - 1cap</code> comes from, and the element’s height is already accounted for by the <code>middle</code> value.</p>
<aside>
If you’re wondering: if the `middle` aligns the _center_ of the x-height with the _center_ of the element, why are we using a margin with a _full_ value of the <span class="no-ligatures">difference</span>, and not a half of it?
<p>If we were using <code>position: relative</code> and <code>inset-block-start</code>, then yes, we’d have to do <code>calc(0.5ex - 0.5cap)</code>, but because we’re using <code>margin</code>, <em>it is accounted</em> for the <code>vertical-align: middle</code>: by having a negative margin, we <em>reduce</em> the size of our element by that value, and that means that the difference for the alignment will be half of that!</p>
</aside>
<h2 id="known-size-just-vertical-align">Known Size, Just Vertical-Align</h2>
<p>The example above is nice but requires us to use a negative margin. There is a different way to achieve the same, but only if we know the height of the element we’re aligning:</p>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example2</span><span style="color:#B392F0"> .icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">min</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">10</span><span style="color:#F97583">vw</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> vertical-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8">cap </span><span style="color:#F97583">-</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--size</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example2"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Nicely Aligned</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Our formula here is <code>0.5cap - 0.5 * var(--size)</code>: half of the cap height minus half of our element’s height. How is this calculated? When the value of <code>vertical-align</code> is a <code><length></code>, an element is aligned in a way its bottom edge stays on the text’s <em>baseline</em>:</p>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example-baseline</span><span style="color:#B392F0"> .icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> vertical-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example-baseline"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Baseline Alignment</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>You might ask: why use this method when it has the limitation of having to know the element’s height?</p>
<p>The answer: sometimes we might not know the <em>context</em> in which our element will be present, and if we will place our element in a context with <code>align-items: center</code>, it might not look good! We can easily demonstrate this by placing both examples inside a flex context:</p>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example-flex</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> align-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & > * {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">contents</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example-flex"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example1"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Not Nice</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example2"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Nice</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Because, in this case, we’re relying on the flex alignment, the <code>vertical-align</code> stops working. For our second technique, it is not relevant, as it was the only thing that handled the alignment (which is now handled by flex), but for the first technique, the margin stays, resulting in misalignment.</p>
<p>That means, that if we’re sure our element will <em>always</em> be in a regular inline flow, we can rely on the negative margin. But if we know the element’s size, then it might be beneficial to use the method that only uses <code>vertical-align</code>.</p>
<h2 id="the-fallbacks">The Fallbacks</h2>
<p>As I mentioned at the beginning of this post, while the <code>cap</code> is newly available, we should not use it in production as is. Too soon.</p>
<p>However, usually, it is not super complicated to work around it, at least partially.</p>
<p>The way to go could be to use a CSS variable and <code>@supports</code>, below is the same technique as in the first example, but modified to work without <code>cap</code> support:</p>
<p><a href="https://blog.kizu.dev/cap-height-align/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">html</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* Adjusted for Iowan Old Style */</span></span>
<span class="line"><span style="color:#FFAB70"> --cap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.704583</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">cap) {</span></span>
<span class="line"><span style="color:#85E89D"> html</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --cap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">cap;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example-fallback</span><span style="color:#B392F0"> .icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> vertical-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">middle</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-block-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1</span><span style="color:#F97583">ex</span><span style="color:#F97583"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--cap</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example-fallback"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Nicely Aligned</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>The only thing we have to do is to replace all our <code>cap</code> units with a <code>var(--cap)</code> variable and set it via <code>@supports</code> to <code>1cap</code> while setting it to the necessary value in <code>em</code> based on the font’s metrics by default.</p>
<p>How did I determine the value <code>0.704583em</code>? It is simple! Now, with <code>cap</code> being available in the browsers, it is effortless to get the proportions of any font. What I did was get a square with a font-size of <code>1000px</code>, and set its height to <code>1cap</code>, which resulted in <code>704.583px</code>, which, when divided by <code>1000</code> results in our value!</p>
<aside>
You can also try using the [Capsize](https://seek-oss.github.io/capsize/) tool by [Michael Taranto](https://github.com/michaeltaranto) to retrieve the metrics of your font — you’ll need to divide the “Cap Height” value by “Em square” value to get the value you’ll use in `em`.
</aside>
<p>Of course, it will work perfectly only for the font I did test it with — “Iowan Old Style” in my case, which I can see on my macOS as I’m using a stack with the built-in fonts. If you’re looking at this example in a browser that does not support <code>cap</code> and does not have Iowan Old Style installed, the alignment could break a bit. Which, in most cases, could be fine if this is only a visual alignment issue, and should not result in the content being inaccessible.</p>
<p>And if you’re using a custom web font, then it is more likely it will be always present, so it is safer to embed its metrics in this way.</p>
<h2 id="in-conclusion">In Conclusion</h2>
<p>I’m delighted that browsers improve the ways we can work with web typography. Maybe progress is not as fast as I would’ve liked (there are so many things I’d want to have!), but the arrival of <code>cap</code> (alongside other very helpful units like <code>ic</code> and <code>lh</code>) unlocks many doors.</p>
<p>As demonstrated, both techniques involving the <code>cap</code> rely on calculations and have their issues — that’s why I will still recommend going over the <a href="https://github.com/w3c/csswg-drafts/issues/4707">Tyler’s CSSWG issue</a> and voting for it, optionally providing your use cases or thoughts on the desired syntax in the comments. And maybe one day we could solve this just by using a single declaration involving <code>vertical-align</code>!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111693995535236523">on Mastodon</a>!</p>Notes on Using Logical Properties and Valueshttps://blog.kizu.dev/logical-props/https://blog.kizu.dev/logical-props/Adam Argyle asked today: “is it time to forget about physical properties like margin-top and left?” I have some thoughts occasionally on this, and decided to write them down as a list: maybe I’ll update it later with other related things, we’ll see. At the bottom of this post, I’ll also list several useful resources — don’t forget to check them out!Sun, 07 Jan 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — Eastern Glow</dd><dt>Current drink:</dt><dd>Yunnan Tea</dd></dl><hr /><p><a href="https://nerdy.dev/">Adam Argyle</a> <a href="https://nerdy.dev/is-it-time-to-throw-out-physical-properties">asked today</a>:</p>
<blockquote>
<p>is it time to forget about physical properties like margin-top and left?</p>
</blockquote>
<p>I have some thoughts occasionally on this, and decided to write them down as a list: maybe I’ll update it later with other related things, we’ll see. At the bottom of this post, I’ll also list several useful resources — don’t forget to check them out!</p>
<ol>
<li>
<p>If you’re new to <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values">logical properties and values in CSS</a>, it might be overwhelming to start using them: so much to learn! I will suggest starting slow, do not attempt to learn <em>everything at the same time</em>.</p>
</li>
<li>
<p>For myself, I found the best way to get used to how logical keywords work was to first start using only logical shorthands: <code>margin-block</code>, <code>margin-inline</code>, <code>padding-block</code>, <code>padding-inline</code> and so on. They’re tremendously useful on their own! Through the years, I often wanted to have these kinds of shortcuts like <code>margin-x</code>, and these logical shortcuts fulfil this. By starting using them, you will cover some of your use cases, and will get used to differentiating <code>block</code> and <code>inline</code> directions as a muscle memory, without thinking.</p>
</li>
<li>
<p>One way to think of the <code>block</code> and <code>inline</code> directions would be to imagine two lists: one where all elements have <code>display: block</code>, and another where all elements have <code>display: inline</code>. By default, <em>block</em> elements go vertically, and <em>inline</em> go horizontally — the same way the logical directions work as well.</p>
</li>
<li>
<p>After starting to distinguish between the block and inline directions, understanding <code>start</code> and <code>end</code> should be, hopefully, much easier! When looking at these keywords, the only thing we need to think about is the positions of the elements or content inside of them: what goes earlier, what goes later? The axis will be handles by <code>block</code> or <code>inline</code>, and I found that separating the parts in this way helps a lot.</p>
</li>
<li>
<p>While I’m mentioning trying different properties separately and getting to learn them slowly, I won’t recommend learning them this way <em>in production</em>. Very often, logical keywords should be all-or-nothing: by mixing them, it might be possible to break things in unexpected ways. It is always a good idea to test how things will actually work by flipping the <code>direction</code> or <code>writing-mode</code>, and seeing <em>what happens</em>. It is easy to make content inaccessible when you expect things to align: when one element flips its direction, and another does not — like when positioning something absolutely.</p>
</li>
<li>
<p>Speaking of absolute positioning: after margins, paddings, and borders it might be time to look at more “complex” (in terms of naming) properties: <code>inset-</code> group of properties as a logical alternative for <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code>, and <code>-size</code> group of properties as an alternative for <code>width</code> and <code>height</code>.</p>
<ul>
<li>For <code>inset</code> the shorthands are <em>very handy</em>: the <code>inset</code> itself, with the <code>inset:0</code> being the staple in a lot of CSS I write, and the <code>inset-block</code> and <code>inset-inline</code> joining the other directional shorthands that make it easier to learn the directions.</li>
<li>The <code>block-size</code>, <code>inline-size</code>, and their <code>min-</code> and <code>max-</code> variations, on the other hand, do not bring any new capabilities, but it is important to learn them when you need to match them with other logical properties.</li>
</ul>
</li>
<li>
<p>The names of some logical properties might be rather frightening: <code>border-start-start-radius</code>, <code>border-start-end-radius</code>, what? The way to remember which is which in this case is to remember how the two-value shorthands for <code>margin</code> and <code>padding</code> work (even though they’re physical): the first value in such shorthand is for the vertical direction, and the second is for the horizontal. If those were logical, with the default mapping of vertical – block and horizontal – inline, then for <code>border-radius</code> logical properties it is the same: the first keyword is for the block direction, the second is for the inline! So, in <code>border-start-end-radius</code> the <code>start</code> is in the block direction, and <code>end</code> is in the inline one.</p>
</li>
<li>
<p>On the other hand, some other cases, especially when only the values are involved, are easier: <code>text-align: start</code> and <code>text-align: end</code> are simple to remember.</p>
</li>
<li>
<p>We need to always check out the support of the keywords we’d want to try using with logical values. While the basic margins and paddings are <a href="https://caniuse.com/css-logical-props">well-supported</a>, other properties could either be just arriving to the browsers (<code>inline-start</code> and <code>inline-end</code> for <code>float</code> and <code>clear</code> are supported in Chrome only from October 2023), or not well-supported (<code>overflow-block</code> and <code>overflow-inline</code> are available only for Firefox at the moment of writing this article). It is better to always check for the support yourself, and, if you have to support older browsers, provide fallbacks.</p>
</li>
<li>
<p>While it might be a good idea to approach CSS with logical keywords first, there are cases where we could want to use physical properties and values. For example, when we want to match something with the positions on an image, which won’t change based on the writing mode. And not <em>everything</em> is yet available in logical forms: transforms, backgrounds, some other cases — when there is a need to match our styles with the physical-only cases, sometimes there is no other choice than to use the physical properties and values alongside, to not create a mismatch.</p>
</li>
<li>
<p>However, as it is often with CSS, there are workarounds, like when using a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:dir"><code>:dir()</code> pseudo-class</a> (warning: started being available in Chromium-based browsers only from December 2023) and overriding things that are physical-only based on the direction.</p>
</li>
</ol>
<h2 id="related-articles">Related Articles</h2>
<p>Final thing: the above are just my thoughts on this, and I’m far from being an expert on this topic! There are many other resources and people who are much more familiar with it, and with other writing systems, who could provide more insights. I highly recommend checking out the following links (starting from references, and then listed in published order).</p>
<ul>
<li><a href="https://drafts.csswg.org/css-logical-1/">“CSS Logical Properties and Values Level 1”</a> specification.</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values">“CSS logical properties and values”</a> — MDN page containing a list of most logical properties and values.</li>
<li><a href="https://adrianroselli.com/2019/11/css-logical-properties.html">“CSS Logical Properties”</a> by <a href="https://adrianroselli.com/">Adrian Roselli</a></li>
<li><a href="https://chenhuijing.com/blog/css-for-i18n/">“CSS for internationalisation”</a> by <a href="https://chenhuijing.com/">Chen Hui Jing</a>.</li>
<li><a href="https://ishadeed.com/article/css-logical-properties/">“Digging Into CSS Logical Properties”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a>.</li>
<li><a href="https://css-irl.info/logical-properties-for-useful-shorthands/">“Logical Properties for Useful Shorthands”</a> by <a href="https://css-irl.info/">Michelle Barker</a>.</li>
<li><a href="https://adactio.com/journal/19457">“Let’s get logical”</a> by <a href="https://adactio.com/">Jeremy Keith</a></li>
<li><a href="https://www.miriamsuzanne.com/2022/09/16/tpac-logical/">“A long-term plan for logical properties?”</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a></li>
</ul>
<hr>
<p>If you’ll have any thoughts, corrections or additions — please let me know!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111714232747568412">on Mastodon</a>!</p>Weekly Bookmarks 11: The Backloghttps://blog.kizu.dev/weekly-bookmarks-011/https://blog.kizu.dev/weekly-bookmarks-011/I did take a break from writing anything for the most of January. During this time, many people published tons of things, so this post will be very long. 50+ articles long.Sun, 11 Feb 2024 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Ginger & apple tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>I did take a break from writing anything for the most of January. During this time, many people published tons of things, so this post will be very long. When I started compiling this list (and actually reading all the content I’m linking to), it ended up a bigger task than I anticipated, so I did also skip publishing over the first week of February. But I’m happy that so many people are writing about CSS!</p>
<p>Because the list of links is so long this time, I did put them into various categories: <a href="#interop-2024">Interop 2024</a>, <a href="#scroll-driven-animations">Scroll-Driven Animations</a>, <a href="#style-encapsulation">Style Encapsulation</a>, <a href="#forms-and-interactions">Forms and Interactions</a>, <a href="#layout">Layout</a>, <a href="#typography">Typography</a>, <a href="#thoughts-and-opinions">Thoughts and Opinions</a>, <a href="#theming">Theming</a>, <a href="#other-articles">Other Articles</a>, <a href="#my-posts">My Posts</a> — feel free to skip to what you find more interesting, as there are more than 50 articles combined!</p>
<h2 id="interop-2024">Interop 2024</h2>
<p>Ok, the first thing I’m sharing is not from January, really. The list of focus areas was just been finalized!</p>
<ul>
<li>
<p><a href="https://web.dev/blog/interop-2023-wrapup">“Celebrate a more interoperable web with Interop 2023”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> — a post about the results of the previous year of the Interop initiative. It is very gratifying to see the possible progress when multiple browser vendors are working on the same goals.</p>
</li>
<li>
<p><a href="https://wpt.fyi/interop-2024">“Interop 2024 Dashboard”</a> — the dashboard to keep an eye on as a way to track the progress throughout the whole 2024.</p>
</li>
<li>
<p>All the stakeholders for this year’s initiative did post the introductory posts about it:</p>
<ul>
<li>
<p><a href="https://webkit.org/blog/14955/the-web-just-gets-better-with-interop/">“The web just gets better with Interop 2024”</a> by <a href="https://jensimmons.com/">Jen Simmons</a> from Apple.</p>
</li>
<li>
<p><a href="https://bocoup.com/blog/interop-2024">“Interop 2024 Launch”</a> by <a href="https://lolaodelola.dev/">Lola Odelola</a> and <a href="https://www.lazarusletcher.com/">Lazarus Letcher</a> from Bocoup.</p>
</li>
<li>
<p><a href="https://web.dev/blog/interop-2024">“Interop 2024”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> from Google.</p>
</li>
<li>
<p><a href="https://www.igalia.com/2024/interop-2024-launches.html">“Interop 2024 Launches”</a> by <a href="https://www.igalia.com/">Igalia</a>.</p>
</li>
<li>
<p><a href="https://blogs.windows.com/msedgedev/2024/02/01/microsoft-edge-and-interop-2024/">“Microsoft Edge and Interop 2024”</a> by <a href="https://patrickbrosset.com/">Patrick Brosset</a> and <a href="https://github.com/dandclark">Dan Clark</a> from Microsoft.</p>
</li>
<li>
<p><a href="https://hacks.mozilla.org/2024/02/announcing-interop-2024/">“Announcing Interop 2024”</a> by <a href="https://hoppipolla.co.uk/">James Graham</a> from Mozilla.</p>
</li>
</ul>
</li>
<li>
<p>Some people did write about what got into the Interop 2024 list and their thoughts regarding this:</p>
<ul>
<li><a href="https://piccalil.li/blog/interop-2024/">“Interop 2024”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a post about the focus areas from the initiative Andy looks forward to most.</li>
<li><a href="https://frontendmasters.com/blog/comparing-interop-2024-choices-to-the-popular-vote/">“Comparing Interop 2024 Choices to the Popular Vote”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post looking at the differences between what was chosen and what people voting for the issues on GitHub wanted to be included. Personally, I think there might be a misconception over what the Interop initiative is, but that might be a topic for a separate blog post, not a sidenote in this long list of links.</li>
</ul>
</li>
</ul>
<h2 id="scroll-driven-animations">Scroll-Driven Animations</h2>
<p>While scroll-driven animations were not selected for the Interop 2024, I truly hope Safari and Firefox will ship them sooner rather than later: there are so many use cases for them!</p>
<ul>
<li>
<p><a href="https://tympanus.net/codrops/2024/01/17/a-practical-introduction-to-scroll-driven-animations-with-css-scroll-and-view/">“A Practical Introduction to Scroll-Driven Animations with CSS <code>scroll()</code> and <code>view()</code>”</a> by <a href="https://nerdy.dev/">Adam Argyle</a> — a tutorial covering the basics of the scroll-driven animations (for more traditional effects on scroll, unlike <a href="https://kizu.dev/tags/scroll_driven_animations/">the weird stuff I tend to do</a>).</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/highlight-text-when-a-user-scrolls-down-to-that-piece-of-text/">“Highlight Text When a User Scrolls Down to That Piece of Text”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a case-study of implementing an effect used by <a href="https://www.lenesaile.com/">Lene Saile</a> in her blog, but implemented using scroll-driven animations.</p>
</li>
<li>
<p><a href="https://ryanmulligan.dev/blog/scroll-triggered-animations-style-queries/">“CSS Scroll-triggered Animations with Style Queries”</a> by <a href="https://ryanmulligan.dev/">Ryan Mulligan</a> — an exploration of one way to have scroll-triggered animations, based initially on an observation it in <a href="https://jhey.dev/">Jhey Tompkins’</a> <a href="https://codepen.io/jh3y/pen/qBgRLxb">CodePen</a> which implemented an effect similar to the one in the previous article, but with an addition of style container queries.</p>
</li>
</ul>
<h2 id="style-encapsulation">Style Encapsulation</h2>
<p>There are many discussions about web components recently, specifically about Shadow DOM, style encapsulation, and other related topics. Here are some of the things I found interesting.</p>
<ul>
<li>
<p><a href="https://nolanlawson.com/2023/12/30/shadow-dom-and-the-problem-of-encapsulation/">“Shadow DOM and the problem of encapsulation”</a> by <a href="https://nolanlawson.com/">Nolan Lawson</a> — an article looking at the problem of Shadow DOM style encapsulation, the tradeoffs of it, and some existing workarounds.</p>
</li>
<li>
<p><a href="https://knowler.dev/blog/so-you-want-to-encapsulate-your-styles">“So, You Want to Encapsulate Your Styles?”</a> by <a href="https://knowler.dev/">Nathan Knowler</a> — an article looking at the ways styles can cross the Shadow DOM boundary, and how we could use CSS layers, especially <code>revert-layer</code> keyword, to achieve encapsulation without it.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/revert-layer">“Some use cases for <code>revert-layer</code>”</a> by <a href="https://www.mayank.co/">Mayank</a> — a more precise look into the <code>revert-layer</code> keyword and its other use cases. Very fascinating techniques showcasing the uniqueness of this keyword and the powers of the custom cascade layers.</p>
</li>
<li>
<p><a href="https://github.com/bkardell/half-light">“half-light”</a> by <a href="https://bkardell.com/">Brian Kardell</a> — a small experimental library which allows writing special custom media-queries to inject some styles into the Shadow DOM from the outside.</p>
</li>
</ul>
<h2 id="forms-and-interactions">Forms and Interactions</h2>
<ul>
<li>
<p><a href="https://ishadeed.com/article/target-size">“Designing better target sizes”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — a long and very detailed article with many interactive examples about the target area of interactive elements, and some other related concepts like spacing and safe triangle areas for dropdown menus.</p>
</li>
<li>
<p><a href="https://polypane.app/blog/field-sizing-just-works/">“Field-sizing just works!”</a> by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a> — a practical overview of the experimental <code>field-sizing</code> property.</p>
</li>
<li>
<p><a href="https://daverupert.com/2024/01/focus-visible-love/">“Big, beautiful, beefy focus states with <code>:focus-visible</code>”</a> by <a href="https://daverupert.com/">Dave Rupert</a> — a post about how we can make the keyboard-only focus state much more prominent than the one that is also applied when using a regular <code>:focus</code>.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/safari-focus">“When will Apple focus on Safari?”</a> by <a href="https://www.mayank.co/">Mayank</a> — an article about how Safari mistreats the focus in CSS, where users have to jump through countless hoops to make it work, and how this is a serious accessibility and interoperability issue.</p>
</li>
<li>
<p><a href="https://jacobpadilla.com/articles/hover-media-query">“The Most Underused CSS Media Queries: Hover & Any-Hover”</a> by <a href="https://jacobpadilla.com/">Jacob Padilla</a> — a brief look at the <code>hover</code> and <code>any-hover</code> media queries.</p>
</li>
<li>
<p><a href="https://www.sarahgebauer.com/post/css-knows-about-your-mouse/">“CSS knows about your mouse”</a> by <a href="https://www.sarahgebauer.com">Sarah Gebauer</a> — a similar post which also touches on the <code>pointer</code> media queries in addition to the <code>hover</code> ones.</p>
</li>
</ul>
<p>Also, a reminder from me: <code>cursor: pointer</code> is a good default for any buttons. Just saying.</p>
<h2 id="layout">Layout</h2>
<p>In this section, we have articles covering almost every layout possible in some way, maybe except for the flex layout.</p>
<ul>
<li>
<p><a href="https://www.scale.at/blog/css-layout-modes">“Tutorial: Four CSS Layout Modes and Their Use Cases”</a> by <a href="https://github.com/lara-amalia">Lara Aigmüller</a> — a brief overview of four older layout algorithms: flow, float, multi-column and positioned.</p>
</li>
<li>
<p><a href="https://dev.to/madsstoumann/a-guide-to-styling-tables-28d2">“A Guide to Styling Tables”</a> by <a href="https://stoumann.dk/">Mads Stoumann</a> — an article covering various ways we can style the tables.</p>
</li>
<li>
<p><a href="https://www.lenesaile.com/en/blog/inheriting-grid-dimensions-from-siblings-with-subgrid/">“‘Inheriting’ grid dimensions from siblings with subgrid”</a> by <a href="https://www.lenesaile.com/">Lene Saile</a> — an article about how subgrid children can affect the parent grid’s dimensions.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/reality-check-3-building-out-a-layered-hero-grid-layout-from-dribbble/">“Reality Check #3: Building out a layered hero grid layout from Dribbble”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a deep dive into an implementation of an interesting layout using CSS grids.</p>
</li>
<li>
<p><a href="https://nerdy.dev/neue-bento-layouts-with-grid-has-and-container-queries">“Always great grid - CSS grid + <code>:has()</code> + view transitions”</a> by <a href="https://nerdy.dev/">Adam Argyle</a> — an experiment showing how we can use <code>:has()</code> in a way similar to <a href="https://alistapart.com/article/quantity-queries-for-css/">quantity queries</a> but when applied to the parent.</p>
</li>
</ul>
<h2 id="typography">Typography</h2>
<ul>
<li>
<p><a href="https://maketypework.com/web-typography-baseline-grids-made-easy/">“Web typography: baseline grids made easy (finally!)”</a> by <a href="https://maketypework.com/">Jake Giltsoff</a> — an article about how the <code>cap</code> unit could help with implementing designs with vertical rhythm.</p>
</li>
<li>
<p><a href="https://httpster.io/article/webfonts-and-layout-shifting/">“Webfonts and layout shifting”</a> by <a href="https://httpster.io/">Sami Mäkelä</a> — a post outlining how it might be possible to reduce the cumulative layout shift coming from the mismatch of the web font with its fallback, with a few useful resources that can help with it linked inside.</p>
</li>
<li>
<p><a href="https://techhub.iodigital.com/articles/going-beyond-pixels-and-rems-in-css/relative-length-units-based-on-font">“Going beyond pixels and (r)ems in CSS - Relative length units based on font”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — a detailed article about font-relative units. While they can be used for non-typography related tasks, for obvious reasons typography is where they will be the most useful, and many examples in the article show this. The <a href="https://techhub.iodigital.com/articles/going-beyond-pixels-and-rems-in-css/relative-length-units-based-on-the-viewport">second part</a> of the series looks into the viewport-relative units, which could also be used for typography, but less so.</p>
</li>
<li>
<p><a href="https://textlab.dev/posts/font-variant-numeric">“Using Font Variant Numeric”</a> by <a href="https://mandy.dev/">Mandy Michael</a> — an article about <code>font-variant-numeric</code> and all the different ways it can help in making numbers look good in text and tables by unlocking the alternative glyphs for the digits that might be present in the fonts you’re using.</p>
</li>
<li>
<p><a href="https://codersblock.com/blog/nicer-text-wrapping-with-css-text-wrap/">“Nicer Text Wrapping with CSS <code>text-wrap</code>”</a> by <a href="https://codersblock.com/">Will Boyd</a> — an article about <code>text-wrap</code> and its two values: <code>balance</code> and <code>pretty</code>.</p>
</li>
</ul>
<h2 id="thoughts-and-opinions">Thoughts and Opinions</h2>
<ul>
<li>
<p><a href="https://bkardell.com/blog/WhatsGood.html">“What’s Good?”</a> by <a href="https://bkardell.com/">Brian Kardell</a> — a question following some Interop 2024 discussions, where Brian asks us to look at things from a different angle and find what we have today and which awesome web platform features we got in the past few years.</p>
</li>
<li>
<p><a href="https://matthiasott.com/notes/whats-too-good-to-be-true">“What’s Too Good to Be True?”</a> by <a href="https://matthiasott.com/">Matthias Ott</a> — a response to the previous question.</p>
</li>
<li>
<p><a href="https://cssence.com/2024/is-css-alive/">“Is CSS alive?”</a> by <a href="https://cssence.com/">Matthias Zöchling</a> — a related article with some thoughts about various recent CSS features and how useful Matthias finds them.</p>
</li>
<li>
<p><a href="https://thinkdobecreate.com/articles/a-call-for-consensus-on-html-semantics/">“A Call for Consensus on HTML Semantics”</a> by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — a glimpse over how HTML semantics are not as simple and clear-cut, with many nuances making us think about the code we write.</p>
</li>
</ul>
<h2 id="theming">Theming</h2>
<p>Nothing too new in this section, but a few small things that are worth it to remember.</p>
<ul>
<li>
<p><a href="https://jwdallas.com/posts/nesteddarkmode">“Nested Dark Mode via CSS Proximity”</a> by <a href="https://jwdallas.com/">Jonathan Dallas</a> — a post about how inheritance of custom properties makes them a good fit for theming.</p>
</li>
<li>
<p><a href="https://blog.cassidoo.co/post/css-accent-color/">“Use CSS <code>accent-color</code> to style your inputs”</a> by <a href="https://cassidoo.co/">Cassidy Williams</a> — a reminder that we can use the <code>accent-color</code> property as a low-effort way to style the native inputs.</p>
</li>
<li>
<p><a href="https://manuel-strehl.de/easy_theming_with_oklch">“Easy Theming with OKLCH colors”</a> by <a href="https://manuel-strehl.de/">Manuel Strehl</a> — a demonstration of how we can use custom property inside an <code>oklch()</code> for theming purposes, achieving a similar effect as for the <code>accent-color</code>, but for any custom styles.</p>
</li>
</ul>
<h2 id="other-articles">Other Articles</h2>
<p>There were other articles, which I couldn’t categorize into more specific groups.</p>
<ul>
<li>
<p><a href="https://utilitybend.com/blog/taking-a-closer-look-at-property-in-css/">“Taking a closer look at <code>@property</code> in CSS”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — an article about the basics of <code>@property</code> and how it can help with animations for custom properties.</p>
</li>
<li>
<p><a href="https://moderncss.dev/12-modern-css-one-line-upgrades/">“12 Modern CSS One-Line Upgrades”</a> by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> — a great collection of simple and powerful CSS techniques.</p>
</li>
<li>
<p><a href="https://keithjgrant.com/posts/2024/01/my-css-resets/">“My CSS resets”</a> by <a href="https://keithjgrant.com/">Keith J. Grant</a> — an article, in which Keith showcases his CSS reset, explaining the decisions behind its various parts.</p>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2024/01/css-border-image-property/">“The Complex But Awesome CSS <code>border-image</code> Property”</a> by <a href="https://css-articles.com/">Temani Afif</a> — a deep dive into the <code>border-image</code>, and various use cases it allows us to achieve.</p>
<p>Temani did publish many other articles and tips, I won’t list them all — follow him yourself! But I will add two of his other recent posts that I did found the most useful:</p>
<ul>
<li>
<p><a href="https://css-tip.com/min-max/">“When to use the <code>min()</code> or <code>max()</code> function”</a> — a nice way to look and understand the differences between <code>min()</code>, <code>max()</code> and <code>clamp()</code>.</p>
</li>
<li>
<p><a href="https://css-tip.com/triangle-rounded-corner/">“Triangle shape with rounded corners”</a> — a nice way to have rounded rectangles by using masks, <code>clip-path</code> and CSS variables.</p>
</li>
</ul>
</li>
<li>
<p><a href="https://polypane.app/blog/my-take-on-fading-content-using-transparent-gradients-in-css/">“My take on fading content using transparent gradients in CSS”</a> by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a> — an article outlining two techniques for achieving an effect of fading lines of text.</p>
</li>
</ul>
<h2 id="my-posts">My Posts</h2>
<p>Since <a href="/weekly-bookmarks-010/">last weekly</a>, I did write just four blog posts, here they are:</p>
<ul>
<li><a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">“A Christmas Tree Selector: Prototyping the <code>:nth-sibling()</code> with CSS Nesting”</a></li>
<li><a href="https://blog.kizu.dev/cap-height-align/">“Cap-Height Vertical Align”</a></li>
<li><a href="https://blog.kizu.dev/logical-props/">“Notes on Using Logical Properties and Values”</a></li>
<li><a href="https://blog.kizu.dev/my-2023-in-css/">“My year in CSS”</a></li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111913738562386145">on Mastodon</a>!</p>Weekly Bookmarks 12https://blog.kizu.dev/weekly-bookmarks-012/https://blog.kizu.dev/weekly-bookmarks-012/I had a lot of fun and ideas reading this last week’s articles and posts about CSS: I’m so happy we have so many people sharing their findings!Mon, 19 Feb 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Heather Woods Broderick — Cottonwood Bay</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>I had a lot of fun and ideas reading this last week’s articles and posts about CSS: I’m so happy we have so many people sharing their findings!</p>
<ul>
<li>
<p><a href="https://www.joshwcomeau.com/css/center-a-div/">“How To Center a Div”</a> by <a href="https://www.joshwcomeau.com/">Josh W. Comeau</a> — a detailed explanation of various ways we can center things in CSS, with many interactive examples.</p>
</li>
<li>
<p><a href="https://miunau.com/posts/dynamic-text-contrast-in-css/">“Dynamic text color contrast based on background lightness with CSS/SVG filters”</a> by <a href="https://miunau.com/">miunau</a> — an experiment about trying to get the contrasting color automatically for some other given color. Basically, what we might eventually get with the <a href="https://drafts.csswg.org/css-color-6/#colorcontrast"><code>color-contrast()</code></a>, but via using CSS or SVG filters instead.</p>
</li>
<li>
<p><a href="https://css-irl.info/how-i-solved-my-font-rendering-problem/">“How I Solved My Font Rendering Problem”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — a post about how it is important to explicitly mention the font-weight range in the <code>@font-face</code> rule of a variable font.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/how-to-fix-the-invisible-scrollbar-issue-in-ios/">“How to fix the invisible scrollbar issue in iOS browsers”</a> by <a href="https://%C5%A1ime.eu/">Šime Vidas</a> — an article about how iOS uses the top-level background color as the thing that defines the color of the overlay scrollbars, sometimes resulting in lack of contrast.</p>
</li>
<li>
<p><a href="https://phloe.co/dev/font-size">“The chaotic neutral nature of font-size”</a> by <a href="https://phloe.co/">Rasmus Fløe</a> — an article about adjusting the size of the fonts to be more logical with <code>font-size-adjust</code> or its workarounds, and a few related issues.</p>
</li>
<li>
<p><a href="https://www.bram.us/2024/02/14/scroll-driven-animations-you-want-overflow-clip-not-overflow-hidden/">“Scroll-Driven Animations: You want <code>overflow: clip</code>, not <code>overflow: hidden</code>”</a> by <a href="https://www.bram.us/">Bramus</a> — a post about how <code>overflow: hidden</code> could interact with scroll-driven animations and about one workaround for this.</p>
</li>
<li>
<p><a href="https://codepen.io/giana/pen/gOEQmVW">“CSS-only Auto-Collapsing Mobile Menu”</a> by <a href="https://codepen.io/giana">Georgiana Blantin</a> — an article about discovering a technique to detect (and use) the position of some elements in a container by using scroll-driven animations, a bit similar to the technique that I called <a href="https://kizu.dev/position-driven-styles/">“Position-Driven Styles”</a>.</p>
</li>
<li>
<p><a href="https://ryanmulligan.dev/blog/50-50-overflow/">“The Fifty-Fifty Split and Overflow”</a> by <a href="https://ryanmulligan.dev/">Ryan Mulligan</a> — an article about one way to achieve a certain type of layout with two side-by-side columns, only one of which dictates the overall height of both.</p>
</li>
<li>
<p><a href="https://codersblock.com/blog/playing-with-infinity-in-css/">“Playing with Infinity in CSS”</a> by <a href="https://codersblock.com/">Will Boyd</a> — an exploration of the CSS <code>infinity</code> constant, with a few curious notes about how it works. Last November, I explored how it could be used in <code>clamp()</code> as a way to remove one of the boundaries in my <a href="/clamp-to-infinity/">“Observation: Clamp to Infinity”</a> post, though just a few days ago we got <a href="https://github.com/w3c/csswg-drafts/issues/9713#issuecomment-1944449961">a CSSWG resolution</a> to have a native ability to define <code>none</code> to achieve the same effect, thanks to <a href="https://lea.verou.me/">Lea Verou</a>’s <a href="https://github.com/w3c/csswg-drafts/issues/9713">proposal</a>.</p>
</li>
<li>
<p><a href="https://textlab.dev/posts/font-variant-ligatures">“Making the most of ligatures”</a> by <a href="https://mandy.dev/">Mandy Michael</a> — an article about the way we can control the rendering of ligatures in CSS.</p>
</li>
<li>
<p><a href="https://danielcwilson.com/posts/mathematicss-powers/">“The New CSS Math: <code>pow()</code>, <code>sqrt()</code>, and exponential friends”</a> by <a href="https://danielcwilson.com/">Daniel C. Wilson</a> — a quick overview of a few newly available CSS math functions.</p>
</li>
<li>
<p><a href="https://cssence.com/2024/accent-color-is-no-css-variable-revisited/">“Accent Color Access, Revisited”</a> by <a href="https://cssence.com/">Matthias Zöchling</a> — a shot post inspired by <a href="https://front-end.social/@mia/111922702873228540">a Mastodon post</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> about the differences between <code>accent-color</code> and <code>accentColor</code>.</p>
</li>
</ul>
<hr>
<p>There were also a few articles about Tailwind and utility-first approach last week, but I don’t want to share them as is without providing my own opinion alongside, and I didn’t have an opportunity to fully work on it.</p>
<p>One thing, as a semi-spoiler for it: look at the above list of articles people did write about CSS in a span of a week, and think about how many things described in them are possible to achieve with today’s utility-first approaches.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111959809989681964">on Mastodon</a>!</p>Weekly Bookmarks 13https://blog.kizu.dev/weekly-bookmarks-013/https://blog.kizu.dev/weekly-bookmarks-013/Mon, 26 Feb 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>toe — The World According To</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>As usual, a few articles about CSS that I found interesting this week, nine of them.</p>
<ul>
<li>
<p><a href="https://lea.verou.me/docs/var-groups/">“Proposal: CSS Variable Groups”</a> by <a href="https://lea.verou.me/">Lea Verou</a> — a proposal and <a href="https://github.com/w3c/csswg-drafts/issues/9992">an associated CSSWG issue</a> about an ability to have something similar to maps or arrays in native CSS. I wanted to have something like this for years, and I truly hope that this will lead to something!</p>
</li>
<li>
<p><a href="https://ericportis.com/posts/2024/okay-color-spaces/">“Okay, Color Spaces”</a> by <a href="https://ericportis.com/">Eric Portis</a> — a very comprehensive article about the color spaces which makes it easy to understand how they work and what are the differences between them.</p>
</li>
<li>
<p><a href="https://ishadeed.com/article/css-has-guide/">“CSS <code>:has()</code> Interactive Guide”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — a detailed article with many interactive examples about what <code>:has()</code> pseudo-class is, and many of its use cases.</p>
</li>
<li>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_size_and_style_queries">“Using container size and style queries”</a> by <a href="https://standardista.com/">Estelle Weyl</a> — an MDN guide about container queries (both size and style ones).</p>
</li>
<li>
<p><a href="https://jakearchibald.com/2024/view-transitions-handling-aspect-ratio-changes/">“View transitions: Handling aspect ratio changes”</a> by <a href="https://jakearchibald.com/">Jake Archibald</a> — a post explaning how we can improve or fix view transitions in complex cases by separating the transitions to happen on multiple elements.</p>
</li>
<li>
<p><a href="https://adactio.com/journal/20899">“Speedier tunes”</a> by <a href="https://adactio.com/">Jeremy Keith</a> — a short post about how <code>content-visibility</code> can improve performance when rendering lists with complex elements (in this case, with SVGs inside).</p>
</li>
<li>
<p><a href="https://developer.chrome.com/blog/css-backdrop-inheritance?hl=en">“Changes to CSS <code>::backdrop</code> inheritance”</a> by <a href="https://www.bram.us/">Bramus</a> — a post about the recent update to the <code>::backdrop</code>, allowing it to inherit styles from the originating element.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/declarative-shadow-dom-guide">“A practical guide to using shadow DOM”</a> by <a href="https://www.mayank.co/">Mayank</a> — a post explaining what shadow DOM is, with a focus on the <em>declarative</em> shadow DOM which is now available in all major browsers.</p>
</li>
<li>
<p><a href="https://knowler.dev/blog/declarative-custom-elements-should-take-inspiration-from-css">“Declarative Custom Elements Should Take Inspiration From CSS”</a> by <a href="https://knowler.dev/">Nathan Knowler</a> — a post outlining an idea to use a CSS-like syntax for re-binding HTML attributes declaratively. It did remind me of <a href="https://web.archive.org/web/20220606213657/https://www.xanthir.com/blog/b4K_0">Cascading Attribute Sheets proposal</a> by <a href="https://xanthir.com/">Tab Atkins-Bittner</a>, though I doubt we will get anything like that anytime soon.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111999228361492307">on Mastodon</a>!</p>Two Invitationshttps://blog.kizu.dev/two-invitations/https://blog.kizu.dev/two-invitations/In the last few weeks, I received two invitations: an invitation to speak at the next CSS Day, and an invitation to join the CSS Working Group as an Invited Expert. Of course, I did accept both of them.Sat, 09 Mar 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>S — wait</dd><dt>Current drink:</dt><dd>Cinnamon Tea</dd></dl><hr /><p>In the last few weeks, I received two invitations:</p>
<ol>
<li>
<p>An invitation to speak at the next <a href="https://cssday.nl/2024">CSS Day</a>.</p>
</li>
<li>
<p>An invitation to join the <a href="https://www.w3.org/Style/CSS/members">CSS Working Group</a> as an <a href="https://www.w3.org/invited-experts/">Invited Expert</a>.</p>
</li>
</ol>
<p>Of course, I did accept both of them:</p>
<ol>
<li>
<p>I’ll <a href="https://cssday.nl/2024/speakers#roma">give a talk</a> titled “Impactful Experimentation” at CSS Day in June.</p>
</li>
<li>
<p>You can now find me on the CSSWG <a href="https://www.w3.org/groups/wg/css/participants/#kizu">“Participants”</a> page.</p>
</li>
</ol>
<p>I still do not entirely believe this did happen.</p>
<p>I guess, I need to push my impostor syndrome away for a bit and accept that maybe after 17+ years of writing CSS as a full-time job, experimenting with it in my spare time, sharing the findings on my site, and my more recent activity in CSSWG issues did bring some fruits.</p>
<p>I did already participate in one weekly CSSWG meeting, and started working on the rought outline of my talk. In CSSWG I’m mostly observing how things work for now, and I’m mostly planning on continuing doing what I’m doing: keeping an eye on the emerging specs, authors’ requests, playing with the existing prototypes of the newer specs like I did with anchor positioning, and give my feedback on all of this.</p>
<p>Let’s see where all of this will lead next!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112065952345245535">on Mastodon</a>!</p>Weekly Bookmarks 14https://blog.kizu.dev/weekly-bookmarks-014/https://blog.kizu.dev/weekly-bookmarks-014/A bit later than usual, but I did finally read all the articles and posts about CSS that I bookmarked in the last week.Tue, 05 Mar 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Exist Strategy — Broken Air</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><p>A bit later than usual, but I did finally read all the articles and posts about CSS that I bookmarked in the last week.</p>
<ul>
<li>
<p><a href="https://www.smashingmagazine.com/2024/03/modern-css-tooltips-speech-bubbles-part1/">“Modern CSS Tooltips And Speech Bubbles (Part 1)”</a> by <a href="https://css-articles.com/">Temani Afif</a> — an article about a technique to implement tooltips with <code>border-image</code> and <code>clip-path</code> (and a bunch of math). I wish there was some native way to do some of this (maybe I should come up with a proposal for this or something).</p>
</li>
<li>
<p><a href="https://techhub.iodigital.com/articles/going-beyond-pixels-and-rems-in-css/container-query-length-units">“Going beyond pixels and (r)ems in CSS - Container query length units”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — a practical article about using container query length units.</p>
</li>
<li>
<p><a href="https://danielcwilson.com/posts/mathematicss-constants/">“The New CSS Math: pi and other constants”</a> by <a href="https://danielcwilson.com/">Daniel C. Wilson</a> — an article about the new math constants: <code>pi</code>, <code>e</code>, <code>infinity</code>, and even <code>NaN</code>.</p>
</li>
<li>
<p><a href="https://www.bram.us/2024/02/26/css-what-is-iacvt/">“CSS Foundations: What is IACVT?”</a> by <a href="https://www.bram.us/">Bramus</a> — a post explaining what “Invalid At Computed Value Time” is in CSS. A good read in case you want to understand how things work on a more foundational level.</p>
</li>
<li>
<p><a href="https://lynnandtonic.com/thoughts/entries/case-study-2023-refresh/">“Case Study: lynnandtonic.com 2023 refresh”</a> by <a href="https://lynnandtonic.com/">Lynn Fisher</a> — a detailed case study about another annual Lynn’s redesign of her website. A lot of <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver">ResizeObserver</a> usage, CSS variables, and nice tiny details.</p>
</li>
<li>
<p><a href="https://clagnut.com/blog/2428/">“Retrofitting fluid typography”</a> by <a href="https://clagnut.com/">Richard Rutter</a> — a case study of using <a href="https://utopia.fyi/">utopia.fyi</a> to implement fluid typography with custom CSS properties.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/menus-toasts-and-more/">“Menus, toasts and more with the Popover API, the dialog element, invokers, anchor positioning and <code>@starting-style</code>”</a> by <a href="https://fullystacked.net/">Ollie Williams</a> — an article about all the new features we will have in the future to work with popovers and dialogs which outlines many aspects we need to consider when implementing them.</p>
</li>
<li>
<p><a href="https://chenhuijing.com/blog/the-value-of-live-web-design/">“The value of live web design”</a> by <a href="https://chenhuijing.com/">Chen Hui Jing</a> — a post about designing live in the browser, and a list of CSS properties that might be helpful to learn and apply when doing it.</p>
</li>
<li>
<p><a href="https://kittygiraudel.com/2024/02/26/css-only-bottom-anchored-scrolling-area/">“CSS-only bottom-anchored scrolling area”</a> by <a href="https://kittygiraudel.com/">Kitty Giraudel</a> — a short post about two ways of making scrolling containers start from bottom. One of them was new to me: I did not know that using <code>flex-direction: column-reverse</code> did work like that!</p>
</li>
<li>
<p><a href="https://webkit.org/blog/15054/an-html-switch-control/">“An HTML Switch Control”</a> by <a href="https://annevankesteren.nl/">Anne van Kesteren</a> and <a href="https://github.com/jdatapple">Jon Davis</a> — a post about the new switch control introduced in Safari 17.4.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112043435672437522">on Mastodon</a>!</p>Recent CSS Bookmarks 15https://blog.kizu.dev/recent-css-bookmarks-015/https://blog.kizu.dev/recent-css-bookmarks-015/A compilation of 23 articles and posts about various topics: colors and themes, container queries, accessibility, grids, future CSS, and more.Thu, 04 Apr 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Follow The Compass — Mountains</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="first-things-first">First things first</h2>
<ol>
<li>
<p>I think it is obvious that the “weekly” format just doesn’t work for me: sometimes there are gaps, I don’t want to always publish on the same day, and so on. Moreover, I ended up sharing predominantly the more recent articles and posts I read, rather than some of the more archived ones, so replacing the “weekly” with “recent” makes sense.</p>
</li>
<li>
<p>While it <em>was</em> a month since <a href="/weekly-bookmarks-014/">the last bookmarks post</a>, I don’t want it to be <em>monthly</em>, but something that I post more often.</p>
</li>
<li>
<p>Almost always, my bookmarks are all about CSS. This will continue, and it should be ok to just put this into the “series” name. I could still include other topics, but the main topic will be CSS. And for bigger compilations like this one, I could always add sub-categories.</p>
</li>
<li>
<p>Some other people have a separate category on their sites where they share bookmarks one by one, or automatically publish groups of them. For me, at least for now, it is more enjoyable to have a more curated list in the way I’m doing it. Maybe I <em>will</em> do something differently in the future, we’ll see.</p>
</li>
</ol>
<p>Now, to the bookmarks themselves, 23 of them this time.</p>
<h2 id="colors-and-themes">Colors and Themes</h2>
<p>I gathered four links about colors and themes that compliment each other.</p>
<ul>
<li>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors">“Using relative colors”</a> by <a href="https://millsdocs.com/">Chris Mills</a> — a new MDN guide to relative colors in CSS, which are currently available in Chrome and Safari, but not in Firefox.</p>
</li>
<li>
<p><a href="https://developer.mozilla.org/en-US/blog/color-palettes-css-color-mix/">“Creating color palettes with the CSS <code>color-mix()</code> function”</a> by <a href="https://michellebarker.co.uk/">Michelle Barker</a> — in contrast to the previous guide, this article is about <code>color-mix()</code> which is newly available in all major browsers for around a year already.</p>
</li>
<li>
<p><a href="https://web.dev/articles/light-dark">“CSS color-scheme-dependent colors with <code>light-dark()</code>”</a> by <a href="https://www.bram.us/">Bramus</a> — a post about two ways to handle light and dark colors: via <code>Canvas</code> and <code>CanvasText</code> keywords, and via a <code>light-dark()</code> function.</p>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2024/03/setting-persisting-color-scheme-preferences-css-javascript/">“Setting And Persisting Color Scheme Preferences With CSS And A ‘Touch’ Of JavaScript”</a> by <a href="https://www.olets.dev/">Henry Bley-Vroman</a> — an article about using <code>:has()</code> for <code>:checked</code> <code><select></code>’s <code><option></code>s as a way to change the page’s color scheme.</p>
</li>
</ul>
<h2 id="container-queries">Container Queries</h2>
<p>All aspects of them, including container query length units and style queries!</p>
<ul>
<li>
<p><a href="https://ishadeed.com/article/css-container-query-guide">“An Interactive Guide to CSS Container Queries”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — a detailed article about the basics of container queries with many interactive examples. And multiple non-card use cases! I particularly liked <a href="https://ishadeed.com/article/css-container-query-guide#dynamic-timeline-layout">one timeline example</a> that combines a regular container query with a style query applied via a <code>:has()</code> quantity selector.</p>
</li>
<li>
<p><a href="https://thathtml.blog/2024/03/superpowered-container-style-queries/">“Add Superpowers to Your CSS Variables with Style Queries”</a> by <a href="https://thathtml.blog/">Jared White</a> — a post about one use case for container style queries, where we could use them for reusable media query values, among other things.</p>
</li>
<li>
<p><a href="https://knowler.dev/blog/algorithmic-functional-css">“Algorithmic Functional CSS”</a> by <a href="https://knowler.dev/">Nathan Knowler</a> — a post about using algorithms that let the browsers provide inputs to them, with an example of a dynamic spacing scale based on container query length units.</p>
</li>
</ul>
<h2 id="accessibility">Accessibility</h2>
<p>A few articles about various aspects of CSS in relation to accessibility.</p>
<ul>
<li>
<p><a href="https://hidde.blog/popover-accessibility/">“On popover accessibility: what the browser does and doesn’t do”</a> by <a href="https://hidde.blog/">Hidde de Vries</a> and <a href="https://www.scottohara.me/">Scott O’Hara</a> — an article about the ways Popover API interacts with accessibility of the popovers and their associated buttons.</p>
</li>
<li>
<p><a href="https://textlab.dev/posts/data-attributes-and-text-effects">“The problem with data-attributes for text effects”</a> by <a href="https://mandy.dev/">Mandy Michael</a> — a post advising against using <code>content</code> property with <code>attr()</code> to get a duplicated text due to potential accessibility issues.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/you-want-border-color-transparent-not-border-none/">“You Want <code>border-color: transparent</code>, Not <code>border: none</code>”</a> by <a href="https://daverupert.com/">Dave Rupert</a> — a post about an important aspect of styling borders (or absence of them) accessibly with the <code>forced-colors</code> mode in mind.</p>
</li>
<li>
<p><a href="https://mikemai.net/blog/2024/03/25/the-case-for-defining-base-font-size.html">“The Case for Defining Base Font-size”</a> by <a href="https://mikemai.net/">Mike Mai</a> — a post about <em>not</em> using absolute units for the <code>font-size</code> on the root of your document, and a way to ensure this with CSS layers.</p>
</li>
</ul>
<h2 id="grids">Grids</h2>
<p>Ok, just two articles, but I just wanted to have a section for them. Grids are cool.</p>
<ul>
<li>
<p><a href="https://9elements.com/blog/building-a-rock-solid-auto-grid/">“Building a Rock Solid Auto Grid”</a> by <a href="https://ichimnetz.com/">Nils Binder</a> — an article that goes step-by-step over a creation of a customizable grid, combining multiple CSS grid aspects.</p>
</li>
<li>
<p><a href="https://noahliebman.net/2024/03/making-room-for-long-list-markers-with-subgrid/">“Making room for long list markers with subgrid”</a> by <a href="https://noahliebman.net/">Noah Liebman</a> — a post about how we can use subgrids to style lists in a way that will accommodate markers of any length.</p>
</li>
</ul>
<h2 id="future-css">Future CSS</h2>
<p>Things that are not available in all browsers, but, hopefully, will be soon. Some of them could be used as a progressive enhancement, some of them — not.</p>
<ul>
<li>
<p><a href="https://frontendmasters.com/blog/what-you-need-to-know-about-modern-css-spring-2024-edition/">“What You Need to Know about Modern CSS (Spring 2024 Edition)”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — while this compilation contains some things that are newly available in all major browsers today, many of these can be still tricky to use in production. Overall, a good summary of what CSS will allow us to do in the future.</p>
</li>
<li>
<p><a href="https://nerdy.dev/steal-this-popover-starter-kit">“Steal this popover code”</a> by <a href="https://nerdy.dev/">Adam Argyle</a> — a post about a way to animate the entry and exit states of a popover via discrete display and overlay transitions, as well as a <code>@starting-style</code> rule.</p>
</li>
<li>
<p><a href="https://robinrendle.com/the-cascade/017-how-to-kill-the-cascade/">“How to Kill the Cascade”</a> by <a href="https://robinrendle.com/">Robin Rendle</a> — an article describing one way to isolate the styles of some element in the light DOM by using an implicit <code>@scope</code> and <code>all: revert-layer</code>.</p>
</li>
<li>
<p><a href="https://utilitybend.com/blog/animating-clip-paths-on-scroll-with-at-property-in-css">“Animating clip paths on scroll with <code>@property</code> in CSS”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — an article about using scroll-driven animations for complex <code>clip-path()</code> that use multiple CSS variables.</p>
</li>
</ul>
<h2 id="everything-else">Everything Else</h2>
<p>These cover so many topics! I could probably spend more time thinking about how I could put these into different boxes as well, but oh well!</p>
<ul>
<li>
<p><a href="https://www.smashingmagazine.com/2024/03/modern-css-tooltips-speech-bubbles-part2/">“Modern CSS Tooltips And Speech Bubbles (Part 2)”</a> by <a href="https://css-articles.com/">Temani Afif</a> — a continuation of the article about doing speech bubbles with <code>border-image</code> and <code>clip-path</code>, this time making things more complicating as a way to solve having a border on the tooltips that goes continuously around the tooltip’s tip, solves via pseudo-elements and some math.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/some-little-ways-im-using-css-has-in-the-real-world/">“Some little ways I’m using CSS <code>:has()</code> in the real world”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a post with several examples of how <code>:has()</code> can be used to solve various practical problems.</p>
</li>
<li>
<p><a href="https://dbushell.com/2024/03/10/css-button-styles-you-might-not-know/">“CSS Button Styles You Might Not Know”</a> by <a href="https://dbushell.com/">David Bushell</a> — a post about a few not very common things that can be used to adjust the button styles.</p>
</li>
<li>
<p><a href="https://web.archive.org/web/20251001101641/https://weblog.anniegreens.lol/2024/03/creating-3x5-pics">“Creating 3x5.pics”</a> by <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a> — a case study for a specific index card blog design, using properties as <code>aspect-ratio</code>, <code>text-orientation</code> among more regular flex and grids, and describing the thought process behind some design and tech decisions.</p>
</li>
<li>
<p><a href="https://front-end.social/@[email protected]/112138741731168637">“Pure CSS element distortion (flattened 3D skew with <code>matrix3d()</code>)”</a> by <a href="https://thebabydino.github.io/">Ana Tudor</a> — a StackOverflow answer and a CodePen demonstration of a way to get a trapezoid transformation for an element by using a flattened 3D transform.</p>
</li>
<li>
<p><a href="https://cssence.com/2024/aspect-ratio-gotcha/">“<code>aspect-ratio</code> Gotcha!”</a> by <a href="https://cssence.com/">Matthias Zöchling</a> — a blog post about <code>aspect-ratio</code> in relation to images, and one aspect of it related to their dimensions explicitly set in the HTML attributes.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112211957177759204">on Mastodon</a>!</p>Recent CSS Bookmarks 16https://blog.kizu.dev/recent-css-bookmarks-016/https://blog.kizu.dev/recent-css-bookmarks-016/Another big batch of CSS bookmarks: more than a month worth of them. As usual, with that number of them (32!), I grouped them into eight sections: Colors and Themes, CSS Layouts, Typography, Future CSS, Selectors, Shapes and Effects, Everything Else and My Articles.Sat, 18 May 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Every Gentle Air — The Sower</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><p>Another big batch of CSS bookmarks: more than a month worth of them. As usual, with that number of them (32!), I grouped them into eight sections.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="colors-and-themes">Colors and Themes</h2>
<ul>
<li>
<p><a href="https://lea.verou.me/blog/2024/contrast-color/">“On compliance vs readability: Generating text colors with CSS”</a> by <a href="https://lea.verou.me/">Lea Verou</a> — a detailed article about a technique that uses the relative color syntax to approximate the future <code>color-contrast()</code> function.</p>
</li>
<li>
<p><a href="https://noahliebman.net/2024/04/recursion-in-the-stylesheet/">“Recursion! In the stylesheet”</a> by <a href="https://noahliebman.net/">Noah Liebman</a> — an article about how we can use <code>color-mix()</code> to retrieve some color from a specific point in any linear-gradient, using recursively nested <code>color-mix()</code> for more complex cases.</p>
</li>
<li>
<p><a href="https://web.archive.org/web/20241109001336/https://weblog.anniegreens.lol/2024/04/what-ive-learned-about-css-color-scheme-and-system-color">“What I’ve learned about CSS <code>color-scheme</code> and friends.”</a> by <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a> — a detailed post about how she did set up light and dark mode in her blogs.</p>
</li>
<li>
<p><a href="https://web.archive.org/web/20240917002044/https://weblog.anniegreens.lol/2024/05/css-color-modules-and-changes-part-i">“CSS Color Modules and Changes, Part I”</a> by <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a> — a compilation of information about various color features, new and old, with some thoughts around them.</p>
</li>
<li>
<p><a href="https://www.bram.us/2024/04/13/what-if-you-had-real-control-over-light-mode-dark-mode-on-a-per-site-basis/">“What if you had real control over Light Mode / Dark Mode on a per-site basis?”</a> by <a href="https://www.bram.us/">Bramus</a> — a post about the experimental Web Preferences API and a Chrome extension Bramus did create that allows to use this API to switch between themes on sites that support them. Hopefully, browsers will provide this natively — I too think that it is the job for the browser to provide controls for changing themes, similarly to how it provides control over the font-size and zoom.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/dark-and-light/">“What’s Going On in Dark Theme / Light Theme Land”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post with some thoughts and links (including those two above) about theming and scheming.</p>
</li>
</ul>
<h2 id="css-layouts">CSS Layouts</h2>
<p>This month is full of talks about the future of CSS “Masonry” layout. There is a prototype implementation in Safari and Firefox, and an alternative proposal from the Chrome team. Both sides did post their posts presenting their arguments, and asking for the developer feedback in the CSSWG issues. It is a lot!</p>
<ul>
<li>
<p><a href="https://webkit.org/blog/15269/help-us-invent-masonry-layouts-for-css-grid-level-3/">“Help us invent CSS Grid Level 3, aka ‘Masonry’ layout”</a> by <a href="https://jensimmons.com/">Jen Simmons</a> — an article by the WebKit team, asking many questions, and providing multiple masonry use cases.</p>
</li>
<li>
<p><a href="https://developer.chrome.com/blog/masonry">“An alternative proposal for CSS masonry”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> — an article from Chrome’s team, explaining their alternative proposal.</p>
</li>
</ul>
<p>Masonry was not the only layout-related topic in the last month, there were some other articles as well.</p>
<ul>
<li>
<p><a href="https://cruncher.ch/blog/printing-music-with-css-grid/">“Printing music with CSS Grid”</a> by <a href="https://stephen.band/">Stephen Band</a> — an article about using CSS grids to create a layout for music sheets. I don’t agree with the choice of using data-attributes to pass data to CSS (inline styles and custom properties are a much better choice), but otherwise a nice approach to an unusual use case.</p>
</li>
<li>
<p><a href="https://ishadeed.com/article/tree-view-css-indent/">“Handling The Indentation of a Treeview Component”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — a post with an exploration of several implementations of nested tree lists, specifically, how spacing was done in them.</p>
</li>
</ul>
<h2 id="typography">Typography</h2>
<ul>
<li>
<p><a href="https://shkspr.mobi/blog/2024/04/use-css-to-boost-the-font-size-of-emoji-with-no-extra-markup/">“Use CSS to boost the font size of emoji with no extra markup”</a> by <a href="https://shkspr.mobi/">Terence Eden</a> — a post about how we can modify some font parameters by applying a <code>unicode-range</code> to a <code>@font-face</code>, with an example of emoji fonts and changing their size while not affecting other typefaces.</p>
</li>
<li>
<p><a href="https://mastodon.social/@mikemai2awesome/112321479276047465">“One line of CSS to make San Francisco more accessible”</a> by <a href="https://mikemai.net/">Mike Mai</a> — a post and a CodePen about how it is possible to apply stylistic alternates to a font (if it provides them) to make it more accessible. Only some fonts will provide this as an option, and there are some alternative ways to do the same mentioned in the thread.</p>
</li>
<li>
<p><a href="https://pimpmytype.com/web-safe-fonts/">“Are Web-Safe Fonts still relevant in 2024?”</a> by <a href="https://pimpmytype.com/">Oliver Schöndorfer</a> — a post about how the old concept of “web-safe fonts” cannot be applied today, especially due to which fonts are available on the popular mobile platforms.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/multiplexed-fonts-have-a-cool-superpower/">“‘Multiplexed’ Fonts Have a Cool Superpower”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post about multiplexed fonts and how they can be used in places where we could want some dynamic font feature’s change not result in a layout change.</p>
</li>
<li>
<p><a href="https://georgefrancis.dev/writing/fluid-design-with-css-round/">“Fluid Design with CSS Round”</a> by <a href="https://georgefrancis.dev/">George Francis</a> — a post about one use-case for a <code>round()</code> function for a dynamic line-height that conforms to a certain grid.</p>
</li>
</ul>
<h2 id="future-css">Future CSS</h2>
<ul>
<li>
<p><a href="https://yuanchuan.dev/time-based-css-animations">“Time-based CSS Animations”</a> by <a href="https://yuanchuan.dev/">Yuan Chuan</a> — an article about how we could use transitions on the registered custom properties to create a timer which could be used as the source for transitions and animations. <code>@property</code> is <em>almost</em> here, and with it so many of different techniques, including this one!</p>
</li>
<li>
<p><a href="https://developer.chrome.com/blog/anchor-positioning-api?hl=en">“Introducing the CSS anchor positioning API”</a> by <a href="https://una.im/">Una Kravets</a> — a detailed article about anchor positioning in the state it is shipping in Chrome 125.</p>
</li>
</ul>
<h2 id="selectors">Selectors</h2>
<ul>
<li>
<p><a href="https://www.smashingmagazine.com/2024/05/combining-css-has-html-select-conditional-styling/">“Combining CSS <code>:has()</code> And HTML <code><select></code> For Greater Conditional Styling”</a> by <a href="https://amitsh.com/">Amit Sheen</a> — an article about how we can style things based on the value of some select using the <code>:has()</code> and other selectors in combination with it.</p>
</li>
<li>
<p><a href="https://heydonworks.com/article/testing-html-with-modern-css/">“Testing HTML With Modern CSS”</a> by <a href="https://heydonworks.com/">Heydon Pickering</a> — a post about how we can use complex CSS selectors to visually highlight various issues in HTML.</p>
</li>
<li>
<p><a href="https://scottjehl.com/posts/wordleish/">“How would you build Wordle with just HTML & CSS?”</a> by <a href="https://scottjehl.com/">Scott Jehl</a> — a post presenting one way we could use form validation selectors to approach building a Wordle clone.</p>
</li>
<li>
<p><a href="https://www.bram.us/2024/05/05/misconceptions-about-css-specificity/">“Misconceptions about CSS Specificity”</a> by <a href="https://www.bram.us/">Bramus</a> — a post explaining a few things people often misunderstand in relation to specificity.</p>
</li>
<li>
<p><a href="https://cssence.com/2024/superior-range-syntax/">“Superior Range Syntax”</a> by <a href="https://cssence.com/">Matthias Zöchling</a> — a post about how the new syntax for container and media queries allows for more precise and reliable comparisons.</p>
</li>
</ul>
<h2 id="shapes-and-effects">Shapes and Effects</h2>
<ul>
<li>
<p><a href="https://www.smashingmagazine.com/2024/05/modern-guide-making-css-shapes/">“The Modern Guide For Making CSS Shapes”</a> by <a href="https://css-articles.com/">Temani Afif</a> — an article with an impressive collection of different shapes and descriptions of how to achieve them in CSS, including many useful tricks and explanations for some of the trigonometry that frequently goes with them.</p>
</li>
<li>
<p><a href="https://verpex.com/blog/website-tips/css-tricks-to-master-the-clip-path-property">“CSS Tricks To Master The <code>clip-path</code> Property”</a> by <a href="https://css-articles.com/">Temani Afif</a> — an article presenting one good way to approach the <code>clip-path</code>’s <code>polygon()</code> value by always starting from a rectangle.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/things-that-can-break-aspect-ratio-in-css/">“Things That Can Break <code>aspect-ratio</code> in CSS”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post with an overview of different things that could “break” the <code>aspect-ratio</code> property’s effect in CSS.</p>
</li>
<li>
<p><a href="https://front-end.social/@[email protected]/112401133828751625">“Pure CSS halftone effect in 3 declarations”</a> by <a href="https://thebabydino.github.io/">Ana Tudor</a> — a thread about a technique to achieve the halftone effect by overlaying gradients and using a contrast filter on them, with multiple live examples.</p>
</li>
</ul>
<h2 id="everything-else">Everything Else</h2>
<ul>
<li>
<p><a href="https://kilianvalkhof.com/2024/css-html/your-page-cant-change-media-features/">“Your page can’t change media features”</a> by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a> — a post about one important aspect of how media queries work, and how the page itself will never change them (yet).</p>
</li>
<li>
<p><a href="https://fullystacked.net/prefix/">“The slow death of CSS vendor prefixes”</a> by <a href="https://fullystacked.net/">Ollie Williams</a> — a post about how even though modern browsers stopped introducing new prefixes for properties and values, some of them are still necessary for achieving some effects that do not yet have a more standard implementation.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/chill-scroll-snapping-article-headers/">“Chill Scroll Snapping: Article Headers”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post about an idea to use scroll-snap for snapping headers. Not sure the <code>mandatory</code> is the best choice there, but I can see a case for optional snapping in some designs.</p>
</li>
</ul>
<h2 id="my-articles">My Articles</h2>
<p>I did publish three articles on my main site in April:</p>
<ul>
<li>
<p><a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a> — an article about a technique where we can use <code>@layer</code>, <code>rever-layer</code> and cyclic toggles to create reusable CSS mixins.</p>
</li>
<li>
<p><a href="https://kizu.dev/alternating-style-queries/">“Alternating Style Queries”</a> — an article about a technique using container style queries that allows us to alternate some styles based on their nesting.</p>
</li>
<li>
<p><a href="https://kizu.dev/self-modifying-variables/">“Self-Modifying Variables: the <code>inherit()</code> Workaround”</a> — an article with a technique based on the one described in the previous article that allows us to use style queries as a way to implement something similar to the <code>inherit()</code> function.</p>
</li>
</ul>
<p>If you did miss any of them, I highly recommend you to check them out.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112462640651862311">on Mastodon</a>!</p>Custom Properties and CSS-Wide Keywordshttps://blog.kizu.dev/variables-and-css-wide-keywords/https://blog.kizu.dev/variables-and-css-wide-keywords/I did some tests with custom properties in CSS, and how they work (or don’t) with the CSS-Wide Keywords (`initial`, `inherit`, `unset`, `revert` and `revert-layer`). As the result, I did create a PR adding a few Web Platform Tests, and opened two bugs in Safari and Firefox.Wed, 19 Jun 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Husking Bee — カナリア</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Recently, my blog feels a bit lonely and sad, I need to write more things that are not <a href="https://blog.kizu.dev/tags/bookmarks/">“Recent CSS Bookmarks”</a> (although, I need to get to the next post of those).</p>
<p>What I want to try (will it work? Who knows!) is to write about things I do more. I did some of that during the last November, but then kinda burnt out on writing so much. Let’s try not to make a schedule out of this, but just write about things that, I think, could be interesting. Here is what I did at the beginning of this week!</p>
<p>I did some tests with <a href="https://drafts.csswg.org/css-variables/">custom properties in CSS</a>, and how they work (or don’t) with the <a href="https://drafts.csswg.org/css-cascade-5/#defaulting-keywords">CSS-Wide Keywords</a> (<a href="https://www.w3.org/TR/css-values-3/#common-keywords"><code>initial</code>, <code>inherit</code> and <code>unset</code></a>, <a href="https://drafts.csswg.org/css-cascade/#valdef-all-revert"><code>revert</code></a> and <a href="https://drafts.csswg.org/css-cascade-5/#revert-layer"><code>revert-layer</code></a>).</p>
<h2 id="the-specs">The Specs</h2>
<p>I invite you to read all the related specs yourself, but I will note a few things related to what I tested:</p>
<ul>
<li>
<p>In theory, there should be no difference if we use a CSS-wide keyword for a regular property, or for a custom one. Here is a quote from <a href="https://drafts.csswg.org/css-variables/#ref-for-css-wide-keywords%E2%91%A0">the <code>css-variables</code> spec</a>:</p>
<blockquote>
<p>The CSS-wide keywords can be used in custom properties, with the same meaning as in any another property.</p>
</blockquote>
</li>
<li>
<p>The note right after this paragraph points towards one important aspect: how we cannot really <em>pass down</em> such keyword through a custom property — it will be applied when the custom property will be defined:</p>
<blockquote>
<p>Note: That is, they’re interpreted at cascaded-value time as normal, and are not preserved as the custom property’s value, and thus are not substituted in by the corresponding variable.</p>
</blockquote>
</li>
<li>
<p>The only way we could apply such a keyword conditionally is via the fallback value of a <code>var()</code>. Here is <a href="https://drafts.csswg.org/css-variables/#ref-for-funcdef-var%E2%91%A2%E2%91%A6">how the spec defines it</a>:</p>
<blockquote>
<p>If a declaration, once all <code>var()</code> functions are substituted in, contains only a CSS-wide keyword (and possibly whitespace), its value is determined as if that keyword were its specified value all along.</p>
</blockquote>
<p>It also provides an example showing the fallback behavior (though with a less-useful <code>initial</code> value):</p>
<blockquote>
<p>Example 14: While a <code>var()</code> function can’t get a CSS-wide keyword from the custom property itself—if you tried to specify that, like <span class="nowrap"><code>--foo: initial; </code></span>, it would just trigger explicit defaulting for the custom property—it can have a CSS-wide keyword in its fallback:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">p</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--does-not-exist</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">); }</span></span></code></pre>
</blockquote>
</li>
</ul>
<h2 id="the-tests">The Tests</h2>
<p>Initially, I did my tests as <a href="https://codepen.io/kizu/pen/rNgpXwL">a CodePen</a>, but then when I saw the results, I decided to write some Web Platform Tests, and opened <a href="https://github.com/web-platform-tests/wpt/pull/46814">a PR adding them</a> (and also <a href="https://github.com/web-platform-tests/wpt/pull/46810">fixed</a> some minor test descriptions that I found when looking for existing tests).</p>
<p>Here is a summary of the results:</p>
<ul>
<li>
<p><strong>Chrome</strong> handles all the cases as expected and as specified.</p>
</li>
<li>
<p><strong>Firefox</strong> failed in 5 out of 30 tests I wrote in WPT. I did open <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1903397">a bug about these in Mozilla’s Bugzilla</a>. I did test in Firefox Nightly — in the current stable version of Firefox there are eleven failures, but as it does not support registered custom properties at all, this is expected (though there as a failure with a <code>revert-layer</code> fallback in an unregistered custom property as well). Notably, all the Nightly failures are related to registered custom properties.</p>
</li>
<li>
<p><strong>Safari</strong> failed in 8 out of 30 tests I wrote in WPT. I did open <a href="https://bugs.webkit.org/show_bug.cgi?id=275629">a bug about these in WebKit’s Bugzilla</a>. There was no difference between the stable version of Safari I tried and its latest Safari Technology Preview. Five of those tests were related to the fallbacks of the unregistered custom properties (basically, all CSS-wide keywords do not work there), and the rest were related to <code>revert-layer</code>.</p>
</li>
<li>
<p>If we were to count tests that succeed in all the latest versions of three major browsers, then it will be 19 out of 30 tests, with 11 total tests failing in at least one browser, two of them failing in both. So, the “Interop” score for this will be around <strong>63%</strong>.</p>
</li>
</ul>
<h2 id="what-does-it-mean">What Does It Mean?</h2>
<ol>
<li>
<p>Main thing: <code>revert-layer</code> is currently cross-browser only when used for non-registered custom properties directly, like <code>--foo: revert-layer</code>. This is still good news, as this means my <a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a> technique works!</p>
</li>
<li>
<p>Fallbacks are very unreliable right now for CSS-wide keywords. <em>However</em>, we can use the <code>unset</code>, <code>revert</code> and <code>inherit</code> values, but only if we will register our variables with <code>inherits: true</code>. Doing so will make them work in Safari, and for stable Firefox it won’t make a difference, as those fallbacks work with unregistered properties anyway.</p>
</li>
<li>
<p>CSS-wide keywords apart from <code>revert-layer</code> work fine for non-registered custom properties, but that’s a rather obvious thing.</p>
</li>
</ol>
<p>Overall, I hope browsers will fix the bugs they currently have, so we will unlock more of the use cases for both the <code>revert-layer</code> keyword, and for registered custom properties.</p>
<h2 id="some-context">Some Context</h2>
<p>In one of the CSS Working Group’s latest face-to-face meetings last week, we did resolve to start working on a native conditional <code>if()</code> function in CSS. I recommend reading the <a href="https://lea.verou.me/blog/2024/css-conditionals/">“Inline conditionals in CSS?”</a> article by <a href="https://lea.verou.me/">Lea Verou</a> if you want to know about it, but an important part in relation to my tests is that as the result we’re focusing more on custom properties, as they will be a big part of those conditionals.</p>
<p>Lea did ask me to look into one weird issue with how fallbacks are applied, and as a result of it she did open an <a href="https://github.com/w3c/csswg-drafts/issues/10455">“Are fallbacks provided for registered properties validated by the CP syntax?”</a> issue in CSSWG GitHub.</p>
<p>Most of my tests were in response to her inquiry (and partially continued some of my earlier tests for my Layered Toggles article).</p>
<h2 id="a-future-technique">A Future Technique</h2>
<p>Initially, I wanted to open another CSSWG issue about adding some way to pass down the CSS-wide keywords and then somehow apply them in-place on either regular properties or on variables, as right now, it is not possible to do it.</p>
<p>However, thinking about it more, the <code>if()</code> could be a viable solution for this: instead of passing a CSS-wide keyword itself, we could pass some ident, like <code>--revert-layer</code>, and then use <code>if()</code> to apply it when necessary!</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.foo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: if(</span></span>
<span class="line"><span style="color:#79B8FF"> style</span><span style="color:#E1E4E8">(--foo: --revert-layer)</span></span>
<span class="line"><span style="color:#E1E4E8"> ? </span><span style="color:#79B8FF">revert-layer</span></span>
<span class="line"><span style="color:#E1E4E8"> : </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--foo</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>A condition like this will check if the variable’s value is some dashed ident, and will apply the actual CSS-wide keyword in-place!</p>
<p>Of course, given all browsers will implement the CSS-wide keywords inside the conditions in the same way they should work with custom properties — and if they won’t, I will write some Web Platform Tests.</p>
<p>And you should try <a href="https://blog.kizu.dev/my-first-web-platform-tests/">doing so too</a>!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112642765721767090">on Mastodon</a>!</p>Recent CSS Bookmarks 17: Layoutshttps://blog.kizu.dev/recent-css-bookmarks-017/https://blog.kizu.dev/recent-css-bookmarks-017/More than three months without sharing bookmarks. The backlog of articles to read grew and grew, becoming unmanageable. Instead of trying to go through the whole backlog in one go, I grouped all the bookmarks, and will post them group-by-group. Today, it is all about layouts.Sun, 11 Aug 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>This is The Kit — Two Wooden Spoons</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><p>Oops, more than three months without sharing bookmarks. My excuse: I spoke at CSS Day, and went to a CSS Working Group face-to-face in A Coruña, and then rested for a bit. And then the backlog of articles to read grew and grew, becoming unmanageable.</p>
<p>Instead of trying to go through the whole backlog in one go, I grouped all the bookmarks, and will post them group-by-group.</p>
<p>Today, it is all about layouts.</p>
<ul>
<li>
<p><a href="https://www.oddbird.net/2024/06/13/css-layout/">“Learn Grid Now, Container Queries Can Wait”</a> by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> — a call to start using CSS grids more, as they’re already available for quite a long time, and are very cool. Use them.</p>
</li>
<li>
<p><a href="https://ishadeed.com/article/the-gap/">“The Gap”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — an article about the history of how we used <code>margin</code> property in the past, and how the <code>gap</code> property in flex and grid layouts eliminates many pain points of margins.</p>
</li>
<li>
<p><a href="https://ishadeed.com/article/css-grid-area/">“CSS Grid Areas”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — a deep exploration of how grid areas work, with many interactive examples and use cases.</p>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2024/05/modern-css-layouts-no-framework-needed/">“Modern CSS Layouts: You Might Not Need A Framework For That”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — an article about four reusable and configurable layouts based on CSS flex and grid modules.</p>
</li>
<li>
<p><a href="https://9elements.com/blog/responsive-bar-charts-in-html-and-css/">“Responsive bar charts in HTML and CSS”</a> by <a href="https://molily.de/">Mathias Schäfer</a> — a case-study of migrating a chart built with SVG to HTML&CSS as a way to make it responsive, with the help of a CSS grid layout, including using subgrids and logical properties.</p>
</li>
<li>
<p><a href="https://thoughtbot.com/blog/absolute-positioning-with-css-grid">“Absolute positioning with CSS grid”</a> by <a href="https://www.elainanatario.com/">Elaina Natario</a> — a post about one useful aspect of CSS grids: an ability to place elements into overlapping areas, either fully reusing the same grid area, or create intersecting ones.</p>
</li>
<li>
<p><a href="https://csscade.com/in-defense-of-asymmetric-grids/">“In defense of asymmetric grids”</a> by <a href="https://robinrendle.com/">Robin Rendle</a> — a short post about how CSS grids allow us to have any grids we want and not just a common 12-columns one (which is still effortless to do with them).</p>
</li>
<li>
<p><a href="https://www.viget.com/articles/fluid-breakout-layout-css-grid/">“Fluid Breakout Layout with CSS Grid”</a> by <a href="https://nathan-long.com/">Nathan Long</a> — an article about how we can set up a complex grid with many defined grid lines that allow us to create complex breakout layouts. It defines the lines using <code>grid-template-columns</code>, which, in my opinion, is a bit cumbersome, so I invite you to also look at my old <a href="https://kizu.dev/grid-projection-naming/">“Grid Projection Naming”</a> article about how we can use <code>grid-template-areas</code> to simplify this.</p>
</li>
<li>
<p><a href="https://noahliebman.net/2024/05/yet-another-take-on-layout-breakouts/">“Yet another take on layout breakouts”</a> by <a href="https://noahliebman.net/">Noah Liebman</a> — a post about another way to do simple breakout layouts by using negative margins and <code>max-inline-size</code>.</p>
</li>
<li>
<p><a href="https://developer.chrome.com/blog/reading-flow-display-contents">“Request for developer feedback on <code>reading-flow</code> and elements with <code>display: contents</code>”</a> by <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> — a post about the property previously drafted as <code>reading-order-items</code>, its current status and a call for feedback over how it should work with <code>display: contents</code>.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/lets-make-a-floating-button-sign-up-form-pattern/">“Let’s make a floating button sign up form pattern”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a case study of creating a micro-layout for an input+button pattern, going into numerous nuances related to accessibility and responsiveness related to it.</p>
</li>
<li>
<p><a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> by me — while it is not really about layouts, this technique uses flexbox inside, as a workaround for not being able to apply container query to an element with an intrinsic width.</p>
</li>
</ul>
<hr>
<p>If I missed something you wrote, or if you saw something else about CSS layouts that I did omit, but you found interesting, — you are always welcome to send links my way.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/112945436008988993">on Mastodon</a>!</p>Querying the Color Schemehttps://blog.kizu.dev/querying-the-color-scheme/https://blog.kizu.dev/querying-the-color-scheme/Media queries are nice, but for many things, we don’t even need them: there is this great CSS property `color-scheme`, which allows us to make various things adapt to the current color scheme. We can even set it on a per-element basis. This post describes how we can use registered custom properties and style queries to read the current value of a `light-dark()` color for styling any non-color properties as well.Thu, 29 Aug 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — Dust Collects</dd><dt>Current drink:</dt><dd>Lemongrass, Ginger & Black Pepper tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Media queries are nice: they allow us to query different features, like the <a href="https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme"><code>prefers-color-scheme</code></a> one, which allows us to get the user preference and switch some styles between light and dark themes.</p>
<p>For many things, we don’t even need the media queries themselves: there is this great CSS property <a href="https://drafts.csswg.org/css-color-adjust/#color-scheme-prop"><code>color-scheme</code></a>. If we set it on the root like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:root</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#79B8FF"> dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Many things in our page will automatically adapt to the user’s color-scheme:</p>
<div class="aside-wrapper" style="grid-row-end: span 3">
<aside>
If you would like to learn more, I can recommend reading these articles that I previously shared in my [bookmarks posts](/tags/bookmarks/):
- [“CSS color-scheme-dependent colors with `light-dark()`”](https://web.dev/articles/light-dark) by [Bramus](https://www.bram.us/).
- [“What I’ve learned about CSS `color-scheme` and friends”](https://web.archive.org/web/20241109001336/https://weblog.anniegreens.lol/2024/04/what-ive-learned-about-css-color-scheme-and-system-color) by [Anne Sturdivant](https://web.archive.org/web/20241214222059/https://anniegreens.lol/).
</aside>
</div>
<ul>
<li>Built-in UI elements: scrollbars, inputs, buttons.</li>
<li>Some <a href="https://drafts.csswg.org/css-color/#css-system-colors">system colors</a>: for example, <code>Canvas</code> and <code>CanvasText</code>.</li>
<li>The built-in <a href="https://drafts.csswg.org/css-color-5/#light-dark"><code>light-dark()</code></a> function, which accepts two colors and returns the first one when the theme is light, and the second one otherwise.</li>
</ul>
<h2 id="adapting-tothe-user-preference">Adapting to the User Preference</h2>
<p>By providing both possible schemes: “<code>light dark</code>” to the <code>color-scheme</code>, we tell the browser that it is ok to adapt to one of those themes that matches the user preference. The example below should adapt to the color-scheme you’re using in your browser:</p>
<style>{`
figure p {
margin: 0;
}
`}</style>
<p><a href="https://blog.kizu.dev/querying-the-color-scheme/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#79B8FF"> dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: Canvas;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: CanvasText;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8"> light-dark(</span><span style="color:#79B8FF">hotpink</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @media</span><span style="color:#E1E4E8"> (prefers-color-scheme: light) {</span></span>
<span class="line"><span style="color:#B392F0"> .dark-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> @media</span><span style="color:#E1E4E8"> (prefers-color-scheme: dark) {</span></span>
<span class="line"><span style="color:#B392F0"> .light-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example1"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>I should adapt. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>We can see how everything — the <code>light-dark()</code>, the <code>Canvas</code> & <code>CanvasText</code> and the media queries — adapts to the current scheme.</p>
<h2 id="enforcing-a-color-scheme">Enforcing a <code>color-scheme</code></h2>
<p>But what if we will set only one value?</p>
<p><a href="https://blog.kizu.dev/querying-the-color-scheme/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example2--light</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> & * {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example2--dark</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> & * {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: Canvas;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: CanvasText;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8"> light-dark(</span><span style="color:#79B8FF">hotpink</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @media</span><span style="color:#E1E4E8"> (prefers-color-scheme: light) {</span></span>
<span class="line"><span style="color:#B392F0"> .dark-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> @media</span><span style="color:#E1E4E8"> (prefers-color-scheme: dark) {</span></span>
<span class="line"><span style="color:#B392F0"> .light-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2 example2--light"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>I should be always light. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2 example2--dark"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>I should be always dark. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<div class="aside-wrapper">
<aside class="warning">
Two notes about browser compatibility here:
<ul>
<li>Firefox has <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1914735">a bug</a> where it does not apply the <code>color-scheme</code> correctly for consecutive elements, so we have to specify it not just on the wrapper, but also for everything nested inside. Note that this workaround makes it so we can’t nest our themes. But, in general, it would work if not for the Firefox.</li>
<li>Safari supports <code>light-dark()</code> only starting from 17.5, so the border won’t be visible in the current stable version.</li>
</ul>
</aside>
</div>
<p>While system colors and <code>light-dark()</code> applied according to our <code>color-scheme</code>, we can’t change the media query from our CSS. It just tells us what is the <em>user preference</em>.</p>
<p>The <code>light-dark()</code> itself is very useful, but can only be used for things that expect an actual CSS <code><color></code> type. But what if we’d want to adapt other, non-color things?</p>
<p>We can work around this by using something different as the source of truth, like CSS scopes or style queries. I recommend reading the recent <a href="https://nerdy.dev/page-and-component-light-dark-strategies">“Page and Component Adaptive Light/Dark”</a> post by <a href="https://nerdy.dev/">Adam Argyle</a> about these.</p>
<p>But what if we’d want to use the <code>color-scheme</code> as the source of truth?</p>
<h2 id="single-source-of-truth">Single Source of Truth</h2>
<p>With the <a href="https://drafts.csswg.org/css-conditional-5/#style-container">style queries</a> and <a href="https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule">registered custom properties</a>, we could! Here is how:</p>
<p><a href="https://blog.kizu.dev/querying-the-color-scheme/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example3--light</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3--dark</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --captured-color {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<color</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: true;</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: white;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-color</span><span style="color:#E1E4E8">: light-dark(</span><span style="color:#79B8FF">white</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">black</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: Canvas;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: CanvasText;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8"> light-dark(</span><span style="color:#79B8FF">hotpink</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> @container</span><span style="color:#E1E4E8"> style(--captured-color: white) {</span></span>
<span class="line"><span style="color:#B392F0"> .dark-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> @container</span><span style="color:#E1E4E8"> style(--captured-color: black) {</span></span>
<span class="line"><span style="color:#B392F0"> .light-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example3 example3--light"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>I should be always light. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example3 example3--dark"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>I should be always dark. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<div class="aside-wrapper">
<aside class="warning">
Note that style queries are only available in Chrome and Safari Technology Preview currently, do not rely on them in production.
<p>I am also not using the fix for the Firefox, as style queries do not work there anyway right now.</p>
</aside>
</div>
<p>Here, instead of using media queries, we register a <code>--captured-color</code> custom property, then assign two different values to it using the <code>light-dark()</code> function. Because the property is registered, the function is properly applied, resulting in the corresponding color changing based on the <code>color-scheme</code>.</p>
<p>Then, instead of relying on the <code>prefers-color-scheme</code>, we use a container style query to query this registered custom property, which allows us setting <em>any</em> properties for anything inside the element that defines the <code>color-scheme</code>!</p>
<aside>
When I first tested this, only Safari Technology Preview was handling this case correctly! I [had to open a bug](https://issues.chromium.org/issues/335383222) for Chromium about it, and it was fixed rather quickly.
</aside>
<h3 id="downsides">Downsides</h3>
<p>The main downside of this method (outside the browser support) is the fact that the style queries apply to the elements inside the element with the <code>color-scheme</code>, but the <code>color-scheme</code> changes the styles on the element itself. Unless we’ll get some way to conditionally apply styles on the element itself, we will need to make sure we never style anything on the element with the <code>color-scheme</code>.</p>
<p>And, of course, it is not as intuitive with the container style queries targeting some variable with some abstract values.</p>
<h3 id="not-the-user-preference">Not the User Preference</h3>
<p>In the most recent <a href="https://web-standards.ru/podcast/437/">“Web-Standards podcast”</a> (in Russian), <a href="https://pepelsbey.dev/">Vadim Makeev</a> mentioned a good point: there is a big difference between the user preference and a <code>color-scheme</code> property. Occasionally, it might be alluring to use the <code>color-scheme</code> as a switch for the <em>components’</em> theme, but we need to consider that even when we do so, we could still want to listen to the <code>prefers-color-scheme</code> to understand which theme the user prefers, and make adjustments to both the light and dark themes we’re applying via <code>color-scheme</code>.</p>
<p>For example, if the user prefers the <code>dark</code> color-scheme, and we’re overriding it to <code>light</code> on some inner component, we could want to not just invert the colors there, but also make them not as bright, as in not to make it stand out too much. We might even want to adjust the overall theme based on it if we have the built-in color scheme switch: dim the <code>light</code> one when the user prefers the <code>dark</code> color scheme, and make the <code>dark</code> more contrast if the user has it as <code>light</code>, as otherwise UI elements could be overshined by the bright browser chrome.</p>
<h2 id="the-future">The Future</h2>
<p>I did not find a dedicated issue about this yet, but in <a href="https://github.com/w3c/csswg-drafts/issues/10249">one of the other issues</a> about <code>color-scheme</code> many people did express their desire to have a dedicated style query for this. I imagine it will work very similarly, and potentially have the same downside of not matching with the <code>color-scheme</code>, unless there will be some specific handling implemented that will prevent any circular dependency issues.</p>
<p>The abovementioned issue itself is about the problem where a <code><meta name=color-scheme></code> in HTML does not reflect on the <code>prefers-color-scheme</code> <code>@media</code>. In my opinion, this is the way it should work: I think the <em>user preferences</em> should stay that way, and it is not correct to change it based on the current color scheme, regardless of where it is defined — in HTML or CSS.</p>
<p>This technique (or a potential style query) will solve the issue described in the issue well enough: just apply it on the <code>html</code> or <code>body</code> element and use it instead of the <code>@media</code> itself.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Registered custom properties are powerful in their ability to capture some value on the element itself, rather than passing it down to be applied later. I got the idea to apply it to the <code>light-dark()</code> function when playing with the <code>tan(atan2())</code> technique as a part of my experiments for the <a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> article, and after playing with the style queries for my <a href="https://kizu.dev/self-modifying-variables/">“Self-Modifying Variables: the <code>inherit()</code> Workaround”</a> article.</p>
<div class="aside-wrapper">
<aside>
I published a separate post about the concept of capturing values: [“Captured Custom Properties”](/captured-custom-properties/).
</aside>
</div>
<p>As always, I am fascinated by what we can achieve by combining different CSS features: in this case we rely on three of them together. I hope this post will encourage you to experiment with all the new things in CSS as well, and will give you ideas about how we could use them in other unusual ways.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113045515536244044">on Mastodon</a>!</p>Captured Custom Propertieshttps://blog.kizu.dev/captured-custom-properties/https://blog.kizu.dev/captured-custom-properties/In a few of my latest CSS experiments and articles, I used one naming pattern for registered custom properties that I think worth highlighting in a separate blog post. This pattern allows us to create a set of generic custom properties, covering a wide set of use cases for computing and storing their values.Mon, 02 Sep 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>toe — 風と記憶</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>In a few of my latest experiments and articles (<a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> and <a href="https://blog.kizu.dev/querying-the-color-scheme/">“Querying the Color Scheme”</a>), I used one naming pattern for registered custom properties that I think worth highlighting in a separate blog post.</p>
<p>Registered custom properties are invaluable, as they unlock many things previously not possible.</p>
<p>Among other use cases (I recommend reading the <a href="https://moderncss.dev/providing-type-definitions-for-css-with-at-property/">Providing Type Definitions for CSS with @property</a> article by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a>), there are two useful effects we can use registered custom properties for:</p>
<ul>
<li>Enabling animations of some custom property.</li>
<li><em>Capturing</em> the value of the custom property on the element itself.</li>
</ul>
<p>The use case for animations is rather obvious, but the capturing one can be harder to wrap your head around.</p>
<h3 id="regular-custom-properties">Regular Custom Properties</h3>
<p>By default, regular custom properties have their computed value as “<a href="https://drafts.csswg.org/css-cascade-5/#specified">specified value</a> with variables substituted”. The <a href="https://drafts.csswg.org/css-variables/#serializing-custom-props">serialization rules</a> for custom properties state:</p>
<blockquote>
<p>Custom property names must be serialized as the exact code point sequence provided by the author, including not altering the case.</p>
<p>Specified values of custom properties must be serialized exactly as specified by the author. Simplifications that might occur in other properties, such as dropping comments, normalizing whitespace, reserializing numeric tokens from their value, etc., must not occur.</p>
<p>Computed values of custom properties must similarly be serialized exactly as specified by the author, save for the replacement of any <code>var()</code> functions.</p>
</blockquote>
<p>So, when we define some custom property, the only thing that happens is the substitution of variables inside. But the actual values will be evaluated only when <em>used</em> on particular elements.</p>
<p>Here is a simple example:</p>
<p><a href="https://blog.kizu.dev/captured-custom-properties/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.666</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example1"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Outer:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Foo</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Inner:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Bar</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Here we can see how we <em>define</em> the <code>--font-size</code> on the wrapper, and then <em>use</em> it on different children. One <code><span></code> is placed right inside our wrapper, but another have an <code>.inner</code> wrapper that changes the font-size to be bigger.</p>
<p>The <code>1.5em</code> from the <code>--font-size</code> custom property is evaluated on the <code><span></code> itself. When it is defined, it does not calculate the <code>em</code> inside, and just passes the value as a code sequence to be applied when it will be used.</p>
<p>Let’s see what will happen if we will register a custom property.</p>
<h3 id="registered-custom-properties">Registered Custom Properties</h3>
<p>The only difference in this example is that we register our custom property, note the font-size of the <code>.inner > span</code> element compared to the regular custom property example.</p>
<p><a href="https://blog.kizu.dev/captured-custom-properties/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --registered-font-size {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<length</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: 0px;</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: true;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.666</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --registered-font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--registered-font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Outer:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Foo</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Inner:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Bar</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>By registering our custom property, the value is now evaluated <em>at the definition</em>, so instead of passing down the abstract <code>1.5em</code>, we now pass down the exact value of the <code>1.5em</code> as calculated on the <code>.example2</code> element!</p>
<p>This is defined in <a href="https://drafts.css-houdini.org/css-properties-values-api/">the spec for the registered custom properties</a>, in a <a href="https://drafts.css-houdini.org/css-properties-values-api/#calculation-of-computed-values">“Computed Value-Time Behavior”</a>.</p>
<p>Many other things will be evaluated in the same way, like almost any calculations (they can’t involve a percentage) or colors. And, as we will see from the <a href="#use-cases">use cases</a>, this can be useful not only when using the inheritance.</p>
<h2 id="the-naming-pattern">The Naming Pattern</h2>
<p>In the above example, I named the custom property <code>--registered-font-size</code>. But is it the best way to name this property? Naming it based on the property it is used for does limit how we can use it. What if we could make it more generic?</p>
<p>In my latest experiments, what I ended up doing is creating a <em>reusable</em> registered custom property, at least one per <em>type</em>.</p>
<p>In this case, the custom property is responsible for capturing the <code><length></code> value, so a better name could be <code>--captured-length</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --captured-length {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<length</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: 0px;</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: true;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>And if we’d want to capture a color, then it would be <code>--captured-color</code>. Integer? <code>--captured-integer</code>, and so on.</p>
<p>In my practice (see the <a href="#use-cases">use cases</a>), most cases require having just a single registered custom property per type on an element. By having a generic reusable property, we make it much easier for us to work with the styles: we no longer need to register many custom properties with the same syntaxes and different names, most of which won’t be used at the same time.</p>
<h3 id="multiple-instances">Multiple Instances</h3>
<p>But edge cases exist: what if we’d want to capture not one <code><length></code> on an element, but multiples of them?</p>
<p>My solution for this is simple: just introduce another registered custom property like <code>--captured-length2</code>.</p>
<p>Of course, this will only work if you control all the styles for your project, as well as the way they’re applied. When designing independent components, we’d want to prefix these names with something related to the component itself, but I still think the best way to name these custom properties is by what they do.</p>
<h3 id="do-we-need-inheritance">Do We Need Inheritance?</h3>
<p>As a matter of habit, I was using <code>inherits: true</code> for these, but I was thinking for a while if we <em>really</em> need to do so.</p>
<p>A recent video <a href="https://www.youtube.com/watch?v=U8NykwZNbGs">“Turning off inheritance on custom props is more useful than I’d thought”</a> by <a href="https://www.kevinpowell.co/">Kevin Powell</a> did remind me of this, and, in our case, I think we can safely make these custom properties non-inheritable.</p>
<p>In the example with the <code>--registered-font-size</code> we had <code>inherits</code> as <code>true</code> because we were using that value on a nested element, inheriting it there. But we can work around this. Here is the same example, but using a non-inheriting <code>--captured-length</code> custom property:</p>
<p><a href="https://blog.kizu.dev/captured-custom-properties/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --captured-length {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<length</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: 0px;</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: false;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.666</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --example-font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--example-font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example3"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Outer:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Foo</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Inner:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Bar</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Here we are using the non-inheriting <code>--captured-length</code> as a way to retrieve the value, but then we save it to another, non-registered custom property that we are free to name as we want.</p>
<p>Because custom properties are <em>replaced</em> when serialized, the <code>--example-font-size</code> will get the computed value right away, and then will be inherited to the inner elements.</p>
<p>This feature allows us to use the same <code>--captured-length</code> property on different nested elements, saving its value into various other custom properties (or using right away), without the need for it to be inherited.</p>
<p>I am not sure if there is a big (if any) performance gain due to this, but I can see how the prevention of inheritance and requiring to save the value into a different custom property can be beneficial. It will reduce the potential confusion if any of the nested elements will be using the inherited <code>--captured-length</code>: where would it get from? A variable with a proper name will be more explicit and expressive.</p>
<h2 id="use-cases">Use Cases</h2>
<p>In my <a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> article, I used this technique four times: <code>--captured-length</code> on three different elements, and also <code>--captured-length2</code> for the optional case fixing the optical adjustment.</p>
<p>In my recent <a href="https://blog.kizu.dev/querying-the-color-scheme/">“Querying the Color Scheme”</a> post, I used a single <code>--captured-color</code> custom property.</p>
<p>Interestingly, there were four different reasons across these five use cases, demonstrating how crucial this technique can be.</p>
<h3 id="detecting-property-support">Detecting <code>@property</code> Support</h3>
<p>For a more graceful fallback in my <a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> article, I use a variation of the <a href="https://www.bram.us/2024/07/03/feature-detect-css-property-support/">“Feature detect CSS <code>@property</code> support”</a> technique by <a href="https://www.bram.us/">Bramus</a>, but instead of registering the <code>--support-sentinel</code> custom property, I reused the <code>--captured-length</code> one:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.text-fit</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --support-sentinel</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">9999</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>When the browser supports <code>@property</code>, the <code>--captured-length</code> will be registered with the <code>initial-value</code> equal to <code>0px</code>, making the <code>--support-sentinel</code> get that value.</p>
<p>But if the browser does not support it, the <code>--support-sentinel</code> would get the value from its provided fallback — <code>9999px</code>.</p>
<h3 id="named-container-query-length-units-workaround">Named Container Query Length Units Workaround</h3>
<p>In the same article, I used the <code>--captured-length</code> to store the value in container query length units, as I wanted to have two different nested containers, and thus couldn’t access the outer one from within:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.text-fit</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & > :not([aria-hidden]) {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --available-space</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & > * {</span></span>
<span class="line"><span style="color:#6A737D"> /* Also using the 100cqi */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>In the future, we will have a way to access the container query length units from any named container, see the <a href="https://github.com/w3c/csswg-drafts/issues/7858">“Reference named containers for cq units”</a> issue by <a href="https://una.im/">Una Kravets</a>, but if we’d want to get them <em>today</em>, then registered custom properties do the job! I actually presented this use case <a href="https://github.com/w3c/csswg-drafts/issues/7858#issuecomment-1484103141">in the comments</a> to this issue in March 2023, though at the time the browser support for registered custom properties was worse, so I did not write about it elsewhere.</p>
<p>If you’re using container query length units often — take a note of this workaround, as you could find many use cases where it could be helpful.</p>
<h3 id="working-around-type-limitations">Working Around Type Limitations</h3>
<p>The third time I used the <code>--captured-length</code> in the same article was to also assign <code>100cqi</code> to it — but for an entirely different reason.</p>
<p>Instead of capturing the value to pass it to the descendant element, I used it as a workaround for the <code>tan(atan2())</code> technique’s issue: at least in Chrome, we cannot use container query length units directly inside the <code>tan(atan2())</code> for some reason.</p>
<p>So, to use the <code>100cqi</code> there, we first had to <em>convert</em> it to what <code>tan(atan2())</code> would understand, which allowed us to calculate the ratio based on it and the <code>--available-space</code> value which we inherited:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.text-fit</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & > :not([aria-hidden]) {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --available-space</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & > * {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --ratio</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">tan</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">atan2</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--available-space</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--available-space</span><span style="color:#E1E4E8">) </span><span style="color:#FFAB70">-</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This example demonstrates how useful it is to have a generic registered custom property: it is used for different purposes, and we didn’t have to register it several times. The second time we used it, we also did not have to name it, as we could use it directly.</p>
<p>The last usage in the same article was also for working around the type limitations when assigning a value to the <code>font-variation-settings</code> property, for which we also had to use the <code>tan(atan2())</code> technique:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.text-fit</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & > :not([aria-hidden]) {</span></span>
<span class="line"><span style="color:#E1E4E8"> & > * {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D"> /* … */</span></span>
<span class="line"><span style="color:#FFAB70"> --font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> 1</span><span style="color:#F97583">em</span><span style="color:#FFAB70"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--ratio</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--max-font-size</span><span style="color:#E1E4E8">, infinity * </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#FFAB70"> -</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--support-sentinel</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &.</span><span style="color:#79B8FF">text-fit</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length2</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> font-variation-settings</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> 'opsz'</span></span>
<span class="line"><span style="color:#79B8FF"> tan</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">atan2</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length2</span><span style="color:#E1E4E8">), </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Here we had to use it on the same element, so we had to introduce the <code>--captured-length2</code> property, and we could also use the value directly, without the name to inherit it or rename.</p>
<p>There are many other similar use cases, where we can use a registered custom property to overcome the typing limitations. Knowing how to solve them effectively allows us to use this powerful <code>tan(atan2())</code> technique, so I will highly recommend you to read the original article about it by <a href="https://kizu.dev/fit-to-width/">Jane Ori</a> — <a href="https://dev.to/janeori/css-type-casting-to-numeric-tanatan2-scalars-582j">“CSS Type Casting to Numeric: <code>tan(atan2())</code> Scalars”</a>. She also mentions this usage of registered custom properties in her article, but without creating a pattern out of it.</p>
<h3 id="unlocking-style-queries">Unlocking Style Queries</h3>
<p>The last use case is from my other post — <a href="https://blog.kizu.dev/querying-the-color-scheme/">“Querying the Color Scheme”</a>.</p>
<p>This time, I am defining a <code>--captured-color</code> as a way to convert the value returned by <code>light-dark()</code> function to something a container style query could accept:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --captured-color {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<color</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: true;</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: white;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-color</span><span style="color:#E1E4E8">: light-dark(</span><span style="color:#79B8FF">white</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">black</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">container</span><span style="color:#79B8FF"> style</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">white</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#6A737D"> /* … */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> @container</span><span style="color:#E1E4E8"> style(--captured-color: black) {</span></span>
<span class="line"><span style="color:#6A737D"> /* … */</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Although, in this case I did not rename the property, which could’ve been better (although, a bit more awkward: instead of comparing to the values of <code>white</code> and <code>black</code>, we would need to compare to <code>rgb(255, 255, 255)</code> and <code>rgb(0, 0, 0)</code> — the actual values the <code>--captured-color</code> will compute to).</p>
<p>This kind of value conversion could be useful in many other cases involving style queries, normalizing different values, or calculating their value, allowing us to compare the computed values rather than strings of tokens.</p>
<h3 id="other-use-cases">Other Use Cases</h3>
<p>There might be many other use cases for this feature of registered custom properties, and for this technique, and I think I saw it in several recent articles, but can’t remember where exactly. If you’d know of any — throw them my way!</p>
<p>One other potential use case (which I did not try) could be to have another set of generic custom properties for <em>animatable</em> values. So, <code>--animatable-length</code>, <code>--animatable-color</code> and so on, allowing to create reusable <code>@keyframes</code> with them. I did not yet do so, but I feel there is a potential to craft something like that.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I love custom properties, and I feel we’re only scratching the surface of what is possible with the registered version of them.</p>
<p>While we probably should not use them in production just yet (Firefox <a href="https://caniuse.com/mdn-css_at-rules_property">supports them</a> only from version 128), if your use cases work well with graceful degradation, or if you want to experiment with them — I highly recommend you to do so.</p>
<p>I find myself reaching for this naming pattern more and more, and I hope you will find it useful as well. I can see a list of these registered custom properties be in the boilerplate for most of my future projects, and maybe libraries like <a href="https://open-props.style/">Open Props</a> by <a href="https://nerdy.dev/">Adam Argyle</a> would also eventually get something like them from the box.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113068685233016457">on Mastodon</a>!</p>Some Planshttps://blog.kizu.dev/some-plans/https://blog.kizu.dev/some-plans/Guess what? It is November. Last year, I went all out and published one post a day for the full month. On one hand, that was hard, and took its toll on me. On the other, I _did_ publish a bunch of stuff that would usually stay in the drafts. I don’t know if I will manage to do the same this month — but I want to try again.Fri, 01 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>This is The Kit — Inside Outside</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>Guess what? It is November. Last year, I went all out and published one post a day for the full month.</p>
<p>On one hand, that was hard, and took its toll on me. On the other, I <em>did</em> publish a bunch of stuff that would usually stay in the drafts.</p>
<p>I don’t know if I will manage to do the same this month — but I want to try again.</p>
<h2 id="what">What</h2>
<p>One thing I would like to try to do: make this a bit more of a <em>blog</em>. A few months ago, I started writing down weekly notes at my work, and found it to be a good way to track what I did achieve.</p>
<p>And, as I look back, many of last November’s posts were also just that: documenting my bug reports, WPT tests, CSSWG issues.</p>
<p>I need to find a good workflow to document and post stuff like that, and maybe a bit more of personal things, like posting <a href="https://pixey.org/i/web/profile/546076540786363642">photos from the walks</a>, sharing my <a href="https://www.last.fm/user/ki_zu">favorite music</a>, my setup, or just anything else.</p>
<h2 id="next-week">Next Week</h2>
<p>Next week I will attend two things:</p>
<ol>
<li>
<p><a href="https://beyondtellerrand.com/events/berlin-2024">beyond tellerrand</a> conference in Berlin.</p>
</li>
<li>
<p><a href="https://indieweb.org/2024/Berlin">IndieWebCamp</a> after it.</p>
</li>
</ol>
<p>I already have many plans about what I want to do with my website and this blog, and having both of these events to think more about it feels convenient.</p>
<p>While I could only visit the first day of IndieWebCamp, I’ll try to hack on my website during my travel back for the second day.</p>
<h2 id="bookmarks">Bookmarks</h2>
<p>As it is often the case for me with periodic things: I tend to always drop them. Well, as I have written in <a href="https://blog.kizu.dev/recent-css-bookmarks-017/">the latest bookmarks post</a>, the backlog of the bookmarks I gathered is unmanageable!</p>
<p>I’ll try to come up with a better workflow for it, one that would actually <em>work</em> for me.</p>
<p>With me giving up on posting the bookmarks weekly, and the need to write up one post a day in November, I could always share one or two bookmarks as the fallback.</p>
<h2 id="experiments">Experiments</h2>
<p>Is the backlog of my experiments and article drafts is as big as for my bookmarks? Well, maybe not that big, but I have <em>many things</em> brewing in my lab.</p>
<p>I even managed to finally publish <a href="https://kizu.dev/tree-counting-and-random/">“Possible Future CSS: Tree-Counting Functions and Random Values”</a> — an article about some of my experiments that I started <em>last year</em>.</p>
<p>There is more in the works. Nothing is fast when each time I touch some code, a browser bug crawls out of it and crashes the party. Or the browser. Had two of these last month alone!</p>
<h2 id="more-plans">More Plans</h2>
<p>Or, actually, fewer? After starting writing this post, I have so many things I want to share. But: I will have the whole month for it. Nice.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113409393378203907">on Mastodon</a>!</p>Current Musichttps://blog.kizu.dev/current-music/https://blog.kizu.dev/current-music/If you have read any posts in this blog, you might’ve noticed the “Current music” field at the top. This is something I adopted back from when I was using LiveJournal. Until today, it was displayed just as a string. Today, I made it into a proper “category”: if I shared some artist more than once, its name will become a link to the list of all posts that share it.Sat, 02 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Husking Bee — ハイブリッドニューモード</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>If you have read any posts in this blog, you might’ve noticed the “Current music” field at the top. This is something I adopted back from <a href="/lj-20-years/">when I was using LiveJournal</a>. Some of the apps that allowed posting there supported a way to detect what is currently playing in your audio player (likely, <a href="https://en.wikipedia.org/wiki/Winamp">Winamp</a>). Or maybe there was even a <a href="https://www.last.fm/">last.fm</a> integration?</p>
<p>Anyways, that was fun! When I <a href="https://blog.kizu.dev/not-an-ideal-start/">started this blog</a>, one of the reasons was because of the nostalgia for these times, and that’s why I added the “Current music” metadata field, and why I am filling it manually for every post I write here.</p>
<p>Until today, it was displayed just as a string. Today, I made it into a proper “category”: if I shared some artist more than once, its name will become a link to the list of all posts that share it. Why? Well, why not?</p>
<p>I already have some ideas over how I could improve this. For example, it would be nice for every artist who appears twice or more, to add some info over on their category page, with links to their official pages, bandcamps and whatnot.</p>
<p>So, yeah. I listen to a lot of music, of many genres, and I always wanted to share some of it a bit wider. This could be a good way to start doing so! And if you’re curious more about my tastes — feel free to peek over at <a href="https://www.last.fm/user/ki_zu">my last.fm profile</a>. I “scrobble” what I’m listening to for over 18 years now, wow.</p>
<p>This post’s “Current music”, if you’re curious, is from the band that I listened the most to when I started using last.fm in 2006. One member of this band sang the vocal parts for the main character in <a href="https://en.wikipedia.org/wiki/Beck_(manga)">Beck</a> anime — I found this band through it.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113415365792868759">on Mastodon</a>!</p>Embedding Pixelfed, part 1https://blog.kizu.dev/embedding-pixelfed-part-1/https://blog.kizu.dev/embedding-pixelfed-part-1/One of the things I planned for the November: to not do _a lot_ of coding on the weekends, and try to post more personal stuff, keeping more technical stuff for the weekdays. Well, for today’s post I wanted to share some photos, and I started to wonder how I should do this. In the end, it _will_ involve code, but today I was mostly doing some exploration and planning.Sun, 03 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>tricot — E</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>One of the things I planned for the November: to not do <em>a lot</em> of coding on the weekends, and try to post more personal stuff, keeping more technical stuff for the weekdays.</p>
<p>Well, for today’s post I wanted to share some photos, and I started to wonder how I should do this. In the end, it <em>will</em> involve code, but today I was mostly doing some exploration and planning.</p>
<p>I already have <a href="https://pixey.org/i/web/profile/546076540786363642">a Pixelfed account</a>, and I wondered if I want to implement some IndieWeb pattern like <a href="https://indieweb.org/PESOS">“Publish Elsewhere, Syndicate (to your) Own Site”</a> or <a href="https://indieweb.org/POSSE">“Publish (on your) Own Site, Syndicate Elsewhere”</a>.</p>
<p>In the end, I think I will go with neither: I don’t want to have <em>automation</em> just yet, but I still would like to reuse what I post to Pixelfed in one way or another.</p>
<p>My thought process: the photos are already uploaded to Pixelfed, alongside associated alt texts. I don’t need to duplicate the images to my site: I already have the source file locally and with a backup in the cloud. Can I just reuse some stuff from it by using its API, and build some kind of gallery locally as a part of my Astro blog?</p>
<p>I don’t have anything ready just yet, but I wanted to demonstrate my process a bit, by documenting what I did and what I am planning to do.</p>
<h2 id="what-i-already-did">What I Already Did</h2>
<ol>
<li>
<p>One thing I want to do, if I can: hotlink the images from Pixelfed. I tested if it is possible: and, for now, it appears that it is. My blog won’t ever be that popular to make this an issue for my Pixelfed instance, and not having to duplicate the effort of storing the image in multiple places sounds good.</p>
</li>
<li>
<p>I looked into Pixelfed API to understand if I could work easily with it. Unlike <a href="https://docs.joinmastodon.org/client/intro/">Mastodon API</a>, where many things are available without authorization, <a href="https://beta-preview.pixelfed.io/">Pixelfed API</a> <strong>requires</strong> providing a “Personal Access Token” with each request. So, I’ll probably need to have some env variable for this.</p>
</li>
<li>
<p>I tested if the API works by creating this token and requesting one of my posts’ data via its API, while providing the token. I did something like this and it worked:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="ts"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">fetch</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`https://pixey.org/api/v1/statuses/${</span><span style="color:#E1E4E8">id</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">, {</span></span>
<span class="line"><span style="color:#E1E4E8"> method: </span><span style="color:#9ECBFF">'get'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> headers: {</span></span>
<span class="line"><span style="color:#9ECBFF"> 'Content-Type'</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">'application/json'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> Authorization: </span><span style="color:#9ECBFF">`Bearer ${</span><span style="color:#79B8FF">ACCESS_TOKEN</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">})</span></span></code></pre>
</li>
<li>
<p>I definitely don’t want to access this API on the client side (due to this token requirement), and I don’t want to call it that often while building the blog locally. That means that I need some kind of caching solution. Looking quickly if there is anything built-in in Astro (or a plugin), I did not find anything aside from a few issues about it (like <a href="https://github.com/withastro/roadmap/discussions/612">“astro: cache core component”</a>). I’ll probably implement the caching solution from scratch: it should be trivial enough.</p>
</li>
</ol>
<h2 id="plans">Plans</h2>
<ul>
<li>
<p>Implement a way to store and use the API token as an environment variable. I don’t think I want to provide it in the CI, as I am planning to always just build things locally, even though Netlify which I am using <a href="https://docs.netlify.com/configure-builds/environment-variables/">allows doing this easily</a>.</p>
</li>
<li>
<p>Implement a wrapper around the Pixelfed API that would cache all the necessary data I need to cache. It should be trivial enough:</p>
<ol>
<li>Check if I already have a cached <code>.json</code>, if so, just use it.</li>
<li>If there is no such cache yet, call the API, get all the data from it, store it as a file <em>near</em> the source page. I <em>will</em> add this cached info to source control: this will be a good way to back up at least some info, like the alt texts etc, making the content more <em>independent</em> of Pixelfed.</li>
<li>That’s it?</li>
</ol>
</li>
<li>
<p>Create an Astro component that would render an image with its alt in some way. I’ll need to come up with the design for it first, though.</p>
</li>
<li>
<p>I’ll likely want to include multiple images from multiple Pixelfed posts on one page, so I’ll need to also come up with a design for the gallery. And think if I need a separate whole category in my blog for this, or make it just a part of regular posts?</p>
</li>
</ul>
<h2 id="just-starting">Just Starting</h2>
<p>Aside from some experimental code to try out the API, I did not write any code for this. But I already started thinking about it, and planning what I want to do — a good first step.</p>
<p>I’ll continue working on this mini-project, and, hopefully, one day could start sharing my photos as a part of my blog (and backfill what I have published earlier in some form as well).</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113420956723708676">on Mastodon</a>!</p>Recent CSS Bookmarks 18: 12 Days of Web CFP, CSS Resets, and Selectorshttps://blog.kizu.dev/recent-css-bookmarks-018/https://blog.kizu.dev/recent-css-bookmarks-018/After a large gap, continuing reading and sharing the recent CSS bookmarks I gathered. I’ll mostly go through more recent ones, but I’ll include one section with a few older ones as well.Mon, 04 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Helios — Coast Off</dd><dt>Current drink:</dt><dd>Ceylon tea</dd></dl><hr /><p>After a large gap, I am continuing reading and sharing the recent bookmarks I gathered. I’ll mostly go through more recent ones, but I’ll include one section with a few older ones as well.</p>
<p>The order in every section is from the older to newer articles. Sorry if I missed something you posted!</p>
<aside>
If you write something about CSS, I will always be happy to read it. The best way to reach me is through [Mastodon DMs](https://front-end.social/@kizu) or [email](mailto:[email protected]).
<p>So if I missed something you published — or you saw something that I did not write about — please, let me know!</p>
</aside>
<h2 id="12-days-of-web-cfp">12 Days of Web CFP</h2>
<p>Speaking of new articles. For the first bookmark, I wanted to highlight this year’s <a href="https://12daysofweb.dev/">12 Days of Web</a>.</p>
<p><a href="https://thinkdobecreate.com/">Stephanie Eckles</a> <a href="https://front-end.social/@5t3ph/113420562852461230">opened</a> a <a href="https://docs.google.com/forms/d/e/1FAIpQLScu7HiNcnxpYwEIJ_S93dWtYWuOzISuU7cgIeITX8d7G71KNQ/viewform">Call For Proposals</a>, which will be open until November 10, with articles due by December 5.</p>
<p>I highly recommend participating (<a href="https://12daysofweb.dev/2023/anchor-positioning/">I did so last year</a>). If you don’t yet know the topic you’d want to write about: the CFP has a list of them for you to choose from.</p>
<aside>
And if you’re not sure about your abilities or just anxious, please let me know! I’d love to see new writers participate in this and other similar projects, and I’ll always be happy to review your articles or help in any other way.
</aside>
<h2 id="css-resets">CSS Resets</h2>
<p>It is always interesting to look at what other people consider their best “default” styles. Recently, many authors shared theirs. Interestingly, I <em>do not</em> use such a reset myself!</p>
<ul>
<li>
<p><a href="https://clagnut.com/blog/2433/">“Introducing TODS – a typographic and OpenType default stylesheet”</a> by <a href="https://clagnut.com/">Richard Rutter</a> — a detailed article about typography-focused CSS defaults, going through many OpenType features and proposing a better default value for some of them.</p>
</li>
<li>
<p><a href="https://wickstrom.tech/2024-09-26-how-i-built-the-monospace-web.html">“How I Built ‘The Monospace Web’”</a> by <a href="https://wickstrom.tech/">Oskar Wickström</a> — a post with a few details about how the author built <a href="https://github.com/owickstrom/the-monospace-web">“The Monospace Web”</a> exploration. It is not just a “reset”, but the main idea is very similar: to have some particular default styles for all elements.</p>
</li>
<li>
<p><a href="https://jakelazaroff.com/words/my-modern-css-reset/">“My Modern CSS Reset”</a> by <a href="https://jakelazaroff.com/">Jake Lazaroff</a> — an article with an explanation of what and why goes into the author’s CSS reset, as well as what they put into a “classless framework”.</p>
</li>
<li>
<p><a href="https://mikemai.net/blog/2024/11/01/you-are-not-a-css-dev-if-you-have-not-made-a-css-reset.html">“You are not a CSS dev if you have not made a CSS reset”</a> by <a href="https://mikemai.net/">Mike Mai</a> — another post about a CSS reset, with an inflammatory title, and a few other opinionated bits.</p>
</li>
<li>
<p><a href="https://www.mayank.co/blog/css-reset-layer">“Your CSS reset should be layered”</a> by <a href="https://www.mayank.co/">Mayank</a> — a post with a simple advice to put your reset into an <code>@layer</code> and a few arguments for doing so.</p>
</li>
</ul>
<p>Many of these articles link to older articles by other authors about their resets, which could be a good read if you’re interested in reading even more about this topic.</p>
<h2 id="selectors">Selectors</h2>
<p>Continuing from CSS resets — one of the main aspects of which are <em>selectors</em> — I’ll also mention some bookmarks specifically about them. This section will contain a few “older” links from my backlog as well, as a way to try to manage its size.</p>
<ul>
<li>
<p><a href="https://www.amitmerchant.com/ignore-and-acknowledge-class-attribute-on-elements-in-css/">“Ignore and acknowledge <code>class</code> attribute on elements in CSS”</a> by <a href="https://www.amitmerchant.com/">Amit Merchant</a> — a short post that names a concept of <em>ignoring</em> or <em>acknowledging</em> the presence of some attribute, like the <code>[class]</code> one.</p>
</li>
<li>
<p><a href="https://crinkles.dev/writing/a-modern-css-previous-sibling-combinator/">“MacOS-like dock effect with a ‘previous-sibling combinator’”</a> by <a href="https://crinkles.dev/">Kevin Pennekamp</a> — a post about how <code>:has()</code> selector allows us to select previous siblings with a dock-like effect as the example.</p>
</li>
<li>
<p><a href="https://brucelawson.co.uk/2024/css-has-the-god-selector/">“CSS <code>:has()</code>, the God Selector”</a> by <a href="https://brucelawson.co.uk/">Bruce Lawson</a> — another post about how <code>:has()</code> could be used separately from the actual element we’re selecting, and how powerful this could be. If anyone remembers the <a href="https://www.w3.org/TR/2013/WD-selectors4-20130502/#subject">“subject selector”</a> — it was replaced with <code>:has()</code>, which is, indeed, much more versatile.</p>
</li>
<li>
<p><a href="https://fantinel.dev/quantity-queries">“CSS ‘Quantity Queries’ are a thing now”</a> by <a href="https://fantinel.dev/">Matt Fantinel</a> — a post that looks at how we can now use <code>:has()</code> for quantity queries. (Term <a href="https://alistapart.com/article/quantity-queries-for-css/">coined</a> by <a href="https://heydonworks.com/">Heydon Pickering</a>.)</p>
</li>
<li>
<p><a href="https://matuzo.at/blog/2024/100daysof-day108">“Day 108: the of S syntax in <code>:nth-child()</code>”</a> by <a href="https://matuzo.at/">Manuel Matuzović</a> — a post that focuses on the optional selector argument of <code>:nth-…</code> pseudo-classes, which is a mighty new feature of them.</p>
</li>
<li>
<p><a href="https://cirrus.twiddles.com/blog/2024/08/21/double-your-specificity-with-this-one-weird-trick/">“Double your specificity with this one weird trick”</a> by <a href="https://cirrus.twiddles.com/">James Nash</a> — a post about how multiple mentions of the same <code>class</code> selector in CSS still bumps up the rule’s specificity. While using the same class <em>is</em> a way to do so, in similar situations I prefer to use the before mentioned <em>acknowledgement</em> selector. So, <code>.foo[class][class]</code> instead of <code>.foo.foo.foo</code>. Although, with <code>:where()</code> and <code>@layer</code>, hacks like these, hopefully, will eventually go away.</p>
</li>
<li>
<p><a href="https://chriskirknielsen.com/blog/nth-next-sibling-no-need/">“<code>:nth-next-sibling</code>? No need.”</a> by <a href="https://chriskirknielsen.com/">Christopher Kirk-Nielsen</a> — a post about a neat hack with the selector argument of a <code>:nth-…</code> family of pseudo-classes. I disagree with the title: the hack itself allows us to only select a <em>finite</em> span of elements, while a hypothetical <code>:nth-next-sibling()</code> would be able to select <em>repeated sequences</em> of them — something I explored in my <a href="https://blog.kizu.dev/nth-sibling-christmas-tree/">“A Christmas Tree Selector: Prototyping the <code>:nth-sibling()</code> with CSS Nesting”</a> post.</p>
</li>
<li>
<p><a href="https://www.trysmudford.com/blog/i-spent-a-day-making-the-website-go-2ms-faster/">“I wasted a day on CSS selector performance to make a website load 2ms faster”</a> by <a href="https://www.trysmudford.com/">Trys Mudford</a> — a post about how Chrome performance profiler’s “CSS selector stats” can only show the relative performance of selectors, with the actual numbers it will show being impacted by all the added instrumentation.</p>
</li>
<li>
<p><a href="https://kizu.dev/tree-counting-and-random/">“Possible Future CSS: Tree-Counting Functions and Random Values”</a> by <a href="https://kizu.dev/">me</a> — while the topic itself is about future <em>functions</em>, the article focuses on the way we can prototype them today by using complex selectors, including those based on quantity queries. Speaking of selectors’ performance: my experiments in this article crashed Safari. We must be careful when using both <code>:has()</code> and native CSS nesting.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/making-content-aware-components-using-css-has-grid-and-quantity-queries/">“Making content-aware components using CSS <code>:has()</code>, grid, and quantity queries”</a> by <a href="https://ericwbailey.website/">Eric Bailey</a> — a post about a real-life use case for quantity queries based on <code>:has()</code> for switching a position of some elements inside a CSS grid. In my opinion, ideally, for cases like this one, we’ll need something that would allow us to detect when things wrap in CSS, like what I <a href="https://kizu.dev/position-driven-styles/#flex-wrap-detection">prototyped</a> with scroll-driven animations in my <a href="https://kizu.dev/position-driven-styles/">“Position-Driven Styles”</a> article.</p>
</li>
<li>
<p><a href="https://css-tip.com/first-element-dom/">“Select the first occurrence of an element in the whole document”</a> by <a href="https://css-articles.com/">Temani Afif</a> — a clever trick that combines <code>:has()</code>, <code>:nth-child(of …)</code>, and <code>:not()</code> pseudo-classes for selecting a first or last element similar to the way <code>querySelector()</code> does it in JS. Based on my experience, I’ll be a bit wary of its potential performance implications, especially in Safari, so if you try using it, test it extensively.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113425284627007762">on Mastodon</a>!</p>Observation: Forced Wrappinghttps://blog.kizu.dev/forced-wrapping/https://blog.kizu.dev/forced-wrapping/Back in August, I saw a Mastodon thread by Anne Sturdivant about how she was styling titles, in which she described a wish for a certain wrapping behavior. Curiously enough, I remembered one interesting aspect of flexbox that could help to achieve what she wanted, and shared it with her. For quite a while, I wanted to write an “observation” post about it — and, finally, here we are! Maybe you’ll find it useful one day too.Tue, 05 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Ling Tosite Sigure — キミトオク</dd><dt>Current drink:</dt><dd>Plain Water</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Back in August, I saw <a href="https://social.lol/@anniegreens/112890011461777367">a Mastodon thread</a> by <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a> about how she was styling titles, in which she <a href="https://social.lol/@anniegreens/112890024470894579">described a wish</a> for a certain wrapping behavior:</p>
<blockquote>
<p>I’m finding myself wanting a variant of <code>text-wrap: balance</code> where you can specify a minimum number of lines for the text to wrap so that it would never appear on one line without having to insert a <code><br></code> element.</p>
</blockquote>
<p>Curiously enough, I remembered one interesting aspect of flexbox that could help to achieve what she wanted, and <a href="https://front-end.social/@kizu/112893348038380451">I shared it with her</a>.</p>
<p>For quite a while, I wanted to write an <a href="/tags/observation">“observation”</a> post about it — and, finally, here we are! Maybe you’ll find it useful one day too.</p>
<h2 id="the-forced-wrapping-technique">The “Forced Wrapping” Technique</h2>
<p>The code behind this technique is very short:</p>
<style>{`
.example {
display: grid;
gap: 1rem;
}
.example h3 {
margin: 0;
outline: 3px double hotpink;
}
`}</style>
<p><a href="https://blog.kizu.dev/forced-wrapping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.forced-wrapping</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> max-inline-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">max-content</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &::after {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">""</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> flex-basis</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">>Hello!</</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">>Some Title</</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">>And a Much Longer Title With Many Words That Would Wrap Anyway</</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Yep, that’s just four declarations, with one for adding a pseudo-element!</p>
<ol>
<li><code>display: flex</code> — first, we must make our element a <a href="https://drafts.csswg.org/css-flexbox/#flex-containers">flex container</a>.</li>
<li><code>max-inline-size: max-content</code> — then, we need to tell our element that it should size itself in the inline axis based on the <a href="https://drafts.csswg.org/css-sizing-3/#max-content">maximum intrinsic size of its content</a>.</li>
<li><code>content: ""</code> — we need a pseudo-element that will go after our text content. That could be an actual element, the main requirement is for it to go <em>after</em> the text. Otherwise, when the content wraps, it will take up the space at the beginning.</li>
<li><code>flex-basis: 0.1px</code> — finally, we make this pseudo-element to have some tiny positive <code>flex-basis</code> value. I found values less than <code>0.1px</code> to not work well with certain values of browser zoom, but <code>0.1px</code> seems to work consistently across all browsers.</li>
</ol>
<h3 id="why-does-it-work">Why Does It Work?</h3>
<p>So, what happens here? Let’s peek at some definitions. First, for <a href="https://drafts.csswg.org/css-sizing-3/#max-content-inline-size"><code>max-inline-size: max-content</code></a>:</p>
<blockquote>
<p>The box’s “ideal” size in the inline axis. Usually the narrowest inline size it could take while fitting around its contents if none of the soft wrap opportunities within the box were taken.</p>
</blockquote>
<p>In other words, if our text doesn’t wrap, and there is nothing else near it, our container will be sized to fit the text inside. Let’s look at two headers: one without the <code>forced-wrapping</code> class, and another with it:</p>
<p><a href="https://blog.kizu.dev/forced-wrapping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"max-inline-size: max-content"</span><span style="color:#E1E4E8">>Some Title</</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">>Some Title</</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>You might’ve noticed from the initial example that the second title had an unusual width. In this second example, you can see why: that <em>is</em> the inner text’s <code>max-content</code> value!</p>
<p>If we now look at the <a href="https://drafts.csswg.org/css-flexbox/#layout-algorithm">“Flex Layout Algorithm”</a>, specifically at the second step, <a href="https://drafts.csswg.org/css-flexbox/#line-sizing">“Line Length Determination”</a>, we will find this:</p>
<blockquote>
<p>if that dimension of the flex container is being sized under a min or max-content constraint, the available space in that dimension is that constraint</p>
</blockquote>
<p>This means that the space available for all our flex items is calculated based on the <code>max-content</code> (in our case) <em>before</em> any of the flex properties will be applied. So, when we calculate that <code>max-content</code>, we only look at the original, non-flex dimensions of our elements, and our <code>::after</code> is empty; thus it contributes <code>0px</code> to the “max-content constraint”, with the actual text being the only real contributor.</p>
<p>The <code>flex-basis</code> on the pseudo-element enters the algorithm later. What happens next is that, with a positive value, it is subtracted from the available space from our text’s anonymous box. From the <a href="https://drafts.csswg.org/css-flexbox/#propdef-flex-basis"><code>flex-basis</code></a> description:</p>
<blockquote>
<p>This component sets the flex-basis longhand, which specifies the flex basis: the initial main size of the flex item, before free space is distributed according to the flex factors.</p>
</blockquote>
<p>And, because our container was sized with our text’s size, subtracting <em>anything</em> results in the text wrapping! Of course, unless it was wrapping already — in which case the tiny size of the <code>::after</code> won’t have any visible impact.</p>
<h3 id="things-to-note">Things to Note</h3>
<p>As mentioned in the original thread, this looks the best with <code>text-wrap: balance</code>. It is not present in the code I showed, as it is not strictly required for the technique to work, but it is applied from my general blog’s CSS.</p>
<p>If some of the text inside the title would need to have an additional element somewhere in the text, we’d need to wrap the whole text into a span, otherwise, due to the flex context, things won’t look as expected:</p>
<p><a href="https://blog.kizu.dev/forced-wrapping/">Component is not available in RSS, visit the the site to access it.</a>` becomes its anonymous box.”></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Some <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Nice</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> Title</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Some <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Nice</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> Title</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>So if you want to use this with unknown content, it might be better to have this extra wrapper present. But maybe one day we’ll have <a href="https://github.com/w3c/csswg-drafts/issues/2406">the <code>:contents</code> pseudo-element</a> which we could use to add an explicit wrapper around everything.</p>
<p>Sometimes, a title could look better when it stays on one line, in which case a non-breaking space could help:</p>
<p><a href="https://blog.kizu.dev/forced-wrapping/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> A Title</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">h3</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"forced-wrapping"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> A</span><span style="color:#79B8FF">&nbsp;</span><span style="color:#E1E4E8">Title</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">h3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<h2 id="conclusion">Conclusion</h2>
<p>There is a chance I explained something incorrectly. Still, the general idea should be clear: when working with a <code>flex-basis</code>, it does not have any impact on the intrinsic size of the flex container, so we can first size things based on the regular dimensions, and then adjust them.</p>
<p>When I first encountered this, I treated it as a bug, until I noticed that this behavior is consistent across all browsers, and seems properly specified.</p>
<p>It was fun finding an interesting use case for this behavior and applying it there. There are still areas of the flex algorithm that I do not understand completely, and I will need to return to it and explore it more.</p>
<p>And if you find other curious use cases for this <code>flex-basis</code> behavior in tandem with intrinsic sizing — please, let me know!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113430428507897750">on Mastodon</a>!</p>Recent CSS Bookmarks 19: Container Querieshttps://blog.kizu.dev/recent-css-bookmarks-019/https://blog.kizu.dev/recent-css-bookmarks-019/I originally wanted to write about something else today but, for some reason, did not have any motivation for it. But hey, let me then do the best thing I could do otherwise: share some other people’s articles. It is always nice to think that there are others, who are interested in the same thing you are. In this post, I gathered 15 bookmarks about CSS container queries (and some other queries as well).Wed, 06 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Phoebe Bridgers — I Know the End</dd><dt>Current drink:</dt><dd>Hot Cocoa</dd></dl><hr /><p>I originally wanted to write about something else today but, for some reason, did not have any motivation for it.</p>
<p>But hey, let me then do the best thing I could do otherwise: share some other people’s articles. It is always nice to think that there are others, who are interested in the same thing you are.</p>
<p>In this post, I gathered 15 bookmarks about container queries (and some other queries as well). This time, the order is from the more recent to the older ones. I’m still playing around with how I want to do these bookmarks.</p>
<ul>
<li>
<p><a href="https://www.joshwcomeau.com/css/container-queries-introduction/">“A Friendly Introduction to Container Queries”</a> by <a href="https://www.joshwcomeau.com/">Josh W. Comeau</a> — a lengthy article with many interactive examples with an overview of container queries: why we need them and how to apply them.</p>
</li>
<li>
<p><a href="https://www.bram.us/2024/10/06/feature-detect-style-queries-support-in-css/">“Feature detect Style Queries Support in CSS”</a> by <a href="https://www.bram.us/">Bramus</a> — a post about how we can use space toggles for the style query feature detection.</p>
</li>
<li>
<p><a href="https://michaelcharl.es/aubrey/en/code/resolving-issues-from-unexpecged-css-changes-in-chrome-129">“Resolving Issues from Unexpected Changes to <code>container-type: inline-size</code> in Chrome 129”</a> by <a href="https://michaelcharl.es/aubrey">Michael Charles Aubrey</a> — a post about a recent change to layout containment (see <a href="https://github.com/w3c/csswg-drafts/issues/10544">“Weaker form of layout containment for container queries”</a> CSSWG issue by <a href="https://github.com/bfgeek">Ian Kilpatrick</a>), which is already shipped in Chrome, and is also present in the latest Firefox Nightly and Safari Technology Preview.</p>
</li>
<li>
<p><a href="https://utilitybend.com/blog/is-the-sticky-thing-stuck-is-the-snappy-item-snapped-a-look-at-state-queries-in-css">“Is the sticky thing stuck? Is the snappy item snapped? A look at state queries in CSS”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — an article with an overview of two experimental scroll-state queries which are currently available for testing in Chrome Canary. I, personally, still think that <a href="https://kizu.dev/scroll-driven-animations/#stuck-states-for-the-sticky-headers">scroll-driven animations produce a much better result</a> for at least the “stuck” use case, but I can also agree that they’re much harder to work with, and for more simple use cases state queries will be much easier to apply.</p>
</li>
<li>
<p><a href="https://css-irl.info/logical-properties-in-size-queries/">“Logical Properties in Size Queries”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — a post about one difference between container queries from media queries when using logical properties in them.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/building-a-breakout-element-with-container-units/">“Building a breakout element with container units”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a short case study about how container query length units can be useful for implementing breakout layouts. I used a similar approach a few times and can attest that this is a good use for them.</p>
</li>
<li>
<p><a href="https://blog.kizu.dev/querying-the-color-scheme/">“Querying the Color Scheme”</a> by <a href="https://kizu.dev/">me</a> — a post about how we could hack around the <code>light-dark ()</code> function, registered custom properties and style queries to implement a way to detect the <code>color-scheme</code> on children of any element.</p>
</li>
<li>
<p><a href="https://css-tricks.com/smart-layouts-with-container-queries/">“‘Smart’ Layouts With Container Queries “</a> by <a href="https://www.kevinpowell.co/">Kevin Powell</a> — an article that shows just how much better container queries are compared to media queries, including showing some of their uncommon but useful aspects.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/what-if-you-used-container-units-for-everything/">“What if you used Container Units for… everything?”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — a post about an experiment with container query length units, and some things we can learn if we try to apply them to <em>everything</em>.</p>
</li>
<li>
<p><a href="https://web.dev/blog/how-to-use-container-queries-now">“How to use container queries now”</a> by <a href="https://philipwalton.com/">Philip Walton</a> — an article with an extensive look over the different steps we can take if we need to support older browsers when using container queries, including working around their absence with a <a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver">ResizeObserver</a>.</p>
</li>
<li>
<p><a href="https://hey.georgie.nu/container-queries-existing-design-system/">“Opting into CSS container queries for an existing design system”</a> by <a href="https://hey.georgie.nu/">Georgie Cooke</a> — a post that takes a banner example to demonstrate how container queries can be used in practice today, outlining one pitfall that we can fall in when applying container queries in a design system context.</p>
</li>
<li>
<p><a href="https://www.speedkit.com/blog/field-testing-css-containment-for-web-performance-optimization">“Field Testing CSS Containment for Web Performance Optimization”</a> by <a href="https://screenspan.net/">Brian Louis Ramirez</a> — a post about using containment (without queries this time, but with <code>content-visibility</code>) as a way to improve the rendering performance of web pages, with a few field tests and their results.</p>
</li>
<li>
<p><a href="https://www.smashingmagazine.com/2024/06/what-are-css-container-style-queries-good-for/">“What Are CSS Container Style Queries Good For?”</a> by <a href="https://www.monknow.dev/en/">Juan Diego Rodriguez</a> — an article with a basic overview of container queries and style container queries, with a few examples and explanations of how they work.</p>
</li>
<li>
<p><a href="https://csscade.com/responsive-posters-in-css/">“Responsive posters in CSS”</a> by <a href="https://robinrendle.com/">Robin Rendle</a> — a post about how we could use <code>aspect-ratio</code> and container query length units to create fully resizable “posters”.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/weve-got-container-queries-now-but-are-we-actually-using-them/">“We’ve Got Container Queries Now, But Are We Actually Using Them?”</a> by <a href="https://chriscoyier.net/">Chris Coyier</a> — an article looking at the current usage of container queries, arguing that we could want to start using them more, and presenting several good examples.</p>
</li>
</ul>
<p>That’s it for today. Be safe.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113438287105492069">on Mastodon</a>!</p>Beyond Tellerrand: Quick Notes on Physicalityhttps://blog.kizu.dev/notes-on-physicality/https://blog.kizu.dev/notes-on-physicality/I spent the whole day at the first day of beyond tellerrand conference in Berlin, so I did not have an opportunity to work on a proper post here. I met many nice people! New and old faces, good talks. I have made many notes, and have many thoughts, but wanted to just quickly jot down one of them, mostly as something that I have been thinking about for quite a while already. That thing is — physicality.Thu, 07 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Veltpunch — killer smile</dd><dt>Current drink:</dt><dd>Hot Cocoa</dd></dl><hr /><p>I spent the whole day at the first of two days of <a href="https://beyondtellerrand.com/events/berlin-2024">beyond tellerrand</a> conference in Berlin, so I did not have an opportunity to work on a proper post here.</p>
<p>I met many nice people! New and old faces, good talks.</p>
<p>I have made many notes, and have many thoughts, but wanted to just quickly jot down one of them, mostly as something that I have been thinking about for quite a while already.</p>
<p>That thing is — <strong>physicality</strong>.</p>
<p>Being someone who is staring at the pixels all day every day, I often wonder: is there something that is possible to do for me <em>outside</em> of the screen?</p>
<p>The problem is: I am kinda bad with physical stuff? My hands cannot draw, they cannot write, just the whole process of keeping physical notes is not something that I can or want to do. But I can see how being limited by the rectangle (or a few — with multiscreen setup) can be restrictive. How absence of a touch, of a feel, a texture, an ability to <em>interact</em> with things in real life is something I miss.</p>
<p>In my childhood, I used to play with LEGO a lot. In the present day (<a href="https://www.youtube.com/watch?v=NfjsLmya1PI">present time</a> hahahaha), a lot of my days are spent fidgeting with any random small items I have on my work desk.</p>
<p>Is there anything that can be done that could fascilitate my experiments with CSS, but that would involve physical objects?</p>
<p>When I first learned about <a href="https://dynamicland.org/">Dynamicland</a> — a project by <a href="https://worrydream.com/">Bret Victor</a> and some others — I was looking at it from a rather sceptical point of view. For my experiments, I am mostly working alone, the collaboration of these physical interactions is not something I need, or even want. Not everyone is comfortable working like that!</p>
<p>But maybe there is something that even I could find with this. Just as a way to augment the reality, but not in a digital way, but recursively, with other real things.</p>
<p>When <a href="http://lindaliukas.com/">Linda Liukas</a> started the first talk of the day — about bulding an actual kids’ playground to fascilitate learning through play — I was immediately reminded of Dynamicland. And was delighted to see it mentioned on one of the slides as an inspiration.</p>
<p>Three other talks today also mentioned physicality in one way or another:</p>
<ul>
<li><a href="https://sulu.be/">Jan De Coster</a> did talk about his robots — actual physical objects.</li>
<li><a href="https://craig.black/">Craig Black</a> works with physical paint and uses the actual physics of acrylic paint to achieve some kind of generative art.</li>
<li><a href="https://jessicahische.is/awesome">Jessica Hische</a> mentioned how she copes with the uncertainty that AI brings today by doing more things in the physical realm, with her <a href="https://jessicahische.shop/">actual shop and studio in Oakland</a>.</li>
</ul>
<p>Everyone is touching their own medium, and I am a bit jelous: what about me? I don’t have anything like that.</p>
<p>Or do I? Maybe I just did not discover it yet. Maybe, one day I would wake up, and my brain will combine some puzzle that would show me the picture of how <em>I</em> could do it.</p>
<p>Maybe, one day, I could leave the <em>wired</em> world, and come back to reality.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113444137809645357">on Mastodon</a>!</p>Moving to Firefox: the First Anniversaryhttps://blog.kizu.dev/moving-to-firefox-first-anniversary/https://blog.kizu.dev/moving-to-firefox-first-anniversary/One year ago, I moved to Firefox. I’m still using it (the “Nightly” version). Mozilla has made some questionable moves since then. But, each time I look at the alternatives, I am not entirely sure if there is any reason — for me — to move to something else.Fri, 08 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Sigur Rós — Sæglópur</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>One year ago, I <a href="https://blog.kizu.dev/moving-to-firefox/">moved to Firefox</a>. I’m still using it (the <a href="https://www.mozilla.org/en-US/firefox/channel/desktop/#nightly">“Nightly”</a> version).</p>
<p>Mozilla has made some questionable moves since then.</p>
<p>But, each time I look at the alternatives, I am not entirely sure if there is any reason — for me — to move to something else.</p>
<ul>
<li>I don’t want to use anything based on Chromium, as I don’t want to use an engine with the biggest market share.</li>
<li>Each time I try Safari, I find it lacking in many areas I care about.</li>
<li>I want to use the latest version possible, so I don’t want to use anything that is based on Gecko, as it would be guaranteed to not be the latest. If I were to use Chromium — I’d use <a href="https://www.google.com/chrome/canary/">Canary</a>, if Safari — then <a href="https://developer.apple.com/safari/technology-preview/">Technology Preview</a>.</li>
<li>And I don’t think <a href="https://servo.org/">Servo</a> is ready (but this is probably the one engine I’ll be looking at more closely when it comes closer to being feature-complete).</li>
</ul>
<p>And like there is no ethical consumption under capitalism, there is no ethical browser development under it. If we’d follow the money trail of almost all browser development, what would we find? Likely, Google’s money.</p>
<p>If Google were to just stop giving money to Apple and Mozilla for the default search, and they would stop updating their engines, would they be added <a href="https://killedbygoogle.com/">killedbygoogle.com</a>?</p>
<p>Monopoly bad, capitalism bad, and I have no idea what the answer to all of this is.</p>
<p>Of course, there are boundaries that Mozilla could cross which will make me reconsider it. For me, they’re not there yet.</p>
<p>Thankfully, I changed browsers so many times, that if the need to move will arise, I will just move. But there are already so many things to worry about, and the theoretical purity of a browser engine is not something I have spoons to tackle right now.</p>
<p>Not that I have that many of them left. Initially, I wanted to write about Firefox plugins that I’m still using, and those I deleted. Or about my custom CSS overrides for Firefox’s UI. Not today. I’m too tired.</p>
<p>Let’s hope that Mozilla won’t do anything else, and I will write another post about all of this in one year.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113449730572393665">on Mastodon</a>!</p>My Mastodon Starter Packhttps://blog.kizu.dev/my-mastodon-starter-pack/https://blog.kizu.dev/my-mastodon-starter-pack/Sometimes, I invite someone to join Mastodon, and I end up sharing the same links and information repeatedly. Following the “manual until it hurts” IndieWeb practice, after repeating the same things a few times, it is time to “automate” it. Well, in this case, just put everything into one blog post, I guess.Sat, 09 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>jizue — atom</dd><dt>Current drink:</dt><dd>English Breakfast Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Sometimes, I invite someone to join <a href="https://joinmastodon.org/">Mastodon</a>, and I end up sharing the same links and information repeatedly.</p>
<p>Following the <a href="https://indieweb.org/manual_until_it_hurts">“manual until it hurts”</a> <a href="https://indieweb.org/">IndieWeb</a> practice, after repeating the same things a few times, it is time to “automate” it. Well, in this case, just put everything into one blog post, I guess.</p>
<aside class="warning">
If you’re looking for whom to follow — I don’t have a “useful” single-click deceptive pattern that will bulk add hundreds of accounts, making those who are already rich richer, and creating an illusion of activity with numbers going up. But I have a [“Whom to Follow?”](#whom-to-follow) section later in the post, with a general recommendation of how to find people you’d want to follow yourself.
</aside>
<aside>
<details>
<summary>Why I’m only talking about “Mastodon”, and not about “Fediverse”?</summary>
<p>While I have other <a href="https://en.wikipedia.org/wiki/Fediverse">Fediverse</a> accounts — on <a href="https://pixelfed.org/">Pixelfed</a> (<a href="https://pixey.org/@kizu">@[email protected]</a>) and <a href="https://joinbookwyrm.com/">BookWyrm</a> (<a href="https://bookrastinating.com/@kizu">@[email protected]</a>) — the main account I’m using is on Mastodon (<a href="https://front-end.social/@kizu">@[email protected]</a>).</p>
<p>This means that I know much more about it specifically.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span></details></span></span></code></pre>
</details></aside>
<h2 id="why-join-mastodon">Why join Mastodon?</h2>
<p>I’ve been using Mastodon actively for more than two years now: on November 6th, it was my second “fediversary” (last year, I wrote a <a href="/first-fediversary/">“My First ‘Fediversary’”</a> post). In that post, I described why <em>I</em> joined. I’m pretty happy there!</p>
<p>If I did send you a link to this post, that means I would be happy if you would join. I am not on any other social network, and I would love to stay connected with you.</p>
<p>That <em><strong>is</strong></em> the main reason.</p>
<aside>
<details>
<summary>Why not other social networks? </summary>
<p>In short: they’re not decentralized. Even if their <em>protocol</em> is (at least in theory), there is usually a single entity that controls everything, backed by venture capital of questionable origins. I’ve been on the Web for more than 20 years, and I’m tired of services changing owners and going away.</p>
<p>If a single instance goes away, you can always move to another. If something happens with Mastodon itself, the Fediverse is still there.</p>
<p>There is a critical mass of people who care, and while moving servers can sometimes be painful, it <em>is</em> possible, and you can continue following everyone you did before.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span></details></span></span></code></pre>
</details></aside>
<h2 id="which-instance-tochoose">Which Instance to Choose?</h2>
<p>If I sent this link to you, it is likely I already sent you an invitation to join the same instance I’m on: <a href="https://front-end.social/about">front-end.social</a> — an instance created by <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> (<a href="https://front-end.social/@mia">@[email protected]</a>).</p>
<p>At this point, if you’re a front-end web developer, this instance gathered so many good people already! Of course, there are many other good instances. For example, <a href="https://fedidevs.com/">fedidevs</a> website by <a href="https://pecar.me/">Anže Pečar</a> (<a href="https://fosstodon.org/@anze3db">@[email protected]</a>) has a page with <a href="https://fedidevs.com/developers-on-mastodon/">a list of a few more popular ones</a>.</p>
<p>But if I look at my stats (via the helpful <a href="https://josephrocca.github.io/public-mastodon-data.js/demos/followers-by-instance.html">“followers by instance”</a> tool by <a href="https://github.com/josephrocca">Joseph Rocca</a> (<a href="https://mastodon.social/@joerocca">@[email protected]</a>)), I follow many people from a few smaller instances:</p>
<ul>
<li><a href="https://toot.cafe/about">toot.cafe</a> (<a href="https://toot.cafe/directory?local=true&order=active">directory</a>)</li>
<li><a href="https://indieweb.social/about">indieweb.social</a> (<a href="https://indieweb.social/directory?local=true&order=active">directory</a>)</li>
<li><a href="https://typo.social/about">typo.social</a> (<a href="https://typo.social/directory">directory</a>, choose the “From typo.social only”)</li>
<li><a href="https://tech.lgbt/about">tech.lgbt</a> (<a href="https://tech.lgbt/directory?local=true&order=active">directory</a>)</li>
<li><a href="https://social.lol/about">social.lol</a> (<a href="https://social.lol/directory?local=true&order=active">directory</a>)</li>
<li><a href="https://vis.social/about">vis.social</a> (<a href="https://vis.social/directory?local=true&order=active">directory</a>)</li>
</ul>
<p>Not everywhere is the registration open, though. If you know someone from an instance with a closed registration, they could usually send you a personalized invitation.</p>
<aside>
<details>
<summary>Why not to choose the “default” instance?</summary>
<p>If you <em>really</em> don’t want to think, and you don’t have any friends, whose Mastodon accounts you know, you can join the <a href="https://mastodon.social/about">mastodon.social</a> instance.</p>
<p>However, I strongly recommend you find a smaller home. You will still be able to follow people from other instances — that’s the main point of decentralization — and you’ll have a smaller and neater neighbourhood, with better moderation and people who will more likely share your interests closer to you.</p>
<p>I did also omit some other larger instances like <a href="https://hachyderm.io/about">hachyderm.io</a> and <a href="https://fosstodon.org/about">fosstodon.org</a>, as, in my opinion, they are already <em>too big</em>.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span></details></span></span></code></pre>
</details></aside>
<h2 id="whom-to-follow">Whom to Follow?</h2>
<p>First, look at the <a href="https://front-end.social/directory?order=active&local=true">front-end.social’s “directory”</a>: it shows everyone who opted-in to be present there. If you had followed people from the front-end community before, you’ll likely see some familiar faces. And if front-end.social won’t be enough for you: look at the directories for other instances I posted above, as well as at the <a href="https://fedidevs.com/">fedidevs</a> directory that I already mentioned.</p>
<p>And — always a good way to find people — go to the “following” tab on anyone’s profile, and, if they did not hide it, you could also find someone to follow there. For example, here is <a href="https://front-end.social/@kizu/following">my “following” list</a>.</p>
<aside>
There is also another good way to find people: search for “Mastodon” in the search of your old and rotten social network, choose “People you follow” and then look at the “Latest” and “People” tabs. They will likely contain mentions of where people are moving to, either in posts, or in usernames and profiles.
<p>I am not going to link to anywhere directly from here, but maybe this will help you: <code>/search?q=mastodon&f=live&pf=on</code></p>
</aside>
<h2 id="which-mastodon-client-touse">Which Mastodon Client to Use?</h2>
<p>By default, the official web-app might not be ideal. As soon as you find its UX confusing, I highly recommend checking out one of many other <a href="https://joinmastodon.org/apps#:~:text=Browse-,third%2Dparty%20apps,-All">third-party apps</a>, in particular:</p>
<ol>
<li>
<p><a href="https://phanpy.social/">Phanpy</a> by <a href="https://cheeaun.com/">Lim Chee Aun</a> (<a href="https://mastodon.social/@cheeaun">@[email protected]</a>) — “A minimalistic opinionated Mastodon web client”. This is the main app I’m using both on the desktop, and the mobile. It is great! So many innovative features! The best part? It is just a <em>static</em> (!) web app — you can fork it, and then use it either just from localhost, or host it yourself on any of the free services — GitHub pages, Netlify, or anything else. See, for example, <a href="https://phanpy.kizu.dev/">my fork</a> — I added some CSS overrides just for myself.</p>
</li>
<li>
<p><a href="https://tapbots.com/ivory/">Ivory</a> by <a href="https://tapbots.com/">TapBots</a> — an iOS app from the creators of “Tweetbot”. I am not using it, but I have warm memories of using Tweetbot back in the day, and if this is the experience you’re missing as well — you can try it! (but it is paid and has a subscription model).</p>
</li>
<li>
<p><a href="https://elk.zone/">Elk</a> — I did not try it, but I heard many good things about it. It might look very familiar to you, and if this familiarity is what you’re craving — you can try it!</p>
</li>
</ol>
<h2 id="what-isthe-basic-etiquette">What is the Basic Etiquette?</h2>
<p>I have no idea! Various instances have differences in how people use Mastodon. Before choosing an instance, I recommend carefully reading out their Code of Conduct and other rules they might have.</p>
<p>If I were to briefly mention something, it would be this:</p>
<ol>
<li>
<p>Fill up your profile: userpic, name, links, etc.</p>
</li>
<li>
<p>Write an <code>#introduction</code> post. You can search for it in Mastodon to see how others do it, for example: <a href="https://front-end.social/tags/introduction">https://front-end.social/tags/introduction</a></p>
</li>
<li>
<p>Start following people! Now, people could recognize you, or just understand who followed them, and not look at a newly created account with the default avatar, not knowing what to expect.</p>
</li>
<li>
<p>Start using Mastodon! Read what people write, and post your own stuff.</p>
</li>
<li>
<p>I recommend not to post links and advertise yourself <em>right away</em>. In general, self-promotion is welcome on most servers, but it is better to first acclimatize a bit to how things work, introduce yourself, show that you’re an actual person, and only then plug your work.</p>
</li>
<li>
<p>Similarly, I don’t recommend jumping into replies to everyone, especially if you do not agree with the other person, or have “not a question, but a comment”. Read first, think second, and only then decide if you can contribute to the conversation tactfully and responsibly. You know, be a decent, empathic person.</p>
</li>
<li>
<p>When posting something, do it accessibly: add proper alternative descriptions to images. I recommend <a href="https://adrianroselli.com/2024/05/my-approach-to-alt-text.html">“My Approach to Alt Text”</a> by <a href="https://adrianroselli.com/">Adrian Roselli</a> (<a href="https://toot.cafe/@aardrian">@[email protected]</a>), and do not use “fancy characters” and unusual markup, as it can be frustrating to get read to you if you’re using a screen reader.</p>
</li>
<li>
<p>Mastodon allows using the “Content Warnings” to hide some content behind a disclosure widget. Different corners of Fediverse have different etiquettes about this: consult your instance’s rules; it is usually mentioned there. Note that “CW” can be used for other purposes as well: not only for hiding NSFW content but also just anything topical that you feel can be distracting or triggering to other people, or even for longer threads, so they take less space in the timeline.</p>
</li>
</ol>
<p>This is not an extensive list. Think with your own head, follow the Code of Conducts, and be a good human.</p>
<h2 id="further-reading">Further Reading</h2>
<p>I might update this post in the future with more links and suggestions, but there are also many resources I recommend checking out <a href="https://fedi.tips/">fedi.tips</a> — a great collection of information about Mastodon and Fediverse in general. If you have a question about anything, you’re likely to find the answer there.</p>
<p>I remember other similar posts by other people in the past, but I don’t have any links to them prepared. If you stumbled upon any — please, share them with me, and I will include them here.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113455328113049542">on Mastodon</a>!</p>Managing Bookmarks, part 1https://blog.kizu.dev/managing-bookmarks-part-1/https://blog.kizu.dev/managing-bookmarks-part-1/I have so many things I want to do with my blog! I’m already thinking about having a good way to embed Pixelfed images, and now I’m also wondering what could be the best way to handle bookmarks. Currently, I’m just posting them as compilations, manually marking them up in Markdown lists with links, writing descriptions, and then categorizing them. But the way I do it now is too limited: it is too manual, and it is difficult to build on top of it.Mon, 11 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Yvette Young — A Map a String a Light, Pt. 2</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>I have so many things I want to do with my blog! I’m already thinking about having <a href="/embedding-pixelfed-part-1/">a good way to embed Pixelfed images</a>, and now I’m also wondering what could be the best way to handle <a href="/tags/bookmarks/">bookmarks</a>.</p>
<p>Currently, I’m just posting them as compilations, manually marking them up in Markdown lists with links, writing descriptions, and then categorizing them.</p>
<p>I considered doing what some others do: posting bookmarks one by one, but I don’t think I like this approach. I enjoy reading articles in bunches, and usually on the same topic. It is interesting to make connections and look at how different people approach similar themes from different angles.</p>
<p>But the way I do it now is too limited: it is too manual, and it is difficult to build on top of it.</p>
<h2 id="what-iwant">What I Want</h2>
<p>Here is an approximate list of things that I want to do:</p>
<ul>
<li>
<p>Make it easier to attribute people. Today, it’s a lot of manual work looking if I already posted something by some author, then copying their name & URL, and later their mastodon handle for mentioning there. I plan to save the common metadata, and then be able to easily access and compile it.</p>
</li>
<li>
<p>Sort things based on the time posted. Right now, I’m doing this manually, and do not really save this information anywhere, just using it to manually reorder bookmarks in the list. I wish to store the date, as it could be very useful in the future, as it will allow building a timeline of events for a specific CSS feature across multiple months.</p>
</li>
<li>
<p>Have better categories. Sometimes, I post bookmarks with too many different topics, not categorizing them at all. Often, I put some sections with a title around a list of them, but this allows me to have only one list. What I want to do is have the ability to add multiple tags per link, and then when I would like to publish a bookmarks post, make it easy to find the common themes.</p>
</li>
<li>
<p>Sometimes a post is a “reply” to something else or mentions other articles. For now, this is something I have to mention manually in my descriptions, but what if this could be another point of metadata added to every bookmark? It could allow the creation of something like a graph view of articles, showing how concepts evolve.</p>
</li>
<li>
<p>With tags, authors, and all the other metadata, I can see endless possibilities of providing different views over all the already posted bookmarks. I will need to fill out all that metadata, yes, but the result should be worth it.</p>
</li>
<li>
<p>If I detach saving the info on some bookmarks from publishing them, I could work on them more iteratively. I could easily separate published bookmarks from those not yet published and have an easy way to compile groups of them for my bookmarks posts.</p>
</li>
</ul>
<p>Well, that’s a lot!</p>
<h2 id="what-im-planning">What I’m Planning</h2>
<p>As I’m using Astro, I wondered how should I approach this. I think <a href="https://docs.astro.build/en/guides/content-collections/">content collections</a> sound the best.</p>
<p>I’ll need to come up with a good structure for everything.</p>
<p>How do I store the common metadata? In separate <code>.json</code> files per metadata type, with the bookmarks aliasing things to mention them? Or should I do it the other way, and gather things from the bookmarks instead?</p>
<p>How do I want to store a single bookmark? Should they be also in <code>.json</code>? One file per bookmark? Or maybe they could even be <code>.mdx</code>, allowing to add more elaborate descriptions, potentially with examples, if needed?</p>
<p>Do I want to store the description of a bookmark alongside its metadata, or only in the compilation posts?</p>
<p>Do I want to have some basic CMS that could simplify adding bookmarks significantly? Or just have some simple template and then just copy and paste stuff?</p>
<p>Should the list of bookmarks exist inside my blog’s repo, or should I maybe even create a separate package for them?</p>
<p>As you can see, I’m not a stranger to feature creep, haha.</p>
<p>Perhaps, I could start small, and work iteratively on something that is good enough from the get-go, and later build on top of it.</p>
<h2 id="what-do-you-think">What Do You Think?</h2>
<p>I’m planning to document how I iterate on this in my blog, with this being the first post in the series. As usual, I’m open to any feedback!</p>
<p>Do you read the lists of bookmarks that I post? Do you like the way I do it now? Am I too ambitious with what I want to do?</p>
<p>Do you post links in your blog? Is there something you are using to keep track of them? Would you change something in how you do it?</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113466763868137714">on Mastodon</a>!</p>I Will Not Delete My Twitter Accounthttps://blog.kizu.dev/i-will-not-delete-my-twitter-account/https://blog.kizu.dev/i-will-not-delete-my-twitter-account/I was working on a different post today, but I got too deep into looking for a good example, realizing a bit too late that I won’t finish it today. So let me just improvise a quick post about a thing I have been thinking about for quite a while.Tue, 12 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — transformation</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>I was working on a different post today, but I got too deep into looking for a good example, realizing a bit too late that I won’t finish it today. So let me just improvise a quick post about a thing I have been thinking about for quite a while.</p>
<p>Here it is: <strong>I won’t delete my twitter account.</strong></p>
<p>For a few years now, twitter is not <a href="https://en.wiktionary.org/wiki/Nazi_bar">a place</a> you want to be at. Some people left it a long time ago. Some, for some reason, are fleeing it only now.</p>
<p>Many people talk about how they delete their accounts there. That’s ok! But that’s not what I will do.</p>
<p>I will not contribute to the <a href="https://en.wikipedia.org/wiki/Link_rot">link rot</a>.</p>
<p>That’s one of the principles that I try to follow. We need to keep the Web interconnected. With over two decades on the Web, I saw many social networks die, their owners closing them up and removing all the content. I’m sick of it.</p>
<p>Twitter might as well die. In many senses, the links to it are already dead: a required sign-in, non-existent API. I removed all links to it from my site more than a year ago. I stopped linking to it, I stopped reading it. I stopped posting there.</p>
<p>If twitter goes away completely — so be it, but <em>I</em> won’t contribute to these links breaking.</p>
<p>The contribution of me deleting my account — whatever it could be — is not worth the harm that will be there from the broken links.</p>
<p>Yes, I have an archive of all content there, and I could host the content on my site (and, maybe, one day I’ll do so), but that won’t change a thing.</p>
<p>So, no, I won’t delete my account, but I am ok with it dying.</p>
<p>And if you’re planning to delete yours: I understand, but I recommend reading into how to do it properly before doing it haphazardly.</p>
<p>I don’t have any links about this (I will gladly add them if anyone shares them with me), but the general idea is that if you delete it, the username will become free, and anyone could take it up. The more followers you have, the higher the chance this will happen, with your username’s prominence being abused for spam, harassment, or even social-engineered attacks. There might be a good way to get rid of it but reserve the name — but, again, I don’t know the details. Send them to me!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113472579468129567">on Mastodon</a>!</p>Observation: Inherited Visibility Transitionhttps://blog.kizu.dev/inherited-visibility-transition/https://blog.kizu.dev/inherited-visibility-transition/Do not use `transition: all` in CSS. Just don’t. I won’t go into all the details today about why it’s bad, but I will share one of the many issues it can cause. Let’s quickly focus on its interaction with the `visibility` property, specifically how transitions work with its inheritance.Wed, 13 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Mammal Hands — Quiet Fire</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Do not use <code>transition: all</code> in CSS. Just don’t (unless you are prototyping something, and will 100% remove it later). I won’t go into all the details today about why it’s bad (if I want to write about it well, I’ll need to do more research), but I will share one of the many issues it can cause.</p>
<p>Let’s quickly focus on its interaction with the <a href="https://drafts.csswg.org/css-display/#visibility"><code>visibility</code></a> property, specifically how transitions work with its inheritance.</p>
<h2 id="the-problem">The Problem</h2>
<p>Look at this example, and focus or hover the button inside, then unhover or blur it.</p>
<p><a href="https://blog.kizu.dev/inherited-visibility-transition/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & > </span><span style="color:#79B8FF">button</span><span style="color:#E1E4E8">:not(:hover, :focus-visible) + </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#85E89D"> em</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> transition</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">all</span><span style="color:#79B8FF"> 2</span><span style="color:#F97583">s</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">>Hover or focus me!</</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Some <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>hidden</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> text!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<div class="aside-wrapper">
<aside>
It might be more obvious what is happening in this minimal example.
<p>In practice, these two rules would likely come from two different components.</p>
<p>One wants to just hide the content, like a dropdown or a popover, and another takes the shortcut of applying an <code>all</code> transition for some state, completely not related to <code>visibility</code>.
</p></aside><p></p>
</div>
<p>If you’re not familiar with how <code>visibility</code> property works, this could be confusing. Like, shouldn’t it be not visible when the parent is not? Well, I wrote an article about this two years ago: <a href="https://kizu.dev/restoring-visibility/">“Obscure CSS: Restoring Visibility”</a>.</p>
<p>In short, unlike <code>display</code> or <code>opacity</code>, it is possible to restore the <code>visibility</code> on the descendent elements! And because <code>visibility</code> is an <em>inherited</em> property, when the parent’s value changes, it inherits onto all the elements inside it.</p>
<p>What happens with a descendent element that has <code>transition: all</code>? That inherited value will be animated!</p>
<h2 id="animating-visibility">Animating Visibility</h2>
<p>And due to the particular way a transition for <code>visibility</code> works, it will be visible for some time after we move the hover/focus away from the button in the example. Let me quote <a href="https://www.w3.org/TR/web-animations/#animating-visibility">the specs</a>:</p>
<div class="aside-wrapper" style="--span: 3">
<aside>
Fun fact: at some point in the past, this was not the case.
<p>It was harder to animate things like <code>opacity</code> alongside <code>visibility</code>, as we had to manually define different values of <code>transition-delay</code> to it.</p>
<p>Now — it works nicely.
</p></aside><p></p>
</div>
<blockquote>
<p>For the <code>visibility</code> property, <code>visible</code> is interpolated as a discrete step where values of <em>p</em> between 0 and 1 map to <code>visible</code> and other values of <em>p</em> map to the closer endpoint; if neither value is <code>visible</code> then discrete animation is used.</p>
</blockquote>
<p>That means that while the transition is happening, the element is hidden only when the value is right at zero, and is visible at all other times.</p>
<h2 id="what-should-we-do">What Should We Do?</h2>
<p>Not use <code>transition: all</code>. Use only the necessary list of properties you need to animate.</p>
<p>If you need to have many of them, instead of repeating the easing, duration, and delay, omit the property and then add the <code>transition-property</code> longhand:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">em</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> transition</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> 0.3</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> linear</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> transition-property</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">color</span><span style="color:#E1E4E8">, transform, opacity;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<h2 id="there-is-more-but-later">There is More (But Later)</h2>
<p>There are many other reasons why <code>transition: all</code> is bad, but a proper explanation would need more research and would result in a bigger post: thus this is an <a href="/tags/observation">“observation”</a>.</p>
<p>As it goes, I did also stumble upon a potential browser bug that I’ll need to research, and then fill that is related to this observation.</p>
<p>I’ll try to do both of these later at some point. I hope even this shorter post will be useful to you.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113478050811099015">on Mastodon</a>!</p>A good way to hide non-defined custom elementshttps://blog.kizu.dev/non-defined-custom-elements/https://blog.kizu.dev/non-defined-custom-elements/This is a very short post about a thing that I have wanted to share for quite a while. I am pretty certain that someone already wrote about this at some point, but hey. There is so much content everywhere that it might be useful to repeat stuff, making it more likely someone will stumble upon a solution to their problem.Thu, 14 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>BimBamBoom — Shinzo BakuBaku Ochokochoi</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>This is a very short post about a thing that I have wanted to share for quite a while. I am pretty certain that someone already wrote about this at some point, but hey. There is so much content everywhere that it might be useful to repeat stuff, making it more likely someone will stumble upon a solution to their problem. And if you know other articles about this topic: please, let me know!</p>
<div class="aside-wrapper" style="--span: 3">
<aside>
This is also the second post in a row where I wrote something about that I encountered in some way while working: I am trying to note things that might not be too obvious and worth sharing. Thanks to the need to post one post a day this November, this is easy to do, haha.
</aside>
</div>
<h2 id="the-problem">The Problem</h2>
<p>Let me show the problem in an example (refresh the page if you want to see how the slow element is defined with a delay).</p>
<p><a href="https://blog.kizu.dev/non-defined-custom-elements/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">fast-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">slow-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">undefined-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(:defined) {</span></span>
<span class="line"><span style="color:#6A737D"> /* Bad; don’t do this. */</span></span>
<span class="line"><span style="color:#79B8FF"> visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example1"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Fast:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Slow:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Undefined:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#B392F0"> MyCustomElement</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> HTMLElement</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> connectedCallback</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">attachShadow</span><span style="color:#E1E4E8">({ mode: </span><span style="color:#9ECBFF">'open'</span><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.shadowRoot.textContent </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> 'Defined!'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF"> 'fast-element'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> MyCustomElement</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#B392F0"> setTimeout</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF"> 'slow-element'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> MyCustomElement</span><span style="color:#E1E4E8"> {}</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8"> }, </span><span style="color:#79B8FF">2000</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#6A737D"> // Nothing for the undefined one, duh.</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>All three have the same styles applied to them, and you can see how it works. Or, rather, it does not.</p>
<p>Without a fix, if an element is never defined, the fallback content will never be shown. This could happen for many different reasons: starting from any random JS error that prevents it from happening, and ending in a user having JS disabled in their browser. Or, in my case, just forgetting to define the element.</p>
<p>And when an issue like this happens — the element ends up being not visible and not accessible.</p>
<h2 id="animated-solution">Animated Solution</h2>
<p>One possible fix that I like: use an animation that would start from the element being hidden, and then, after some delay, it will reveal the fallback regardless (refresh the page to see the example in action):</p>
<p><a href="https://blog.kizu.dev/non-defined-custom-elements/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@keyframes</span><span style="color:#FFAB70"> --not-defined</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> from</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.example2</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">fast-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">slow-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">undefined-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(:defined) {</span></span>
<span class="line"><span style="color:#79B8FF"> animation</span><span style="color:#E1E4E8">: --not-defined </span><span style="color:#79B8FF">0</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> 3</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> both</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Fast:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Slow:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Undefined:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>I saw other approaches to that, like having something what detects if JS is enabled, but these kinds of approaches will not help with the JS error edge case.</p>
<h2 id="future-alternative-starting-style">Future Alternative <code>@starting-style</code></h2>
<p>In the future, when @starting-style will be more widely available, we could use it instead: the following example will work only in <a href="https://caniuse.com/mdn-css_at-rules_starting-style">browsers that support it</a>. And when they do boot support it, the styles won’t apply at all, which is also ok, as I always see this technique of hiding contents until defined as an enhancement, everything will still work without it, it just won’t be as pretty.</p>
<p><a href="https://blog.kizu.dev/non-defined-custom-elements/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">fast-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">slow-element</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">undefined-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(:defined) {</span></span>
<span class="line"><span style="color:#79B8FF"> transition</span><span style="color:#E1E4E8">: visibility </span><span style="color:#79B8FF">0</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> 3</span><span style="color:#F97583">s</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">starting-style</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example3"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Fast:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">fast-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Slow:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">slow-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Undefined:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">>Fallback</</span><span style="color:#85E89D">undefined-element</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<h2 id="final-words">Final Words</h2>
<p>This case is a thing that I often see people not doing: not considering the failing states of something they implement.</p>
<p>It is always a useful habit: to ask yourself “What is the worst-case scenario?” when doing something as drastic as hiding content.</p>
<p>I am in no way an expert in custom elements. If you know any downsides of my approach or a better way to shove the same: please, let me know!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113483786835419624">on Mastodon</a>!</p>The Problem of Embeddable Interactionshttps://blog.kizu.dev/embedded-interactions/https://blog.kizu.dev/embedded-interactions/When I created this blog, I implemented the same thing I did on my main site: a custom element that links to the Mastodon post where I shared the link to the post, and which also shows the number of replies, favorites, and boosts. I saw others implement this as well. Now, people are also adding the same for reactions on bluesky as well. I won’t do it.Sat, 16 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Novo Amor, Gia Margaret — No Fun</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="what-im-talking-about">What I’m Talking About</h2>
<p>When I created this blog, I implemented the same thing I did on my main site: a custom element that links to the mastodon post where I shared the link to the post, and which also shows the number of replies, favorites, and boosts.</p>
<div class="aside-wrapper" style="--span: 3">
<aside>
That said, I still question myself: do I even need these? I don’t like the tendency to strive for bigger numbers, and I often feel bad about some of my articles that I think deserve a better reception.
<p>All these numbers rarely reflect the effort that was put into some articles.
</p></aside><p></p>
</div>
<p>It is very primitive (so there is no real point in sharing its code yet), but I have some plans to improve it.</p>
<p>One thing I <em>do not</em> plan: embedding the comments and userpics of the people who reacted to the posts.</p>
<p>I did think about this for quite a while. I saw others implement this: pulling as much data as they can, showing all the comments people leave to their Mastodon posts, showing all the faces of people who “liked” the post. Now, people are also adding the same for reactions on bluesky as well.</p>
<p><strong>I won’t do it.</strong></p>
<h2 id="why-not">Why not?</h2>
<p>For me, this is an issue of expectations and consent.</p>
<p>I see a difference between publishing something on a website, and an interaction that is happening in a social network.</p>
<p>When I look at some post in Mastodon, I do not usually consider that a reply to it, or me boosting or favoriting it, will be broadcast to everyone. Personally, I do not care much, but I can see how someone more concerned with their privacy could not expect their userpic be shown under someone’s post. In most cases, this can be harmless. But what about the edge cases?</p>
<p>It is easy to be ok with your name under someone’s post in Mastodon — where it is visible only if you’d explicitly go look who did interact with it.</p>
<p>Compare this with your userpic or username clearly visible on the page with some content.</p>
<p>Yes, the information about the interaction is public, but I can see the difference in the perception of privacy, and the potential impact.</p>
<p>If your interaction is automatically displayed this way, often you won’t even know about it. Most Mastodon posts that are used to pull these interactions do not have anything stated in them about this.</p>
<h2 id="can-we-improve-this">Can We Improve This?</h2>
<h3 id="comments">Comments</h3>
<p>When I was thinking about whether there is a good way to display comments this way, I decided that if I did it, I would use the boosting feature in Mastodon.</p>
<p>Basically, by default, no comments are pulled into the post. If you boost it from your account — only then it could be included. By boosting it in Mastodon, you’re communicating that you’re sharing the comment further.</p>
<p>This makes it also a good pre-moderation tool: comments are <em>not</em> displayed by default under your post, and require your explicit action to be added there. “Favorites” could also be used this way, but it feels a bit too easy to misuse.</p>
<p>Another thing that could be considered: respecting the “quiet public” (as Mastodon calls it now, previously “unlisted”) privacy setting.</p>
<p>Even with boosting, I probably won’t ever display an unlisted post — after all, their author explicitly opts out of it being too public.</p>
<h3 id="favorites-and-boosts">Favorites and Boosts</h3>
<p>With favorites and boosts, it is much harder to gauge when they can be safely displayed. The closest thing to use could be the <a href="https://docs.joinmastodon.org/entities/Account/#discoverable">“discoverable”</a> flag from the account data, likely, alongside the <a href="https://docs.joinmastodon.org/entities/Account/#noindex">“noindex”</a> one, and probably the <a href="https://docs.joinmastodon.org/entities/Account/#locked">“locked”</a> one.</p>
<p>If I were to implement something like that, I wouldn’t show the interaction if there is any indication that the author didn’t want their content to be shared more widely. Actually, this is likely something that could also be considered for displaying comments as well.</p>
<p>With this in mind, the number of favorites and boosts could be displayed as “N likes, including from this person and that person”.</p>
<h2 id="final-words">Final Words</h2>
<p>Even though I did propose some ways this feature could be implemented in a slightly more respectful way, I will likely not do it for my blog (and maybe even remove the interaction counters whatsoever).</p>
<p>But if you’re already displaying others’ Mastodon and bluesky interaction on your blog — I recommend you to think about it, and see if you could consider what I wrote about above.</p>
<p>Also, perhaps it is just me overthinking things, as usual, but hey. If you also ever had thoughts about this, or felt a bit uncomfortable when seeing these integrated interactions — I’ll be happy to hear your ideas about it!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113495053412100923">on Mastodon</a>!</p>Repetition and Attributionhttps://blog.kizu.dev/repetition-and-attribution/https://blog.kizu.dev/repetition-and-attribution/Today, I want to talk about two things, in the context of writing articles and sharing knowledge in general. One of them we don’t need to be afraid of, and another we need to do as often as possible. The first one is repetition. The second one — attribution. It could seem like an odd pair, but I’ll try to explain how they are connected.Sun, 17 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Tenniscoats — 風の歌</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Today, I want to talk about two things, in the context of writing articles and sharing knowledge in general. One of them we don’t need to be afraid of, and another we need to do as often as possible.</p>
<p>The first one is repetition. The second one — attribution. It could seem like an odd pair, but I’ll try to explain how they are connected.</p>
<h2 id="repetition">Repetition</h2>
<p>We should not be afraid to repeat others and ourselves. When thinking about an idea for a blog post, article, talk, or anything else, often a stray thought can appear: what if someone did this already — and did this better, so why bother?</p>
<p>This is the wrong way to think about ideas and knowledge. A question like this can have two answers:</p>
<ol>
<li>
<p>“No, no one did write about it.” If you can verify it, this is a great answer! But a boring one. Well, in the context of this article: if you know that what you’re going to share is novel, there should not be any hesitation. Go ahead and do it!</p>
</li>
<li>
<p>“Yes, someone did already share it.” Ok, but that does not mean that it should stop <em>there</em>. This is a much more interesting position to be, and a big part of what I want to talk about.</p>
</li>
</ol>
<h3 id="unknowingly-repeating">Unknowingly Repeating</h3>
<p>It might happen that you could not find prior art and decided to share something. It is totally fine if you discover later that someone did do the same thing! <a href="https://en.wikipedia.org/wiki/Multiple_discovery">“Multiple discovery”</a> is possible, and even if someone did come up with the same concept before, it is rarely expressed in the same way. Everyone is different, and you’ll likely still contribute something.</p>
<p>Take the “space toggles” as an example. Multiple people discovered them at different times, and shared them in one way or another. I compiled a timeline of this in the <a href="https://kizu.dev/cyclic-toggles/#was-this-always-possible">“Was This Always Possible?”</a> section of my <a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a> article.</p>
<p>Don’t be afraid to publish something just because you’re afraid that someone in the past already did so.</p>
<p>If they did — and you will later get to know about it — you can always, you know, <em>attribute</em> them, and then spend some time looking at what they did, and how it is different from your perspective.</p>
<p>It is always fun to look at these differences, and look at the same thing from others’ perspective. Often, an unexpected angle could bring a new insight.</p>
<h3 id="continuing-the-work">Continuing the Work</h3>
<p>Occasionally, you can get this insight based on others’ work and don’t think much of it. You can read someone’s article, see a small potential for improvement, and think that this is too small of a thing to share.</p>
<p>But there is no such thing as a “too small to share”. At the minimum, you can share it on your social network. Or — explore the idea further. If the author missed this small part, what else could there be? What if you played with their code more, tried to understand it, and maybe integrated it into your work?</p>
<p>All of this could lead to more discoveries or new use cases. Often, some articles can be too theoretical, with not many practical examples. It can explain why some techniques work, but not go into details of when they can be applied, or how they can fit into your workflow. By exploring it, you can, at least, share it as a case study. Or you will eventually discover something more interesting!</p>
<p>Many discoveries have others’ work at their foundation. You don’t have to be that foundation, but you can use it to build something new on top of it.</p>
<h3 id="rephrasing">Rephrasing</h3>
<p>Even if you don’t have anything new <em>at all</em> to say, rephrasing the common knowledge can be really useful!</p>
<p>A radical example is a translation: the same meaning is made accessible for a bigger slice of the world population.</p>
<p>But even without translation, there are multiple ways we can repeat something. Everyone is different and has various mental models of the world, and ways they like to consume information.</p>
<p>Your sources can be too technical or too dry, but you can always reword things, presenting them in a way <em>you</em> like to receive them. Take some CSS specs or an MDN article, and try to think how you would describe it to your friend. Which examples could you make? What specific parts talk to you more than others?</p>
<p>You can focus on one aspect, and dig deeper into it, or you can do the opposite and generalize the text by giving an overview.</p>
<h3 id="just-sharing">Just Sharing</h3>
<p>Even if you don’t introduce much new, in today’s work with the constant flood of information, a repetition can bring something to someone’s attention that they could’ve missed otherwise.</p>
<p>You can just share that you’ve learned something, and describe it in a few words. For example, you could stumble upon a CSS feature from recent years that you somehow missed. You know what? Others could’ve missed it too! If you write about it — even without adding much new — someone else will now stumble upon it too.</p>
<h2 id="attribution">Attribution</h2>
<p>I hope it is obvious to you, but let me be explicit here: when doing all of the above — reading others’ works, sharing what we learned, and building on top of it — <strong>we must attribute our sources</strong>.</p>
<p>In today’s world, where information is so often processed through a grinder into a uniform soulless mess, attributing the sources is something that could make your work stand out.</p>
<p>When you mention another person, you create a connection. Hyperlinks — they’re cool. They provide context, they allow others to read the same thing you read, and they allow others to discover something new.</p>
<p>If you share some links, don’t do it blindly: find out who the author is. Do they have a personal website? Do they have a Mastodon account? What else do they write about? Can you subscribe to their RSS feed?</p>
<p>You have the power to bring attention to others — use it. Now that you know someone by their work, you can elevate them, and multiply the force they put into their work by sharing it with attribution.</p>
<p>If someone did write something, they might have had doubts and anxieties about whether it was worth it, whether their work was novel, and whether anyone was interested in it. When sharing a work with an attribution, you’re not just sharing a link; you point at someone and say, “Look at how this person did a cool thing!”.</p>
<p>I can assure you, that brings joy, and I wish I saw others do this more. I think we’ve gotten much better at it in the last few years.</p>
<h2 id="final-words">Final Words</h2>
<p>Do not be afraid to share what you learned. Use others’ works as an inspiration, and give it back by attributing them properly. If you missed something — you can always edit it later. If someone reminds you about it or shares a link to a similar thing — thank them, attribute it, and consider that you’re in such good company. Others are interested in the same thing that you are!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113500716344287248">on Mastodon</a>!</p>Writing About Experimentshttps://blog.kizu.dev/writing-about-experiments/https://blog.kizu.dev/writing-about-experiments/I often see complaints about people hyping up new web platform features while they’re not yet ready for wide use. I also was on the receiving end of similar complaints. When I publish my articles, I always have plenty of things in mind, not necessarily a set of rules, but rather guidelines and directions that I follow. In this post, I cover some of them.Mon, 18 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haley Heynderickx — Gemini</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="in-response-to">In Response To</h2>
<p>I often see complaints about people hyping up new web platform features while they’re not yet ready for wide use. Like, developers getting tired of hearing about all these shiny new things, and not being able to apply them to their production sites.</p>
<p>One recent article that mentioned this was <a href="https://thomasorus.com/new-css-that-can-actually-be-used-in-2024.html" title=".u-in-reply-to">“New CSS that can actually be used in 2024”</a> by <a href="https://thomasorus.com/">Thomas Loreille</a> from this March. In it, he tries to look at various <em>wider</em> supported features instead. Ironically, in some enterprise environments, even these features you couldn’t, actually, use.</p>
<p>A few days ago, <a href="https://rachelandrew.co.uk/">Rachel Andrew</a> wrote about this (and also mentioned Thomas’ article) in her post <a href="https://rachelandrew.co.uk/archives/2024/11/15/when-is-the-right-time-to-share-our-excitement-about-new-web-features/" title=".u-in-reply-to">“When is the right time to share our excitement about new web features?”</a>, where she looks at this issue from a browser DevRel perspective.</p>
<p>As someone, who regularly writes about the emerging specs and their experimental implementations, I also was on the receiving end of similar complaints.</p>
<h2 id="what-i-do">What I Do</h2>
<p>I am not a browser DevRel. However, I am now a <a href="https://blog.kizu.dev/two-invitations/">member of CSSWG</a> (previously: an invited expert, now a member on behalf of the company I am working in — <a href="https://www.datadoghq.com/">Datadog</a> — as it joined W3C), but I am trying to look at things in the same way I did before, and write about them in the same way.</p>
<p>When I publish my articles, I always have plenty of things in mind, not necessarily a set of rules, but rather guidelines and directions that I follow.</p>
<p>In this post, I cover some of them, and if you want to experiment as well, consider thinking about them too.</p>
<h3 id="browser-support">Browser Support</h3>
<p>This is the most obvious thing: when writing about something that is not widely supported, we must warn others which browsers support something, and if the feature is experimental.</p>
<p>I am not only talking in terms of <a href="https://web-platform-dx.github.io/web-features/">Baseline</a>, but I am glad we are working on standardizing the way we can share this in articles.</p>
<h3 id="current-experimental-version">Current Experimental Version</h3>
<p>When I write about some experimental feature, not only do I mention that it <em>is</em> such, but I prefer to mention which exact browser version I am using.</p>
<p>Both specs and experimental implementations change — it is not guaranteed that the code I share will work after I publish an article.</p>
<p>We always should have a date somewhere on the page with a post we share, but having an exact browser version is very convenient too, especially if you’d want to later report a regression.</p>
<h3 id="adding-screen-recordings">Adding Screen Recordings</h3>
<p>When sharing live examples of the new code, I almost always provide a screen recording of them, which is shown if the reader is looking at the page in a browser that does not support the required CSS feature. This fulfills multiple things:</p>
<ol>
<li>
<p>A user without a browser with the feature in question can still see how it works. This can be especially helpful on mobile devices, where you can’t easily switch the browser to the experimental one with some feature flag turned on.</p>
</li>
<li>
<p>It records the way something works in case it changes. Even if the code example breaks due to the implementation change, it will still be possible to see how the example was intended to work. You can also consider it to be a kind of visual regression testing: if something breaks or changes, it will be possible to use the recording for comparison. And with the exact browser version, it can be used in browser bug reports.</p>
</li>
<li>
<p>Finally, a minor bonus: for highly interactive examples, a video like this provides an alternative way of experiencing this interactivity. By watching the video, you’ll know what I wanted to show with the added interactivity, and it can be helpful if that interactivity is inaccessible otherwise, like with the <code>resize</code> CSS property on a mobile device (where you’d likely also won’t have enough space to test the responsiveness). I am even thinking of maybe adding this to articles that do not have browser limitations, but as this is extra work, I never find extra spoons for this.</p>
</li>
</ol>
<h3 id="not-writing-tutorials">Not Writing Tutorials</h3>
<p>I rarely intend the code I share in my articles to be easy to copy. Usually, I display only the necessary parts to explain what they do, and I do not always work on making it reusable.</p>
<p>As Rachel writes:</p>
<blockquote>
<p>You often don’t need to write huge guides, how tos, and tutorials for experimental things.</p>
</blockquote>
<p>I do not consider myself a good teacher, and I am not the best at organizing things. I adore people like <a href="https://thinkdobecreate.com/">Stephanie Eckles</a> who can distill some technique into a nice reusable snippet, or <a href="https://www.joshwcomeau.com/">Josh W. Comeau</a> who can explain things in plain language with great interactive examples.</p>
<p>Me? I like to poke at the code with a stick, see what happens, and then share it alongside my thoughts about it.</p>
<h3 id="not-sharing-as-tips">Not Sharing as Tips</h3>
<p>This is something where I can often agree with the critics of the experimental features hype: we should not present new tech as “tips”. If something is a foundational CSS feature but does not work everywhere, you cannot, with good conscience, recommend it as a solution.</p>
<p>I notice that many authors play the “algorithm” by sharing very obnoxiously experimental demos as “CSS Tips”, and I find it misleading and harmful. Don’t do this, please.</p>
<h3 id="thinking-about-the-future">Thinking About the Future</h3>
<p>When I write about new features, I always look into the future. A day will come when we will be, finally, able to use all of this new goodness in production.</p>
<p>By experimenting with all of that today and writing about it, I believe I am bringing this day a bit closer.</p>
<p>Browsers implementors and spec editors need feedback from authors from many different angles:</p>
<ul>
<li>Is there someone who needs this feature?</li>
<li>Are there issues with the way the feature works?</li>
<li>Is its API convenient?</li>
<li>How does it play with other features?</li>
<li>What are edge cases?</li>
<li>Could we change something small, and get a quick win while we’re in the context of working on this feature?</li>
<li>Is there something that it can unlock that was not possible before?</li>
</ul>
<p>If you read my articles about <a href="https://kizu.dev/tags/anchor_positioning/">anchor positioning</a> or <a href="https://kizu.dev/tags/scroll_driven_animations/">scroll-driven animations</a>, you’d likely see how I try to cover most of these questions with what I write.</p>
<p>I experiment, fill browser bugs, provide feedback in CSSWG issues, and share the potential techniques that will be possible with the new experimental features.</p>
<p>When the future becomes the present, we will have it in better shape — and with all these techniques ready to be applied. After all, some techniques that use existing features can take years to discover, my <a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> or <a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a> being good examples.</p>
<h2 id="final-words">Final Words</h2>
<p>The last few years were very productive for CSS: both in terms of what goes into specs, and what browsers implement. Some authors look at all of this and think that it is too much. Some are frustrated that we cannot use all of this today.</p>
<p>We are in an interesting spot: after these years of progress on CSS, much of it started to become wider and wider available.</p>
<p>My hypothesis is that many people have a delayed response — and a habit — of being frustrated about the limited capabilities of CSS.</p>
<p>I am only excited. With each day, browser support for container queries, <code>:has()</code>, <code>@layer</code>, <code>@property</code>, and countless other “newly available” CSS features improve.</p>
<p>And as someone who tries to follow almost everything that authors write about CSS, as features become more available, we get more articles about them.</p>
<p>When a feature lands in all browsers, people write about it. The longer a feature is available, the more people start using it in production and also write about it.</p>
<p>It is a long process, and we can be frustrated that the bright future is not there yet. But it will be there. I believe in it, and in us, who are trying to bring it closer.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113506263052911112">on Mastodon</a>!</p>Recent CSS Bookmarks 20: Just Three Linkshttps://blog.kizu.dev/recent-css-bookmarks-020/https://blog.kizu.dev/recent-css-bookmarks-020/Writing one post a day is hard! I had an idea for an observation but did not have an opportunity to write it up properly. Come on, me, these should not take that long! That means I am falling back to the idea I reserved for cases like this one: where I cannot quickly come up with a post on the spot. That is: share just a few recent bookmarks!Tue, 19 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — Mirror</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>Writing one post a day is hard! I had an idea for an <a href="https://blog.kizu.dev/tags/observation/">observation</a> but did not have an opportunity to write it up properly. Come on, me, these should not take that long!</p>
<p>That means I am falling back to the idea I reserved for cases like this one: where I cannot quickly come up with a post on the spot. That is: share just a few recent bookmarks!</p>
<p>Here they are! This time, they’re ordered from longer to shorter.</p>
<ul>
<li>
<p><a href="https://ishadeed.com/article/overflow-clip/">“Overflow Clip”</a> by <a href="https://ishadeed.com/">Ahmad Shadeed</a> — an article explaining the <code>clip</code> value of the <code>overflow</code> property and where it can be used. Fun fact: the ideas for some of my experiments with scroll-driven animations, that later became <a href="https://kizu.dev/fit-to-width-text/">“Fit-to-Width Text”</a> and <a href="https://kizu.dev/position-driven-styles/">“Position-Driven Styles”</a> articles, came from me reading the <a href="https://drafts.csswg.org/css-overflow/#valdef-overflow-clip">specs for <code>overflow: clip</code></a>, specifically its difference from <code>hidden</code>. The <code>clip</code> value is cool, and <a href="https://caniuse.com/mdn-css_properties_overflow_clip">well-supported</a> — play with it!</p>
</li>
<li>
<p><a href="https://fullystacked.net/stretch/">“The <code>stretch</code> keyword: a better alternative to <code>width: 100%</code> in CSS?”</a> by <a href="https://fullystacked.net/">Ollie Williams</a> — a post about the <a href="https://drafts.csswg.org/css-sizing-4/#valdef-width-stretch">new standard sizing value</a>, which is now implemented in Chrome, and will come as a replacement for <code>-moz-available</code> and <code>-webkit-fill-available</code> (and could be potentially used in more contexts).</p>
</li>
<li>
<p><a href="https://css-tip.com/steps/">“How to correctly use <code>steps()</code> with animations”</a> by <a href="https://css-articles.com/">Temani Afif</a> — a quick tip about the <code>steps()</code> easing function for CSS animations, specifically its <code>jump-none</code> value for <code><step-position></code>. This is something I did not play much, so it was new to me! And I can already remember how some places where I struggled before could’ve been solved by this tiny trick. I recommend reading <a href="https://drafts.csswg.org/css-easing/#funcdef-steps">the specs for <code>steps()</code></a> — there are some nice <em>animations</em> that demonstrate how its different values work!</p>
</li>
</ul>
<p>I wonder: have you noticed a common theme between these three bookmarks? Please tell me if you did spot it!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113511982256008699">on Mastodon</a>!</p>Transitions of Inherited Propertieshttps://blog.kizu.dev/transitions-of-inherited-properties/https://blog.kizu.dev/transitions-of-inherited-properties/When I shared my “Observation: Inherited Visibility Transition” post, I mentioned that there was a CSS bug I encountered that I wanted to research and maybe fill later. Well. I thought it would be a quick thing, making into a quick post. Apparently, not!Wed, 20 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Stage Kids — The Seven Pillars of Gulu</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>When I shared my <a href="/inherited-visibility-transition/">“Observation: Inherited Visibility Transition”</a> post, I mentioned that there was a CSS bug I encountered that I wanted to research and maybe fill later.</p>
<p>Well. I thought it would be a quick thing, making into a quick post. Apparently, not!</p>
<h2 id="the-problem">The Problem</h2>
<p>In that post, I talked about <code>visibility</code> and inheritance. The bug that I wanted to report was related to how values are inherited: I noticed a difference between how Firefox does it, and how Chrome and Safari do it.</p>
<p>When there are <em>multiple</em> nested elements with a transition for an inherited property, Firefox applies the transition immediately for all of them, while other browsers stagger it.</p>
<p>Looking if this is already reported, I found the following:</p>
<ul>
<li>A Webkit bug report <a href="https://bugs.webkit.org/show_bug.cgi?id=46041">“CSS inheritance delayed when transition duration on parent and child elements”</a> from 2010 by <a href="https://s4y.us/">Sidney San Martín</a>.</li>
<li>A Chromium bug report <a href="https://issues.chromium.org/issues/40337057">“CSS transitions inherit incorrectly when specified both an element and its ancestor”</a> from 2013.</li>
<li><a href="https://github.com/w3c/csswg-drafts/issues/5324">“Undesired behaviour - transition of inherited value happening in sequence”</a> CSSWG issue from 2020 by <a href="https://github.com/meirkoen">Meir Cohen</a>. Meir also opened two bug reports alongside it:
<ul>
<li>A Chromium bug report <a href="https://issues.chromium.org/issues/40709392">“CSS Transition of inherited value sequenced across children elements”</a>.</li>
<li>A WebKit bug report <a href="https://bugs.webkit.org/show_bug.cgi?id=214352">“CSS Transition of inherited value sequenced across children elements”</a>.</li>
</ul>
</li>
<li>A Chromium bug report <a href="https://issues.chromium.org/issues/353738500">“CSS font size transition is slower if the element inherits it”</a> from 2024.</li>
</ul>
<p>Almost in every case, people seem to prefer the way Firefox handles it (applying immediately across all elements), rather than how Safari and Chrome do it (restarting the transition of the inherited property on every frame).</p>
<h2 id="not-a-bug">Not a Bug?</h2>
<p>The bigger problem: this might not be a bug, even though this might be a significant interop issue. It is obvious that multiple people have stumbled upon this over the last 14 years. If I would not look up for existing bug reports, I would be another person reporting the same issue.</p>
<p>But is it a bug? This is one of those cases, where <a href="https://drafts.csswg.org/css-transitions/#starting">CSS specs</a> explicitly say that the browsers can do whatever they want:</p>
<blockquote>
<p>This specification does not define when computed values are updated, beyond saying that implementations must not use, present, or display something resulting from the CSS cascading, value computation, and inheritance process without updating the computed value (which means merely that implementations cannot avoid meeting requirements of this specification by claiming not to have updated the computed value as part of handling a style change).</p>
<p>[…]</p>
<p>Since this specification does not define when a style change event occurs, and thus what changes to computed values are considered simultaneous, authors should be aware that changing any of the transition properties a small amount of time after making a change that might transition can result in behavior that varies between implementations, since the changes might be considered simultaneous in some implementations but not others.</p>
</blockquote>
<p>So, according to specs… this is not a bug?</p>
<h2 id="still-a-problem">Still a Problem</h2>
<p>Looking into the history of the transition specs — this last part was there already in 2009. Here it is from <a href="https://www.w3.org/TR/2009/WD-css3-transitions-20091201/#starting">CSS3 specs</a>:</p>
<blockquote>
<p>When the value of an animatable property changes, implementations must decide what transitions to start based on the values of the <code>transition-property</code>, <code>transition-duration</code>, <code>transition-timing-function</code>, and <code>transition-delay</code> properties at the time of the change. Since this specification does not define what property changes are considered simultaneous, authors should be aware that changing any of the transition properties a small amount of time after making a change that might transition can result in behavior that varies between implementations, since the changes might be considered simultaneous in some implementations but not others.</p>
</blockquote>
<p>This was even before CSS animations were a thing! Not mentioning what we have today, and what is planned (view transitions, scroll-driven animations, and so on).</p>
<p>Maybe it is time to revisit it?</p>
<p>Given the interop inconsistency is there for so many years, on one hand, it might be tricky to change, on the other — different browsers already treat it differently, and the world did not explode.</p>
<p>If anything, I think I could even prefer having a separate property that would control how such a transition happens! I still think that the way Firefox behaves is the correct one, but I can also see how what Safari and Chrome do today can be potentially used in some techniques.</p>
<h2 id="lets-reopen-the-issue">Let’s Reopen the Issue</h2>
<p>After thinking about this, I decided to reopen <a href="https://github.com/w3c/csswg-drafts/issues/5324">the issue</a> that I mentioned in the beginning. I don’t like to have inconsistencies like that in the web platform, and the longer we keep them, the higher chance they will impact something in the future, making it much harder to implement new things consistently and in an interoperable manner.</p>
<p>Please participate in this issue if you did also stumble upon this in the past!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113517751977816118">on Mastodon</a>!</p>Recent CSS Bookmarks 21: Anchor Positioninghttps://blog.kizu.dev/recent-css-bookmarks-021/https://blog.kizu.dev/recent-css-bookmarks-021/Anchor positioning is cool! And there were many articles and posts about anchor positioning since I last mentioned it in my bookmark posts. Here they are!Thu, 21 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>toe — グッドバイ</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>Anchor positioning is cool! And there were many articles and posts about anchor positioning since I last mentioned it in my bookmark posts. Here they are!</p>
<aside class="warning">
While both Apple and Mozilla are working on anchor positioning right now, most of the examples from these articles will work only in Chrome (and/or Chrome Canary) for now.
</aside>
<ul>
<li>
<p><a href="https://utilitybend.com/blog/lets-hang-an-intro-to-css-anchor-positioning-with-basic-examples">“Let’s hang! An intro to CSS Anchor Positioning with basic examples”</a> by <a href="https://utilitybend.com/">Brecht De Ruyte</a> — a good introductory article about anchor positioning that compares two different ways we can achieve the same thing, and looks into some other details.</p>
</li>
<li>
<p><a href="https://anchoreum.com/">“Anchoreum”</a> by <a href="https://thomaspark.co/">Thomas Park</a> — a fun game that teaches anchor positioning. I did not yet finish it, but it might be a good way to learn how some of its aspects work if you’re not yet familiar with it.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/9816">“Layered positioning”</a> by <a href="https://github.com/Crissov">Christoph Päper</a> — a CSSWG issue about how we could make an anchored element match the layer of its anchor. I <a href="https://github.com/w3c/csswg-drafts/issues/9816#issuecomment-2492457219">commented there today</a> with two small proposals, the ideas for which I got after a <a href="https://front-end.social/@mayank/113376766689246458">mastodon thread</a> started by <a href="https://www.mayank.co/">Mayank</a>. Check out the thread itself for a demo of another anchor positioning use case: animated focus ring. I mentioned this use case in <a href="https://www.youtube.com/watch?v=ZC_WS05t2lI">my CSSDay talk</a>, but did not have an opportunity to finish a draft of an article about it yet.</p>
</li>
<li>
<p><a href="https://www.oddbird.net/2024/11/18/anchor-position-yearbook/">“Anchor Positioning Is Disruptive”</a> by <a href="https://jamessw.com/">James Stuckey Weber</a> — a post about an interesting use case for anchor positioning, a bit similar to the one with the sidenotes. See also <a href="https://css-irl.info/another-anchor-positioning-demo-multiple-anchors/">“Another Anchor Positioning Demo: Multiple Anchors”</a> by <a href="https://css-irl.info/">Michelle Barker</a>, <a href="https://meyerweb.com/eric/thoughts/2023/09/12/nuclear-anchored-sidenotes/">Nuclear Anchored Sidenotes</a> by <a href="https://meyerweb.com/">Eric Meyer</a>, and the <a href="https://kizu.dev/anchor-positioning-experiments/#sidenotes-layout">“Sidenotes Layout”</a> section of my old <a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a> article.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/custom-range-slider-using-anchor-positioning-scroll-driven-animations/">“Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations”</a> by <a href="https://css-articles.com/">Temani Afif</a> — an article about how we can target pseudo-elements of the range slider with both scroll-driven animations and anchor positioning. The result is very impressive and even uses the technique from the <a href="https://www.bram.us/2023/10/23/css-scroll-detection/">“Solved by CSS Scroll-Driven Animations: Style an element based on the active Scroll Direction and Scroll Speed”</a> article by <a href="https://www.bram.us/">Bramus</a>. I am glad that we now have a proper exploration of this concept, which I shared a year ago in my <a href="https://blog.kizu.dev/input-range-thumb/">“Observation: Range Input’s Thumb and Emerging CSS”</a> post.</p>
</li>
<li>
<p><a href="https://frontendmasters.com/blog/custom-progress-element-using-anchor-positioning-scroll-driven-animations/">“Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations”</a> by <a href="https://css-articles.com/">Temani Afif</a> — a continuation of the previous article, this time applying this method to the <code><progress></code> HTML element.</p>
</li>
<li>
<p><a href="https://piccalil.li/blog/front-end-solution-eyebrow-heading-dots/">“Front-End solution: Eyebrow heading dots”</a> by <a href="https://andy-bell.co.uk/">Andy Bell</a> — a post about a challenge for placing elements on two sides of a wrapping element with a solution that builds on top of my <a href="https://kizu.dev/shrinkwrap-problem/">“The Shrinkwrap Problem: Possible Future Solutions”</a> article that I shared with the author.</p>
</li>
<li>
<p><a href="https://css-irl.info/anchor-positioning-and-the-popover-api/">“Anchor Positioning and the Popover API for a JS-Free Site Menu ”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — an article that looks at various aspects of how we could use anchor positioning with popover API, including a site menu use case.</p>
</li>
<li>
<p><a href="https://css-irl.info/progressively-enhanced-popover-toggletips/">“Progressively Enhanced Popover Toggletips”</a> by <a href="https://css-irl.info/">Michelle Barker</a> — an article about using anchor positioning to progressivly enhance footnotes.</p>
</li>
<li>
<p><a href="https://jschof.dev/posts/2024/9/love-letter-to-the-platform/">“Web components + anchor positioning + popover API = I love the platform”</a> by <a href="https://jschof.dev/">Jim Schofield</a> — a post that looks at how we could build a popover with anchor positioning as a custom element.</p>
</li>
<li>
<p><a href="https://coryrylan.com/blog/flow-charts-with-css-anchor-positioning">“Flow Charts with CSS Anchor Positioning”</a> by <a href="https://coryrylan.com/">Cory Rylan</a> — a post that looks at the flow charts use case for anchor positioning. See also: the <a href="https://kizu.dev/anchor-positioning-experiments/#using-the-connections">“Using the Connections”</a> section of my old <a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a> article.</p>
</li>
</ul>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113523528017981859">on Mastodon</a>!</p>Managing Bookmarks, part 2https://blog.kizu.dev/managing-bookmarks-part-2/https://blog.kizu.dev/managing-bookmarks-part-2/I spent this evening thinking a bit more about what I want to do with my bookmarks. Nothing really done, but this time I experimented with Obsidian to see if it could be a good way to store them, add metadata to them, and so on. I tried a few plugins and, at first glance, managed to get rather close to a good starting point. No code to share yet, but I’ll mention the plugins that I tried.Fri, 22 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>・・・・・・・・・ — shiduka no umi</dd><dt>Current drink:</dt><dd>Camomile & Lavender tea</dd></dl><hr /><p>I spent this evening thinking a bit more about what I want to do with my bookmarks.</p>
<p>Nothing really done, but this time I experimented with <a href="https://obsidian.md/">Obsidian</a> to see if it could be a good way to store them, add metadata to them, and so on.</p>
<p>I tried a few plugins and, at first glance, managed to get rather close to a good starting point. No code to share yet, but I’ll mention the plugins that I tried:</p>
<ul>
<li>
<p><a href="https://github.com/SilentVoid13/Templater">Templater</a> plugin by <a href="https://github.com/SilentVoid13">SilentVoid13</a> is nice, and allows (among other things) setting up a default template per folder, so creating a file in it could fill it with some default metadata. And, potentially, run some scripts. Some other plugins can build on top of this one.</p>
</li>
<li>
<p><a href="https://github.com/mProjectsCode/obsidian-js-engine-plugin">JS Engine</a> plugin by <a href="https://www.moritzjung.dev/">Moritz Jung</a> is fun, and allows running arbitrary JS right inside Obsidian. It is required for some other plugins.</p>
</li>
<li>
<p><a href="https://github.com/mProjectsCode/obsidian-meta-bind-plugin">Meta Bind</a> (also by Moritz) is one such plugin that depends on JS Engine and allows adding various inputs, like buttons, right inside your documents.</p>
</li>
<li>
<p><a href="https://github.com/chhoumann/MetaEdit">MetaEdit</a> plugin by <a href="https://bagerbach.com/">Christian Bager Bach Houmann</a>. I wanted to see if there is an easy way to modify the frontmatter of any current file, as by default Obsidian does not seem to provide a built-in API for this. At first, I encountered a few issues with how it works: I tried using the MetaEdit’s API inside a <code>js-engine</code> fenced block, but it was bugging out. Then, I tried it with Meta Bind — and it worked inside of it!</p>
</li>
</ul>
<p>At this point, what I am planning to do: create a default template with some metadata fields and a button. Then, I could create a new bookmark file, paste the bookmark’s URL into one of the fields, press the button, and it would try and fill the remaining fields automatically for me. In theory.</p>
<p>When I’ll get to something that would work, I’ll post another update. Stay tuned, I guess!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113529209931180717">on Mastodon</a>!</p>Idea: Self-Boosting Image Mastodon Bothttps://blog.kizu.dev/self-boost-bot/https://blog.kizu.dev/self-boost-bot/There is such thing as picture bots that post images every hour. I subscribe to a few of these that post red pandas, and opossums. They’re all cute! While I like these kinds of bots, I noticed several problems with them. In this post, I share my idea for a potential solution of them.Sat, 23 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>MindaRyn — SURVIVE</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Every so often I write down various non-CSS ideas in my notes, which I know I likely won’t ever implement (or maybe will do, but I never know when). This is one example of such an idea: perhaps it could be worth sharing them in the blog.</p>
<p>There is such thing as picture bots that post images every hour. I subscribe to a few of these that post <a href="https://botsin.space/@HourlyRedPanda">red pandas</a>, <a href="https://botsin.space/@RaccoonsHourly">raccoons</a>, and <a href="https://botsin.space/@possumeveryhour">opossums</a>. They’re all cute! Though, with the <a href="https://muffinlabs.com/posts/2024/10/29/10-29-rip-botsin-space/">botsin.space instance going away</a>, I’ll likely need to find another source of these.</p>
<h2 id="the-problems">The Problems</h2>
<p>While I like these kinds of bots (they bring some positivity to a sometimes too sad or technical timeline), I noticed several problems with them:</p>
<ul>
<li>
<p>Digital waste. These bots can regularly post the same image, over and over. While you could set up automatic deletion of old posts, this is still not ideal for various reasons.</p>
</li>
<li>
<p>No way to know whether you saw some image or not. You have to rely on your memory: is this a new picture? Or you saw it, but forgot about it? As the same image can be randomly reposted, that post will be a new one, so you couldn’t use likes or bookmarks to mark those that you already saw.</p>
</li>
<li>
<p>It is difficult to identify an entirely new image. When a new one is added to the dataset, you won’t know if a new random post takes an image from the archive or if that image is a sparkling fresh.</p>
</li>
<li>
<p>The randomness algorithm is frequently flawed, commonly reposting the same image too close to others, or not giving some image a chance for a while.</p>
</li>
</ul>
<h2 id="one-potential-solution">One Potential Solution</h2>
<p>If I were to implement a similar bot (or if you’re thinking about one), here is how I’d try to approach it.</p>
<ol>
<li>
<p>Each image from the dataset should be posted only once. No deletion, and no duplicates.</p>
</li>
<li>
<p>On every iteration, if there is an image in the backlog that was never published, it is published as a new post. If there are multiple images in the backlog, a new one is chosen randomly.</p>
</li>
<li>
<p>Crucial part: once all images from the backlog are published, instead of <em>reposting</em> the old ones, the bot starts <em>boosting</em> old posts. It must boost only an image that it never boosted before, and select one randomly.</p>
</li>
<li>
<p>It should never pick to boost a newly published post until a certain grace period passes.</p>
</li>
<li>
<p>The same grace period is used to un-boost the old boosted posts, making them enter the stack of possible posts to boost next.</p>
</li>
</ol>
<p>We can think of the posts as of multiple stacks of cards: they never duplicate, and we just shuffle them around, making sure we keep things fresh for the duration of the grace period.</p>
<h2 id="benefits">Benefits</h2>
<ul>
<li>
<p>Because the images are never duplicated, this should be much lighter for the servers and the infrastructure. No need to upload duplicate images, as the old ones could be just used.</p>
</li>
<li>
<p>All the interactions stay with the image: if you boosted, liked, or bookmarked a post, you’ll know when it comes again.</p>
</li>
<li>
<p>As even comments will stay, this can allow people to add their input to the posts: add better alternative descriptions, sources, and attribution.</p>
</li>
<li>
<p>Bot authors could use these interactions to improve the posts: the data in them can become the source of truth, and the images could be easily updated with the better descriptions and attribution, or retired if found problematic for some reason.</p>
</li>
<li>
<p>New posts will stand out, as they won’t have the “self-boost” visual. Even more: you could always disable boosts from the bot account, and only receive new images if you’d want to.</p>
</li>
<li>
<p>It might be easier to implement the algorithm, and maybe even keep it for boosting only, while allowing posting new images outside the regular schedule manually. This way, all the necessary data for the algorithm can be contained in the bot’s timeline, making the bot much more simple.</p>
</li>
</ul>
<h2 id="final-words">Final Words</h2>
<p>I never wrote a Mastodon bot. So take my idea with a grain of salt. But I have been sitting on this idea for a few months already, and I still think that it is a good one. Maybe I am wrong! Please let me know if so. And you are welcome to try implementing it — the last time I touched <a href="https://docs.joinmastodon.org/">Mastodon API</a>, it was rather simple.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113533662731010947">on Mastodon</a>!</p>Embedding Pixelfed, part 2https://blog.kizu.dev/embedding-pixelfed-part-2/https://blog.kizu.dev/embedding-pixelfed-part-2/Since my last post about this, I did some progress on embedding Pixelfed images in my blog. There are still many things I want to implement before I could start using this properly, but this seems like a good checkpoint in my work on the feature.Sun, 24 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>This is The Kit — No Such Thing</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><p><img src="pixelfed:739971733249250140/3" alt=""></p>
<p>Look at this squirrel!</p>
<h2 id="table-of-contents">Table Of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>Since <a href="/embedding-pixelfed-part-1/">my last post about this</a>, I did some progress on embedding Pixelfed images in my blog. Here is what I had to write in this post’s markdown to get this photo displayed:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="md"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"></span></span></code></pre>
<p>That’s it. You might notice that in the markdown there is no <code>alt</code> provided. But it is still present in the actual HTML, as I am retrieving it from the one I submitted with the photo when uploading it to <a href="https://pixey.org/">my Pixelfed instance</a>.</p>
<p>The <code>src</code> for this image in Markdown contains two things: first the lookup string — in this case <a href="https://pixey.org/i/web/post/739971733249250140">the post’s ID</a>, and then the index of the image in the post.</p>
<p>There are still many things I want to implement before I could start using this properly, but this seems like a good checkpoint in my work on the feature.</p>
<h2 id="what-i-did">What I Did</h2>
<p>Looking at the <a href="/embedding-pixelfed-part-1/#plans">“Plans”</a> section of my previous post, this one covers most of what I wanted to achieve so far, except for the design/CSS part.</p>
<ul>
<li>
<p>For now, I am using the <a href="https://www.npmjs.com/package/dotenv"><code>dotenv</code></a> NPM package for storing the API token. I know, there is likely a way to do this without depending on a package, but I’m lazy to explore this, ok?</p>
<p><strong>Update from 2025-01-24:</strong> actually, Astro has build-in support for <a href="https://docs.astro.build/en/guides/environment-variables/">env variables</a>, so now I’m using it.</p>
</li>
<li>
<p>I implemented fetching and caching the data for my Pixelfed posts. It is likely far from optimal, but it works. I’ll only fetch things when doing local development, then what I receive from the API is saved as <code>.json</code> files, one per post, so there won’t be any fetching done neither in the CI nor on the client (aside from the image’s <code>src</code>, of course).</p>
</li>
<li>
<p>I added a wrapper around the MDX <code>img</code> component that checks if it uses the fake <code>pixelfed:</code> protocol in the <code>src</code>. If not, it falls back to the original Astro’s <a href="https://docs.astro.build/en/reference/modules/astro-assets/#image-">Image component</a>, but otherwise it will do everything necessary to get the <code>src</code>, <code>alt</code>, <code>width</code>, and <code>height</code> for the image from the cached/fetched data. See my <a href="/astro-mdx-components/">“Astro MDX Components”</a> post on how I substitute the built-in HTML tags rendered by MDX with custom Astro components.</p>
</li>
<li>
<p>I added some very basic CSS for the photos:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> max-inline-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &.</span><span style="color:#79B8FF">photo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> max-block-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">min</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqw</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> margin-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> p</span><span style="color:#E1E4E8">:has(> &) {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Nothing special; mostly trying to make images always fit into the viewport, and make it so horizontal and vertical images will have roughly the same area. I will likely redo this, but it works for now.</p>
</li>
</ul>
<h2 id="to-do-next">To Do Next</h2>
<p>Here is what I am planning to do next:</p>
<ul>
<li>
<p>Come up with the design for a <code><figure></code> around a photo, and for how I want to display its caption. As I wrote in the beginning, I already have the <code>alt</code> coming from the Pixelfed API, so I am thinking of reusing the markdown’s alt (<code>![this part]()</code>) to provide an additional caption for a photo.</p>
</li>
<li>
<p>Find a good way to display a gallery of photos, optionally with the thumbnails and a way to see one in full.</p>
</li>
<li>
<p>Refactor the code behind how I fetch and display the images. Currently, it is a mess. I want it to be less of a mess. When I do so, I might write about what I’m doing here, but I don’t want to share my suboptimal code just yet.</p>
</li>
</ul>
<p>That’s it for now! I have many other ideas as well: somehow getting the <a href="https://en.wikipedia.org/wiki/Exif">Exif</a> metadata from my photos that I have locally, displaying it, and so on. But that’s likely for much further in the future.</p>
<h2 id="final-words">Final Words</h2>
<p>I am pretty happy with what I did so far, and with what I’m planning to do in the future.</p>
<p>Fun fact: I just ordered a <a href="https://explore.omsystem.com/gb/en/m-zuiko-25mm-f1-8">new lens</a> for <a href="https://en.wikipedia.org/wiki/Olympus_OM-D_E-M5">my camera</a>. I’m a bit frugal with my setup, and rarely buy new stuff in general, but as I managed to do quite a few (for me) photo walks this year, I decided that it might be time to add another lens to my very tiny collection. Maybe one day I’ll write about my setup.</p>
<p>But for now, I’ll need to continue working on an ability to embed photos in this blog, so I could properly share what I capture.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113540109766028436">on Mastodon</a>!</p>Observation: Sticky Anchor Navigationhttps://blog.kizu.dev/sticky-anchor-navigation/https://blog.kizu.dev/sticky-anchor-navigation/When I updated how I am doing scroll markers for the table of contents in this blog, I stumbled upon one curious interaction that I previously did not think deeply about. That interaction: how anchor navigation behaves with elements that have sticky positioning. Initially, this behavior baffled me, and I considered this a bug. But I wondered: are there any legit use cases for this weird behavior?Mon, 25 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Paranoid void — The end of the travel,The beginning of the world</dd><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>When I updated <a href="/toc-scroll-markers/">how I am doing scroll markers for the table of contents</a> in this blog, I stumbled upon one curious interaction that I previously did not think deeply about.</p>
<p>That interaction: how anchor navigation behaves with elements that have sticky positioning.</p>
<p>Look at this example, and try clicking on the “Go to” links, including clicking the same link multiple times.</p>
<style>{`
.test {
display: inline-block;
vertical-align: top;
width: calc(100% / 6);
text-align: center;
background: var(--PINK);
&[style]::after {
display: block;
content: attr(style);
font-size: var(--FONT-SIZE--SMALL);
}
}
.example-nav {
position: sticky;
max-width: max-content;
margin-inline: auto;
top: 0;
z-index: 1;
background: var(--CONTENT-BG);
& a {
padding: 0.25em;
}
}
.example {
background: linear-gradient(
in oklab,
var(--BLUE),
var(--GREEN)
);
}
`}</style>
<p><a href="https://blog.kizu.dev/sticky-anchor-navigation/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.scrollport</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow-x</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> scroll-behavior</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">smooth</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> height</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">200</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.test</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">sticky</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">nav</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example-nav"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Skip to:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#A"</span><span style="color:#E1E4E8">>A</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#B"</span><span style="color:#E1E4E8">>B</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#C"</span><span style="color:#E1E4E8">>C</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#D"</span><span style="color:#E1E4E8">>D</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#E"</span><span style="color:#E1E4E8">>E</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#F"</span><span style="color:#E1E4E8">>F</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> |</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#top"</span><span style="color:#E1E4E8">>Top</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#bottom"</span><span style="color:#E1E4E8">>Bottom</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">nav</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"height: 200vh"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"A"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: 0"</span><span style="color:#E1E4E8">>A</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"B"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: 100px"</span><span style="color:#E1E4E8">>B</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"C"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: -100px"</span><span style="color:#E1E4E8">>C</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"D"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: 0"</span><span style="color:#E1E4E8">>D</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"E"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: 100px"</span><span style="color:#E1E4E8">>E</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"F"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: -100px"</span><span style="color:#E1E4E8">>F</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"height: 200vh"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<div class="aside-wrapper">
<aside>
<p>For example, when on the top, try going to “B”, “D”, “E”, or “F”, multiple times in a row.</p>
<p>Or, go to “C” when at the bottom.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span></aside></span></span></code></pre>
</aside></div>
<p>Isn’t this curious?</p>
<h2 id="whats-going-on">What’s Going On?</h2>
<p>This behavior is (mostly) interoperable across all browsers, and is defined in the specs, in the <a href="https://www.w3.org/TR/css-position-3/#stickypos-scroll">“Scroll Position of Sticky-Positioned Boxes”</a> section of the <a href="https://www.w3.org/TR/css-position-3/">“CSS Positioned Layout Module Level 3”</a> specification:</p>
<blockquote>
<p>For the purposes of any operation targeting the scroll position of a sticky positioned element (or one of its descendants), the sticky positioned element must be considered to be at its offsetted position.</p>
</blockquote>
<p>The spec also provides this non-normative example:</p>
<blockquote>
<p>For example, if a user clicks a link targeting a sticky-positioned element, if the element’s nearest scrollport is currently scrolled such that the sticky positioned element is offset from its initial position, the scroll container will be scrolled back only the minimum necessary to bring it into its desired position in the scrollport (rather than scrolling all the way back to target its original, non-offsetted position).</p>
</blockquote>
<p>When we want to scroll from some position in the scrollport to some element, essentially, we need to have two points: <em>start</em> and <em>end</em>.</p>
<p>What the spec says: both points are considered regardless of the element’s original position. Instead of using the original position, the browser will pretend that everything is static, but as if the current visible position of elements is the truth. Then it will look at the difference between the element’s current position in the scrollport, and calculate the distance we’d want to scroll to put that element to the target position (“scroll snap area”, which is affected by <a href="https://drafts.csswg.org/css-scroll-snap/#scroll-margin"><code>scroll-margin</code></a>, for example).</p>
<h2 id="can-this-be-useful">Can This Be Useful?</h2>
<p>Initially, this behavior baffled me, and I considered this a bug. After discovering that this repeats across all browsers, I had to dig a bit deeper, which resulted in this post.</p>
<p>But I wondered: are there any legit use cases for this weird behavior?</p>
<p>I came up with one: something like a “page down” and “page down” links for some scrollable element. Or, in the below example, “page left” and “page right” — I implemented this for horizontal scrollport because navigation to elements inside nested scrollports is <em>even weirder</em>, and is outside the scope for this post.</p>
<style>{`
.example2 {
min-width: 0;
}
.example2-scrollport {
display: flex;
resize: horizontal;
}
.spacer {
width: 500cqw;
flex-shrink: 0;
background: linear-gradient(
to right,
var(--BLUE) 50%,
var(--GREEN) 0
);
background-size: 100cqw 100%;
}
#page-left,
#page-right {
scroll-margin: 100px 0;
}
`}</style>
<p><a href="https://blog.kizu.dev/sticky-anchor-navigation/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example2-scrollport</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow-x</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">#page-left</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">sticky</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">-100</span><span style="color:#F97583">cqw</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">#page-right</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">sticky</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> right</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">-100</span><span style="color:#F97583">cqw</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#page-left"</span><span style="color:#E1E4E8">>Page Left</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#page-right"</span><span style="color:#E1E4E8">>Page Right</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example2-scrollport"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"page-left"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Start</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"spacer"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> End</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"page-right"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This kinda works? I am unlikely to use this in production, and won’t recommend you as well, but hey.</p>
<p>The way it works is simple: if we know the “size” of a page, we can use a zero-sized sticky element in the corresponding direction, and then set its inset to a negative value equal to this desired page size.</p>
<h2 id="what-ifidont-wantit">What If I Don’t Want It?</h2>
<p>In my case, this was not a desired behavior. What I wanted was to scroll to the <em>original</em> position of the element. Can we somehow achieve this while keeping the sticky positioning?</p>
<p>We can, using one of my recent favorites: a one-time animation. Below is the first example, modified to keep the sticky position, but with its navigation to now properly scrolling up to the original position of such element.</p>
<p><a href="https://blog.kizu.dev/sticky-anchor-navigation/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@keyframes</span><span style="color:#FFAB70"> --unstuck</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> from</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">static</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example--fixed</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(:</span><span style="color:#79B8FF">active</span><span style="color:#E1E4E8">) .</span><span style="color:#79B8FF">test</span><span style="color:#E1E4E8">:target {</span></span>
<span class="line"><span style="color:#E1E4E8"> animation: --unstuck </span><span style="color:#79B8FF">0.01</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> 0</span><span style="color:#F97583">s</span><span style="color:#79B8FF"> both</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example--fixed"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">nav</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example-nav"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Skip to:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#A2"</span><span style="color:#E1E4E8">>A</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#B2"</span><span style="color:#E1E4E8">>B</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#C2"</span><span style="color:#E1E4E8">>C</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#D2"</span><span style="color:#E1E4E8">>D</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#E2"</span><span style="color:#E1E4E8">>E</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#F2"</span><span style="color:#E1E4E8">>F</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> |</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#top2"</span><span style="color:#E1E4E8">>Top</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#bottom2"</span><span style="color:#E1E4E8">>Bottom</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">nav</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top2"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"height: 200vh"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"A2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: 0"</span><span style="color:#E1E4E8">>A</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"B2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: 100px"</span><span style="color:#E1E4E8">>B</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"C2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"top: -100px"</span><span style="color:#E1E4E8">>C</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"D2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: 0"</span><span style="color:#E1E4E8">>D</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"E2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: 100px"</span><span style="color:#E1E4E8">>E</</span><span style="color:#85E89D">div</span></span>
<span class="line"><span style="color:#E1E4E8"> ><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"F2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom: -100px"</span><span style="color:#E1E4E8">>F</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"height: 200vh"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bottom2"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This <em>mostly</em> helps: clicking on one of the links scrolls the page to the correct place. The only issue is with the “B” element, which might visually jump for a split second. This is because, for positive <code>top</code> value, in this case, the element will <em>never</em> be at its original position. So, when we temporarily disable the sticky positioning, it “returns” there, but then immediately goes back to being sticky. Could this specific issue be the reason this aspect was specified the way it is?</p>
<p>Of course, we could also just throw away <code>sticky</code> when the element has <code>:target</code>, but then for any scroll following this navigation the element won’t be sticky, which is usually not what we expect.</p>
<h2 id="final-words">Final Words</h2>
<p>I hope that now, if you stumble over a similar issue in your project, you will know why it happens and how it can be potentially fixed.</p>
<p>There are still so many things that are weird about anchor navigation, especially with nested scrollports, with many interop issues. But that’s a topic for another post.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113546268685956396">on Mastodon</a>!</p>Every :has() in my Blog’s CSShttps://blog.kizu.dev/every-has-in-my-blog-css/https://blog.kizu.dev/every-has-in-my-blog-css/Miriam Suzanne asked: “What are your favorite little day-to-day use cases for the CSS `:has()` selector? Anyone using it in their reset yet?” While I don’t have “day-to-day” cases at work (`:has()` falls outside our browser support for now, and we’re careful around its performance issues), I am using it in a few places for my blog’s CSS. So, I decided to list _all_ the places in my blog’s styles with brief explanations why I’m using `:has()` there.Tue, 26 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Soft Blue Shimmer — Prism of Feeling</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="in-response-to">In Response To</h2>
<p><a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> <a href="https://front-end.social/@mia/113548620361402447" title=".u-in-reply-to">asked in Mastodon</a>:</p>
<blockquote>
<p>What are your favorite little day-to-day use cases for the CSS <code>:has()</code> selector? Anyone using it in their reset yet?</p>
</blockquote>
<p>While I don’t have “day-to-day” cases at work (<code>:has()</code> falls outside our browser support for now, and we’re careful around its performance issues), I am using it in a few places for my blog’s CSS.</p>
<p>So, I decided to list <em>all</em> the places in my blog’s styles with brief explanations why I’m using <code>:has()</code> there.</p>
<h2 id="my-has-usage">My <code>:has()</code> Usage</h2>
<aside class="warning">
Note that the styles for my blog are not refined, and are very experimental. I see many ways they can be improved, but I like to work on them iteratively, resolving issues only when I encounter the need for them, and not prematurely.
</aside>
<h3 id="adjusting-the-grid">Adjusting the Grid</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.root-grid</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:has(.aside-wrapper, aside > details) {</span></span>
<span class="line"><span style="color:#FFAB70"> --min-aside-width</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--ASIDE-WIDTH</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--has-aside</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The <code>--min-aside-width</code> custom proprety is used in two places: for the CSS grid itself, and for the <code>min-inline-size</code> of the <code>.aside-wrapper</code>. While for the latter it is not necessary to use the <code>:has()</code>, I am just reusing this variable. Why I am using it: to adjust the layout when there is a secondary column present, changing how responsiveness works.</p>
<p>When there is enough space on the page, the main content is always centered. But when there is not enough space, this behavior kicks in. Without <code>aside</code>. The content will continue to be centered, but when it is present, content will shift aside. Five years ago, I wrote a post about a similar layout: <a href="https://kizu.dev/my-grid-layout/">“My Grid Layout”</a> — layout there relies on the intrinsic dimensions of things inside columns.</p>
<p>I find <code>:has()</code> to be very convenient for adjusting various aspects of CSS grids. Sometimes, as with the article above, it might be possible to hack around with intrinsic values and comples <code>minmax()</code> and repeating columns, but for simple cases we can often just use <code>:has()</code>. It is more convenient and expressive.</p>
<h3 id="modifier-shortcut">Modifier Shortcut</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:has(> h1) {</span></span>
<span class="line"><span style="color:#FFAB70"> --ratio</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>On the main page, <code>h1</code> is inside the topmost <code>header</code>. On inner pages, it is moved inside the <code><article></code>. I could add a class to the <code>header</code> based on the layout, but eh, why not just use <code>:has()</code>? I won’t use this in an enterprise production code, but for my blog? Why not.</p>
<p>The <code>--ratio</code> here just changes some dimensions somewhere, its style is not that important.</p>
<h3 id="indented-paragraphs">Indented Paragraphs</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:is</span><span style="color:#E1E4E8">(</span><span style="color:#85E89D">article</span><span style="color:#E1E4E8">, </span><span style="color:#85E89D">blockquote</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">></span><span style="color:#85E89D"> p</span><span style="color:#B392F0">:not</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">.starts-with-tag:has</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">></span><span style="color:#85E89D"> img</span><span style="color:#B392F0">:only-child</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &,</span></span>
<span class="line"><span style="color:#E1E4E8"> & + .</span><span style="color:#79B8FF">aside-wrapper</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> & + </span><span style="color:#79B8FF">p</span><span style="color:#E1E4E8">:not(.starts-with-tag:has(> img:only-child)) {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-block-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">-1</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--gap</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF"> text-indent</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--text-indent</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & > * {</span></span>
<span class="line"><span style="color:#79B8FF"> text-indent</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Ok, this one might be overcomplicated. The idea is to style <code>p + p</code> to have an indentation instead of a gap. Yes, inside my <code>article</code> I am using a CSS grid with <code>gap</code> which defines the basic distance between any elements inside.</p>
<p>But for consecutive paragraphs, I really like the indented text look.</p>
<p>There are a few things going on:</p>
<ol>
<li>
<p>The first <code>:has()</code> is used to check if our paragraph is not one containing just a singular image. In this case, it would be just some illustration, and it should not be considered an actual paragraph.</p>
</li>
<li>
<p>The <code>.starts-with-tag</code> is there because in CSS all the <code>:NNN-child</code> does not care about text nodes, and I have a <a href="https://github.com/kizu/kizu-blog/blob/main/src/components/mdx/Paragraph.astro">custom Astro component for paragraphs</a> in MDX that looks at their content, and if it does not have text nodes in the beginning, adds this class. There is <a href="https://github.com/w3c/csswg-drafts/issues/3216">a CSSWG issue about this</a> by <a href="https://exe-boss.tech/">ExE Boss</a> — if you want to have a native way to do so as well, please, share your use cases there.</p>
</li>
<li>
<p>The <code>&, & + .aside-wrapper</code> in the middle is there because we might have an optional <code>.aside-wrapper</code>, which usually interrupts the flow and goes into a sidebar. In that case, we would like to treat the paragraphs that are separated by it as consecutive. This does not work for narrow screen for now; maybe I will fix that case one day.</p>
</li>
<li>
<p>Because <code>text-indent</code> is an <em>inherited</em> property, and my content can have inline-blocks etc, I need to reset it for anything nested: <code>& > *</code>.</p>
</li>
</ol>
<h3 id="different-types-of-lists">Different Types Of Lists</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">li</span><span style="color:#F97583"> +</span><span style="color:#85E89D"> li</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-block-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.25</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#85E89D">li</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">+</span><span style="color:#85E89D"> li</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-block-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>In some flavors of Markdown, there is a difference whether your list items have an empty line between them or not. Those that care about this difference tend to put the content of more sparse items inside paragraphs. I am using <code>:has()</code> here to modify the margin to replicate this spacing in Markdown.</p>
<h3 id="hanging-punctuation">Hanging Punctuation</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:is</span><span style="color:#E1E4E8">(</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">, </span><span style="color:#85E89D">ol</span><span style="color:#E1E4E8">)</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#F97583"> ></span><span style="color:#85E89D"> li</span><span style="color:#B392F0">.starts-with-tag</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> a</span><span style="color:#B392F0">.has-left-overhang:first-child</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#F97583"> ></span><span style="color:#85E89D"> li</span><span style="color:#B392F0">.starts-with-tag</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> p</span><span style="color:#B392F0">.starts-with-tag:first-child</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> a</span><span style="color:#B392F0">.has-left-overhang:first-child</span></span>
<span class="line"><span style="color:#E1E4E8">) </span><span style="color:#85E89D">li</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--overhang</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> margin-inline-start</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">-1</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--overhang</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">li</span><span style="color:#B392F0">.starts-with-tag:has</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#F97583"> ></span><span style="color:#85E89D"> a</span><span style="color:#B392F0">.has-left-overhang:first-child</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#F97583"> ></span><span style="color:#85E89D"> p</span><span style="color:#B392F0">.starts-with-tag:first-child</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> a</span><span style="color:#B392F0">.has-left-overhang:first-child</span></span>
<span class="line"><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> & > </span><span style="color:#79B8FF">a</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">has-left-overhang</span><span style="color:#E1E4E8">:first-child,</span></span>
<span class="line"><span style="color:#E1E4E8"> & > p.starts-with-tag:first-child > a.has-left-overhang:first-child {</span></span>
<span class="line"><span style="color:#E1E4E8"> margin-inline-start: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">-1</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--overhang</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>I have many thoughts about hanging punctuation, and I am not talking about the highly restricted and limited <code>hanging-punctuation</code>. Even if it was wider available, I would probably not use it. Well, I would, but also keep all the other similar stuff I’m doing.</p>
<p>This specific example was made specifically for my <a href="/tags/bookmarks/">“bookmarks”</a> posts: they contain lists with links, and I wanted to adjust their styling just a bit.</p>
<p>I don’t know if you ever noticed this when looking at them, but hey. If you did — nice.</p>
<h3 id="conditional-container">Conditional Container</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">img</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &.</span><span style="color:#79B8FF">photo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> max-block-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">min</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">100</span><span style="color:#F97583">vh</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqw</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> p</span><span style="color:#E1E4E8">:has(> &) {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>I already showed this as a part of my <a href="/embedding-pixelfed-part-2/">“Embedding Pixelfed, part 2”</a> post, but I did not explain what it does.</p>
<p>I am using a CSS grid where all content goes inside a middle column. But for images inside a lonely paragraph, I want to limit their width by the width of the content area, so I need to have a container on the paragraph. While I could apply the containment to <em>all</em> paragraphs, I decided to do it only for these that need it.</p>
<h3 id="bleed-layout-for-images">Bleed Layout for Images</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">p</span><span style="color:#B392F0">.starts-with-tag:has</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">></span><span style="color:#85E89D"> img</span><span style="color:#B392F0">:only-child</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">-1</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--content-padding</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>I already mentioned this case where I excluded paragraphs with lonely images, now we target them and use the custom property for the content padding to make them go full-width. For an example, you can peek at the beginning of my <a href="/embedding-pixelfed-part-2/">“Embedding Pixelfed, part 2”</a> post that I already mentioned above.</p>
<h3 id="figure-decorations">Figure Decorations</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">figure</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(:has( > figcaption))::after {</span></span>
<span class="line"><span style="color:#E1E4E8"> inset-block-end: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The way I style <code><figure></code> and <code><figcaption></code> probably deserve a separate post, but in short: when there is a figcaption, I draw a border via an <code>::after</code> pseudo-element, making it wrap everything <em>except</em> for the <code>figcaption</code>. When there is no figcaption, I need to adjust the position of the bottom edge of this decorative element.</p>
<h3 id="table-of-contents-1">Table of Contents</h3>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.table-of-contents</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:hover,</span></span>
<span class="line"><span style="color:#E1E4E8"> &:has(:focus-visible) {</span></span>
<span class="line"><span style="color:#79B8FF"> z-index</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> opacity</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">></span><span style="color:#85E89D"> details</span><span style="color:#E1E4E8">[</span><span style="color:#B392F0">open</span><span style="color:#E1E4E8">]) {</span></span>
<span class="line"><span style="color:#FFAB70"> --toc-margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--DOUBLE-PADDING</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> transform</span><span style="color:#E1E4E8">: </span><span style="color:#6A737D">/*…*/</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &:hover,</span></span>
<span class="line"><span style="color:#E1E4E8"> &:has(:focus-visible) {</span></span>
<span class="line"><span style="color:#79B8FF"> transform</span><span style="color:#E1E4E8">: </span><span style="color:#6A737D">/*…*/</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>My table of contents also deserves an extra post for sure. In this case, the <code>:has(:focus-visible)</code> works basically like non-existent <code>:focus-visible-within</code>. But hey, look at <a href="https://github.com/w3c/csswg-drafts/issues/3080">this CSSWG issue</a> by <a href="https://dbaron.org/">David Baron</a>. You know what to do if you want this as well.</p>
<p>And another usage here is for checking if my ToC contains an opened <code><details></code></p>
<h2 id="conclusion">Conclusion</h2>
<p>Most of my usage for <code>:has()</code> are shortcuts for something that could, potentially, be done either by manually hardcoding the modifiers, or by <del>parsing</del> regexping the content and adding classes similar to <code>.starts-with-tag</code>.</p>
<p>But <code>:has()</code> allows doing this declaratively from CSS. Which is nice, but can have performance issues. Still good enough for a hobby project.</p>
<p>The only cases above that cannot be done without relying on JS are for anything <em>dynamic</em>: the <code>:has(: focus-visible)</code> and <code>:has(details[open])</code>. These are prime use cases for <code>:has()</code>, and even though in some cases <code>JS</code> could still be more performant, these are very fun to apply from CSS.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113551588828250712">on Mastodon</a>!</p>Observation: CSS Math Evalhttps://blog.kizu.dev/css-math-eval/https://blog.kizu.dev/css-math-eval/There is a calculator that uses JS in the post. If you wonder: “What is special about it” — there was one problem that I wanted to solve: evaluating some math expression from user input in a very safe way. I know, there exist external libraries people did already write which could do this job well enough. But I wanted something minimal and with no dependencies. And hacky. Enter CSS, registered custom property, and `calc()`.Thu, 28 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>how to count one to ten — news paper</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><aside>
## Update from 2024-11-29
<p>I published a continuation post: <a href="/css-math-eval-2/">“CSS Math Eval, now Better and Weirder”</a>, in which I mention one better solution, one weirder, and talk a bit more about browser support.</p>
</aside>
<p>This is just a quick idea that I had recently, and decided to write down. Look at this:</p>
<p><a href="https://blog.kizu.dev/css-math-eval/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"2 + 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"sin(90deg)"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"(pi - 1) * 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This is a calculator? I guess? If you wonder: “What is special about it” — there was one problem that I wanted to solve.</p>
<p>That problem: evaluating some math expression from user input in a very safe way. I know, there exist external libraries people did already write which could do this job well enough. But I wanted something minimal and with no dependencies. And hacky.</p>
<p>Enter CSS, registered custom property, and <code>calc()</code>:</p>
<p><a href="https://blog.kizu.dev/css-math-eval/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#79B8FF"> CSS</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">registerProperty</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8"> name: </span><span style="color:#9ECBFF">'--css-math'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: </span><span style="color:#9ECBFF">'<number>'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> initialValue: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#B392F0"> CSSMath</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> HTMLElement</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> getResult</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">el</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.style.</span><span style="color:#B392F0">setProperty</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF"> '--css-math'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF"> `calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#B392F0"> getComputedStyle</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">getPropertyValue</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'--css-math'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> connectedCallback</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> input</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> output</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'output'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0"> setTimeout</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(input)</span></span>
<span class="line"><span style="color:#E1E4E8"> }, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> input.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">, ({ </span><span style="color:#FFAB70">target</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(target);</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'css-math'</span><span style="color:#E1E4E8">, CSSMath);</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This is far, <em>far</em>, <strong>far</strong> from being a good implementation. Among other things, it accepts only what CSS can: <code>2 + 2</code> works, but <code>2+2</code> does not.</p>
<p>I imagine, it might be possible to throw a quick regex that would normalize the input to be easier accepted by <em>the thing</em>, but hey, this is just a quick idea, and a quick post.</p>
<p>If you’re wondering what’s going on inside, we register a custom property in CSS, then put our user input inside a <code>calc()</code>, and set this property on our element. And then read the resulting value: because the custom property is registered, we will get the already calculated value!</p>
<p>The main problem of this method is that it is <em>slow</em>. After all, you have to set a property, and then run a <code>getComputedStyle()</code> on it.</p>
<p>But I still think that this is neat: <code>calc()</code> is so powerful in CSS today, and allows throwing many different things into it, and is continously improved.</p>
<p>While writing this post, I got an even wilder idea about how this could be “improved”, but, I guess, let me save it for another <a href="/tags/observation/">observation</a>-type post.</p>
<p>And, maybe, before that, you could tell me: how wacky is this? Do you wish we had a safe native way to evaluate math expressions in JS, without <code>eval()</code>, <code>new Function()</code> etc? Do you know a better way to achive the same, which would be as full of features as math in CSS?</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113562972739668152">on Mastodon</a>!</p>Short Lines, Bad Breaks, and CSShttps://blog.kizu.dev/short-lines-bad-breaks-and-css/https://blog.kizu.dev/short-lines-bad-breaks-and-css/In today’s CSSWG meeting, there was one issue about the new value of `text-wrap-style` property — `avoid-orphans`. There was agreement in the meeting that we should look for a better name, and open a separate issue about this, which I did, as well as opened another one — about the `orphans` and `widows` properties.Wed, 27 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Dandelion</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>In today’s CSSWG meeting, there was <a href="https://github.com/w3c/csswg-drafts/issues/3473#issuecomment-2348275178">one issue</a> about the new value of <code>text-wrap-style</code> property — <a href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-style-avoid-orphans"><code>avoid-orphans</code></a> (originally by <a href="https://s10wen.com/">Simon Owen</a>, in the agenda regarding an addition of it to the spec by <a href="https://florian.rivoal.net/">Florian Rivoal</a>).</p>
<p>When going through the list of issues in the agenda before the meeting, I saw this issue, and it reminded me of one typographic thing that I had been thinking about for quite a while: the weirdness of the “widows” and “orphans” terms.</p>
<p>I never could remember them, even when people mentioned various mnemonics. And then, whenever in some typographic context people mentioned “eliminate widows”, without that context, it sounded pretty bad.</p>
<p>I was glad that I am not the only one who did not like this term: this year I bought the third edition of <a href="https://ellenlupton.com/">Ellen Lupton</a>’s <a href="https://ellenlupton.com/Thinking-with-Type">“Thinking with Type”</a>, and was pleasantly surprised when she brought this up in the “Short Lines” chapter (starting from page 128):</p>
<blockquote>
<p>In English, short lines are often called <code>widows</code> and <code>orphans</code>. When used as epithets, these terms are sexist and insensitive. Neutral descriptions like “short line” or “bad break” are respectful and easy to understand.</p>
</blockquote>
<p>I read the whole book, and can happily recommend it to everyone, by the way.</p>
<p>Beyond the terms being insensitive, there is another problem that I mentioned in the beginning: these terms are just plain confusing. If you go to the <a href="https://en.wikipedia.org/wiki/Widows_and_orphans#Definitions">Wikipedia page about them</a>, here is what you will find in how it defines these terms:</p>
<blockquote>
<dl>
<dt>Widow (sometimes called orphan)</dt>
<dd>A paragraph-ending line that falls at the beginning of the following page or column, thus separated from the rest of the text. Mnemonically, a widow is “alone at the top” (of the family tree but, in this case, of the page).</dd>
<dt>Orphan (sometimes called widow)</dt>
<dd>A paragraph-opening line that appears by itself at the bottom of a page or column, thus separated from the rest of the text. Mnemonically, an orphan is “alone at the bottom” (of the family tree but, in this case, of the page).</dd>
<dt>Runt (sometimes called widow or orphan)</dt>
<dd>A word, part of a word, or a very short line that appears by itself at the end of a paragraph. Mnemonically still “alone at the bottom”, just this time at the bottom of a paragraph. Orphans of this type give the impression of too much white space between paragraphs.</dd>
</dl>
</blockquote>
<p>Just look at these parentheses! No wonder, I was confused for so long: likely, I looked at different sources inconsistently calling the same thing different names.</p>
<p>Even more: if we look at the definitions of “widows” and “orphans” in this Wikipedia article, we’ll see that the proposed <code>avoid-orphans</code> is about neither! It is about the third case, which in this article is called “runts”. And, which, unsurprisingly, also can be used <a href="https://www.merriam-webster.com/dictionary/runt">as a derogatory term</a> (see third definition). This was also the first time I heard this term in a typographic context, so I just flipped through a few books on typography from my bookshelf and did not find it mentioned there.</p>
<h2 id="opening-issues">Opening Issues</h2>
<p>Anyway, stumbling upon this issue today made me remember this grip I had with the terms, so I both <a href="https://github.com/w3c/csswg-drafts/issues/3473#issuecomment-2504370877">commented on the issue</a>, and then later brought all of that up in the discussion.</p>
<p>There was agreement that we should look for a better name, and open a separate issue about this, <a href="https://github.com/w3c/csswg-drafts/issues/11283">which I did</a>. Spoiler: my suggested name for this value is <code>avoid-short-lines</code>, but if you have a better name (or just agree) — please, participate there.</p>
<p>In the discussion, it was mentioned that CSS already has two other properties: <code>orphans</code> and <code>widows</code>. Oh wow, I completely forgot that we had these! Likely, because <a href="https://caniuse.com/css-widows-orphans">their support</a> is still not there, with Firefox missing, and in browsers that claim to support them, it appears to be uneven. See <a href="https://quirksmode.org/css/css2/widows.html">this test example</a> by <a href="https://quirksmode.org/">Peter-Paul Koch</a> and compare how things render in Safari vs Chrome. There was also an <a href="https://github.com/web-platform-tests/interop/issues/520">Interop 2023 proposal related to this</a> by <a href="https://scottkellum.com/">Scott Kellum</a>.</p>
<p>After some thought, I decided to open an issue about renaming (and maybe reimagining?) them too: <a href="https://github.com/w3c/csswg-drafts/issues/11286">“Rename and/or reimagine widows and orphans”</a>. Given that they’re not interoperable today, we could retire them (well, keep them deprecated by “working” where they do now), and come up with both better names, and perhaps better behavior (if needed).</p>
<h2 id="final-words">Final Words</h2>
<p>Let me copy the last two paragraphs from that second issue:</p>
<blockquote>
<p>This could be a good opportunity to discuss these differences, why they’re there, and if we could come with a consensus which all browsers could agree on, so we could move forward.</p>
<p>Both avoiding short lines, and avoiding single leading or trailing lines in fragments are something I (and many other developers) wanted to have for a while, so it would be great to get closer to it.</p>
</blockquote>
<p>Do you have an opinion about this? Were you also confused about these terms? Did you want to use them in your code? Please let me know, or — even better — comment in these issues.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113557242439790096">on Mastodon</a>!</p>CSS Math Eval, now Better and Weirderhttps://blog.kizu.dev/css-math-eval-2/https://blog.kizu.dev/css-math-eval-2/After the yesterday’s “Observation: CSS Math Eval” post, I got a mastodon reply from Valtteri Laitinen. In this post, I modify my example with `CSSNumericValue`, provide a better fallback, and also look into one curious aspect of `initial-value` of registered custom properties.Fri, 29 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Uchu Conbini — 体温</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="a-better-solution">A Better Solution</h2>
<p>After the yesterday’s <a href="/css-math-eval/">“Observation: CSS Math Eval”</a> post, I got a <a href="https://fedi.valtlai.fi/@valtlai/113567079349772684">mastodon reply</a> from <a href="https://valtlai.fi/en/">Valtteri Laitinen</a> (in a <a href="https://mastodon.social/@Kilian/113565127260717868">reply thread</a> started by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a>):</p>
<blockquote>
<p>Seems that you can use</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="js"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">CSSNumericValue</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">parse</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">to</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'number'</span><span style="color:#E1E4E8">).value</span></span></code></pre>
<p>instead of the custom property and <code>getComputedStyle()</code>. That isn’t supported by Firefox though.</p>
</blockquote>
<p>When I was experimenting for my original post, I briefly looked at the <a href="https://developer.mozilla.org/fr/docs/Web/API/CSS_Object_Model">CSSOM</a>, but did miss the <code>.to('number')</code> method! I suspected that it <em>should</em> provide something similar, and I am happy that it exists, and that Valtteri pointed it out to me!</p>
<p>For <a href="https://caniuse.com/mdn-api_cssnumericvalue">browsers that support <code>CSSNumericValue</code></a>, this is a much better solution, as it does not require <code>getComputedStyle()</code>, and thus should not cause a layout recalculation.</p>
<p>Here is the example from the last article, now using <code>CSSNumericValue</code> when it is available:</p>
<p><a href="https://blog.kizu.dev/css-math-eval-2/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"2 + 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"sin(90deg)"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"(pi - 1) * 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-2</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#79B8FF"> CSS</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">registerProperty</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8"> name: </span><span style="color:#9ECBFF">'--css-math-2'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: </span><span style="color:#9ECBFF">'<number>'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> initialValue: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#B392F0"> CSSMath2</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> HTMLElement</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> getResult</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">el</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (</span><span style="color:#9ECBFF">'CSSNumericValue'</span><span style="color:#F97583"> in</span><span style="color:#E1E4E8"> window) {</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> CSSNumericValue</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">parse</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">to</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'number'</span><span style="color:#E1E4E8">).value</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#9ECBFF"> ' (using CSSNumericValue)'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.style.</span><span style="color:#B392F0">setProperty</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF"> '--css-math-2'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#9ECBFF"> `calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#B392F0"> getComputedStyle</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">getPropertyValue</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'--css-math-2'</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#9ECBFF"> ' (using getComputedStyle)'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> connectedCallback</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> input</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> output</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'output'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0"> setTimeout</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(input)</span></span>
<span class="line"><span style="color:#E1E4E8"> }, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> input.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">, ({ </span><span style="color:#FFAB70">target</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(target);</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'css-math-2'</span><span style="color:#E1E4E8">, CSSMath2);</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span></code></pre>
<h2 id="a-better-fallback">A Better Fallback</h2>
<p>However, if we’re talking about fallbacks, my original method was still far from being perfect: after all, <code>registerProperty</code> has a <a href="https://caniuse.com/?search=registerProperty"><em>worse</em> support</a>.</p>
<p>Can we have a better fallback for it? Yes, if instead of using a registered custom property, we will use a regular property that accepts a <code><number></code> syntax:</p>
<p><a href="https://blog.kizu.dev/css-math-eval-2/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"2 + 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"sin(90deg)"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"(pi - 1) * 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-3</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#F97583"> let</span><span style="color:#E1E4E8"> propertyToCheck </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> 'border-image-outset'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (</span><span style="color:#9ECBFF">'registerProperty'</span><span style="color:#F97583"> in</span><span style="color:#79B8FF"> CSS</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> propertyToCheck </span><span style="color:#F97583">=</span><span style="color:#9ECBFF"> '--css-math-3'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> CSS</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">registerProperty</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8"> name: propertyToCheck,</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: </span><span style="color:#9ECBFF">'<number>'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> initialValue: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#B392F0"> CSSMath3</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> HTMLElement</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> getResult</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">el</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (</span><span style="color:#9ECBFF">'CSSNumericValue'</span><span style="color:#F97583"> in</span><span style="color:#E1E4E8"> window) {</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> CSSNumericValue</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">parse</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">`calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">to</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'number'</span><span style="color:#E1E4E8">).value</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#9ECBFF"> ' (using CSSNumericValue)'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.style.</span><span style="color:#B392F0">setProperty</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> propertyToCheck,</span></span>
<span class="line"><span style="color:#9ECBFF"> `calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#B392F0"> getComputedStyle</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">getPropertyValue</span><span style="color:#E1E4E8">(propertyToCheck)</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#9ECBFF"> ` (using ${</span><span style="color:#E1E4E8">propertyToCheck</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> connectedCallback</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> input</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> output</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'output'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0"> setTimeout</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(input)</span></span>
<span class="line"><span style="color:#E1E4E8"> }, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> input.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">, ({ </span><span style="color:#FFAB70">target</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(target);</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'css-math-3'</span><span style="color:#E1E4E8">, CSSMath3);</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Just for fun (and because it is unlikely to clash with anything usually), I used the <code>border-image-outset</code> property. Did you know about its existence? It is there for <a href="https://caniuse.com/mdn-css_properties_border-image-outset">as long</a> as <a href="https://caniuse.com/calc"><code>calc()</code></a>, which we also need for things to work.</p>
<h2 id="a-weird-solution-calculated-initial-value">A Weird Solution: Calculated <code>initial-value</code></h2>
<p>Before I got to know about <code>CSSNumericValue</code>, I was playing with various ways to improve the performance of my initial method. I found a thing about which I did not know about, but which seems obvious in hindsight.</p>
<p>We can use calculations for <code>initial-value</code> of registered properties! Here is my original example which uses this method:</p>
<p><a href="https://blog.kizu.dev/css-math-eval-2/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"2 + 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"sin(90deg)"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"text"</span><span style="color:#B392F0"> value</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"(pi - 1) * 2"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> =<</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">output</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">css-math-weird</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> mathCache</span><span style="color:#F97583"> =</span><span style="color:#F97583"> new</span><span style="color:#B392F0"> Map</span><span style="color:#E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583"> class</span><span style="color:#B392F0"> CSSMathWeird</span><span style="color:#F97583"> extends</span><span style="color:#B392F0"> HTMLElement</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#B392F0"> getResult</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">el</span><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> result</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> mathCache.</span><span style="color:#B392F0">get</span><span style="color:#E1E4E8">(el.value);</span></span>
<span class="line"><span style="color:#F97583"> if</span><span style="color:#E1E4E8"> (result) {</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> result;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> name</span><span style="color:#F97583"> =</span></span>
<span class="line"><span style="color:#9ECBFF"> `--css-math-weird-${</span><span style="color:#E1E4E8">mathCache</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">size</span><span style="color:#9ECBFF">}`</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> CSS</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">registerProperty</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#E1E4E8"> name,</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: </span><span style="color:#9ECBFF">'<number>'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: </span><span style="color:#79B8FF">false</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> initialValue: </span><span style="color:#9ECBFF">`calc(${</span><span style="color:#E1E4E8">el</span><span style="color:#9ECBFF">.</span><span style="color:#E1E4E8">value</span><span style="color:#9ECBFF">})`</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> value</span><span style="color:#F97583"> =</span><span style="color:#B392F0"> getComputedStyle</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">this</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#B392F0">getPropertyValue</span><span style="color:#E1E4E8">(name);</span></span>
<span class="line"><span style="color:#E1E4E8"> mathCache.</span><span style="color:#B392F0">set</span><span style="color:#E1E4E8">(el.value, value);</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> value;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> connectedCallback</span><span style="color:#E1E4E8">() {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> input</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#79B8FF"> output</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">querySelector</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'output'</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#B392F0"> setTimeout</span><span style="color:#E1E4E8">(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(input)</span></span>
<span class="line"><span style="color:#E1E4E8"> }, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> input.</span><span style="color:#B392F0">addEventListener</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">'input'</span><span style="color:#E1E4E8">, ({ </span><span style="color:#FFAB70">target</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> output.value </span><span style="color:#F97583">=</span><span style="color:#79B8FF"> this</span><span style="color:#E1E4E8">.</span><span style="color:#B392F0">getResult</span><span style="color:#E1E4E8">(target);</span></span>
<span class="line"><span style="color:#E1E4E8"> });</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> customElements.</span><span style="color:#B392F0">define</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#9ECBFF"> 'css-math-weird'</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> CSSMathWeird</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">script</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Ok, this one is very inefficient: we need to maintain a cache for the values (so we won’t attempt to register the same custom property twice, which is prohibited), and I don’t even want to know how the browser will behave if we will suddenly register hundreds of unused custom properties.</p>
<p>But hey, it works! Not sure what can be the practical purpose of this, though.</p>
<h2 id="room-for-improvement">Room for Improvement</h2>
<p>There are still many things that something like this will require for it to be a viable reusable solution.</p>
<p>But now I know about <code>CSSNumericValue</code>! I hope we will get it in all browsers, eventually. Mozilla is <a href="https://github.com/mozilla/standards-positions/issues/1091">positive</a> about CSS Typed OM, so, hopefully, someone will eventually implement it there.</p>
<aside>
If, for some reason, you want be the one to do so, here is the [Bugzilla page](https://bugzilla.mozilla.org/show_bug.cgi?id=1278697) for its implementation, where [Emilio Cobos Álvarez](https://crisal.io/) [writes](https://bugzilla.mozilla.org/show_bug.cgi?id=1278697#c10):
<blockquote>
<p>Anybody can pick this up, I’d be happy to mentor / review patches / etc. We can sort out the complex bits as we get to them :)</p>
</blockquote>
</aside>
<p>It is fascinating how by implementing a powerful feature like this one in CSS, we unlock it not only there, but also for JS as well. Can it be viable to propose a native JS method for evaluating CSS math?</p>
<p>I’m also happy that I wrote the original post, even though the idea was very wild and unpolished. It might help someone (like Kilian), and now we know more about CSS and its API.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113568121548314900">on Mastodon</a>!</p>Embedding Pixelfed, part 3https://blog.kizu.dev/embedding-pixelfed-part-3/https://blog.kizu.dev/embedding-pixelfed-part-3/While I did not do everything from the “To Do Next” of my last update, I did most of it. Now, if I provide a caption in the markdown, it will render as a `<figure>` with a `<figcaption>`.Sat, 30 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — Forest and lighting</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><h2 id="table-of-contents">Table Of Contents</h2>
<h2 id="since-last-update">Since Last Update</h2>
<p>While I did not do everything from the <a href="/embedding-pixelfed-part-2/#to-do-next">“To Do Next”</a> of my <a href="/embedding-pixelfed-part-2/">last update</a>, I did most of it.</p>
<p>Now, if I provide a caption in the markdown, like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="markdown"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"></span></span></code></pre>
<p>It will render as a <code><figure></code> with a <code><figcaption></code>:</p>
<p><a href="https://blog.kizu.dev/embedding-pixelfed-part-3/">“A horizontal photo” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>It will also work with vertical photos, in which case I am trying to make either have similar dimensions, as if I would just stretch a vertical photo to the content width, it will overwhelm everything around it.</p>
<p><a href="https://blog.kizu.dev/embedding-pixelfed-part-3/">“A vertical photo” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>You might’ve noticed a “See details” link under both, and maybe even interacted with it.</p>
<p>This part is not yet finished, but was also something I mentioned I wanted to do: a full-page view for any photo. For now, it is handled with just CSS and some in-page anchor links, but there are a few things I’d want to enhance.</p>
<h2 id="next-time">Next Time</h2>
<ul>
<li>I want to enhance it with some Popover API:
<ul>
<li>Right now it is using <code>position: fixed</code>, but it would be better to put it into the top layer.</li>
<li>It will also provide <code>esc</code> for closing it from the box.</li>
</ul>
</li>
<li>I would like to add buttons for going to the next/prev photos on the page.
<ul>
<li>This is complicated, as if I’d want to do it without client-side JS, I’ll need to gather all the photos on the page in Astro, and then use this when rendering the images.</li>
</ul>
</li>
<li>I did try, but did not finish making a list with thumbnails.
<ul>
<li>For it, I’d need to conditionally render the image and its figure differently.</li>
<li>However, in Astro, there is no such thing as context. So I’ll need to do something differently. Likely, reuse what I’ll do for prev/next buttons, and will try to detect the images’ context when parsing their markdown.</li>
</ul>
</li>
<li>The visuals for the full-page view are not final. Well, nothing is, but it’s even more.
<ul>
<li>I’ll need to add more metadata, handle responsiveness better, work on margins, etc.</li>
</ul>
</li>
<li>I wonder if I could add view transitions, for browsers that support them?</li>
</ul>
<p>Again, there are also tons of other things that I’d want to do, but I think I am close to a state where I could actually start using this!</p>
<h2 id="end-ofnovember">End of November</h2>
<p>This is the last post of November. I guess, I managed to do all 30 posts this month. Some — good, some — meh.</p>
<p>Whiel I did not manage to plan all of them in advance, I tried to play with different ways of setting up the next ones by having these process posts.</p>
<p>Posting what I did and, especially, what I plan to, really helps to continue the work. It makes it easier to get into the context of what I did, and then provides a few starting points. I’ll try to continue doing updates like these in the future.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113574138835706785">on Mastodon</a>!</p>Splash Colour Mixinhttps://blog.kizu.dev/splash-colour-mixin/https://blog.kizu.dev/splash-colour-mixin/Two days ago, I published a new article. In that article, I presented a way to prototype native CSS mixins with what we have in CSS today. Three days ago, Lu Wilson published an experimental colour format: Splash. When I read about it, I immediately saw what I’d want to do with it: prototype a mixin.Thu, 26 Dec 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Nuito — NeKoMaJiN Vs</dd><dt>Current drink:</dt><dd>Jasmine Green Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>Two days ago, I published a new article: <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a>. It is long, but might be a necessary context for today’s post. If you did not yet check it out: please, do!</p>
<p>Anyway. In that article, I presented a way to prototype native CSS mixins with what we have in CSS today: custom cascade layers, and a new technique based on how cyclic dependencies work for custom properties.</p>
<p>Unlike my previous steps toward this — <a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a> — the new technique allows us to call a mixin with at least one <em>parameter</em>!</p>
<p>The increase in usefullness is infinite: <code>0 → 1</code>. An ability to assign just one custom property — and provide the value at the same time — makes me want to do everything in this way now.</p>
<p>So, in the last two days following the publication of this article, I am already testing it for various things, and written at least two relatively complicated mixins based on it.</p>
<p>In this post, I will write about one of them.</p>
<h2 id="the-splash">The Splash</h2>
<p>Three days ago, <a href="https://www.todepond.com/">Lu Wilson</a> published an experimental colour format: <a href="https://www.todepond.com/lab/splash/">Splash</a>. It is a simple idea: to express RGB in just three decimal digits, with an explicitly loose definition over how it should be converted into the actual color, with an invitation to adjust and play with it.</p>
<aside>
I, personally, don’t like RGB too much, so I wonder if we could do the same, but for something like [OKLCH](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch). And name it… OKSplash?! You are welcome to do it, if you think that’s a good idea.
</aside>
<p>Coincidentally, after publishing my article about mixins, and talking a bit with <a href="https://lea.verou.me/">Lea Verou</a>, she nerd-sniped me into <a href="https://front-end.social/@kizu/113714092648709846">playing with colors</a> for a bit.</p>
<p>So later, when I read about Splash, I immediately saw what I’d want to do with it. Because in my color experiments, I was looking into how we could map and convert colors when we have only their components. And a format being just a three-digit number makes it straightforward to work with. If it had any letters in it, it would be much harder to work with in CSS!</p>
<h2 id="the-mixin">The Mixin</h2>
<p>The original experimental mixin is available <a href="https://codepen.io/kizu/pen/yyBoyev">on CodePen</a>, but I’ll present it here as well, and will try to explain it a bit further.</p>
<p>I think it is a good demonstration of what might be possible with native mixins.</p>
<p><a href="https://blog.kizu.dev/splash-colour-mixin/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"position: sticky; top: 0;"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--splash-bg: 967"</span><span style="color:#E1E4E8">>pink</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--splash-bg: 342"</span><span style="color:#E1E4E8">>dark olive</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">strong</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--splash-bg: 277"</span><span style="color:#E1E4E8">>turquoise</</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">strong</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--splash-bg: 999"</span><span style="color:#E1E4E8">>white</</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">strong</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--splash-bg: 000"</span><span style="color:#E1E4E8">>black</</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@layer</span><span style="color:#E1E4E8"> splash { </span><span style="color:#85E89D">*</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* Our input, with a list of “dependencies” */</span></span>
<span class="line"><span style="color:#FFAB70"> --splash-bg</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-bg-value</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-shadow</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-color</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* Extracting the color components from the input */</span></span>
<span class="line"><span style="color:#FFAB70"> --_splash_r</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">round</span><span style="color:#E1E4E8">(down,</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--splash-bg</span><span style="color:#E1E4E8">) / </span><span style="color:#79B8FF">100</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FFAB70"> --_splash_g</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">round</span><span style="color:#E1E4E8">(down,</span></span>
<span class="line"><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--splash-bg</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_r</span><span style="color:#E1E4E8">) * </span><span style="color:#79B8FF">100</span><span style="color:#E1E4E8">) / 10,</span></span>
<span class="line"><span style="color:#E1E4E8"> 1);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FFAB70"> --_splash_b</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--splash-bg</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> -</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_r</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 100</span></span>
<span class="line"><span style="color:#F97583"> -</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_g</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 10</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* Normalizing the values to regular rgb: any changes and adjustements can go here */</span></span>
<span class="line"><span style="color:#FFAB70"> --_rgb_r</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_r</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 255</span><span style="color:#F97583">/</span><span style="color:#79B8FF">9</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --_rgb_g</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_g</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 255</span><span style="color:#F97583">/</span><span style="color:#79B8FF">9</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --_rgb_b</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash_b</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 255</span><span style="color:#F97583">/</span><span style="color:#79B8FF">9</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* Assigning the actual value for the background color. */</span></span>
<span class="line"><span style="color:#FFAB70"> --_splash-bg-value</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> rgb</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_rgb_r</span><span style="color:#E1E4E8">), </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_rgb_g</span><span style="color:#E1E4E8">), </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_rgb_b</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-bg-value</span><span style="color:#E1E4E8">, revert-layer);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* By default, adding a text-shadow (might be overridden later) */</span></span>
<span class="line"><span style="color:#FFAB70"> --_splash-shadow</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">, if(</span><span style="color:#79B8FF">style</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-bg-value</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-bg-value</span><span style="color:#E1E4E8">)):))</span></span>
<span class="line"><span style="color:#79B8FF"> Canvas</span><span style="color:#E1E4E8"> 1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 0</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> Canvas</span><span style="color:#79B8FF"> -</span><span style="color:#E1E4E8">1</span><span style="color:#79B8FF">px</span><span style="color:#79B8FF"> -</span><span style="color:#E1E4E8">1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 0</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> Canvas</span><span style="color:#E1E4E8"> 1</span><span style="color:#79B8FF">px</span><span style="color:#79B8FF"> -</span><span style="color:#E1E4E8">1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 0</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> Canvas</span><span style="color:#79B8FF"> -</span><span style="color:#E1E4E8">1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 1</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8"> 0</span><span style="color:#79B8FF">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> text-shadow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-shadow</span><span style="color:#E1E4E8">, revert-layer);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* If the browser supports relative colors, use them to assign a color instead of a shadow */</span></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">oklch</span><span style="color:#E1E4E8">(from </span><span style="color:#79B8FF">red</span><span style="color:#E1E4E8"> l c h)) {</span></span>
<span class="line"><span style="color:#FFAB70"> --_splash-l</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 0</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#FFAB70"> (l</span><span style="color:#FFAB70"> /</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--l-threshold</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">0.71</span><span style="color:#E1E4E8">) </span><span style="color:#FFAB70">-</span><span style="color:#79B8FF"> 1</span><span style="color:#E1E4E8">) * -infinity,</span></span>
<span class="line"><span style="color:#79B8FF"> 1</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FFAB70"> --_splash-color</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">, if(</span><span style="color:#79B8FF">style</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--splash-bg</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--splash-bg</span><span style="color:#E1E4E8">)):))</span></span>
<span class="line"><span style="color:#79B8FF"> oklch</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> from</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-bg-value</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-l</span><span style="color:#E1E4E8">) 0 </span><span style="color:#79B8FF">h</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_splash-color</span><span style="color:#E1E4E8">, revert-layer);</span></span>
<span class="line"><span style="color:#79B8FF"> text-shadow</span><span style="color:#E1E4E8">: revert-layer;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">} }</span></span></code></pre>
<p>Here is what this mixin does:</p>
<ol>
<li>
<p>On any element, we can add a <code>--splash-bg</code> custom property with a three-digit number.</p>
</li>
<li>
<p>Doing so will enable the “mixin”: the <code>background</code> and <code>text-shadow</code> or <code>color</code> properties will be applied. Without the <code>--splash-bg</code>, thanks to custom cascade layers and <code>revert-layer</code>, these properties will not have any effect on anything evben though we apply them via <code>*</code>.</p>
</li>
<li>
<p>In addition, as we know the background color, we can try using <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors">relative colors</a> to assign a contrasting text color alongside that background! This is thanks to the <a href="https://lea.verou.me/blog/2024/contrast-color/">“On compliance vs readability: Generating text colors with CSS”</a> article by <a href="https://lea.verou.me/">Lea Verou</a>.</p>
</li>
</ol>
<p>I won’t explain what’s going on there in detail: aside from what is explained in all the linked articles, there is nothing too complex going on.</p>
<p>The remaining most interesting part is splitting the incoming three-digit color into three components. There might be a better way to do it, but I used the very helpful <code>round()</code> CSS function for this, plus some math.</p>
<h2 id="some-lessons">Some Lessons</h2>
<p>When I did this experiment, I left some notes to myself.</p>
<ol>
<li>
<p>When we do mixins like that, because we can return any number of properties, it is easy to add something extra — like the contrasting <code>color</code> in addition to the <code>background</code> that we know. This would be not a case with custom functions, or anything that involves only custom properties.</p>
</li>
<li>
<p>If we were to implement “OKSplash” based on OKLCH — that is, we had three pure components for the perceived Lightness, color’s Chroma, and its Hue — we could skip the relative color part, and calcualte the <code>color</code> directly.</p>
</li>
<li>
<p>When we’re inside an <code>@layer</code>, using <code>revert-layer</code> for things inside an <code>@supports</code> or other overrides feels very natural and lifts some weight from the mind: we completely revert the declaration, instead of overriding it to some <em>default</em>.</p>
</li>
<li>
<p>Initially, I saw the intermediate step required for the mixin to work — where we define our value for the property as a separate custom property — as a downside. However, when it is done this way, it is effortless to then reuse this value. In this case, I did not have to change the existing code I wrote for the mixin to use this color to get the contrasting one.</p>
</li>
<li>
<p>When I use <code>round()</code> for regular numbers, I always forget the <code>1</code> in the end. This was a change based <a href="https://github.com/w3c/csswg-drafts/issues/9668">an issue</a> by <a href="https://github.com/Loirooriol">Oriol Brufau</a>, but it is not yet available in all browsers. Testing helps!</p>
</li>
</ol>
<h2 id="thats-it">That’s It</h2>
<p>I really like how we can hide a lot of the complexity behind a simple custom property call. Can we have native mixins already in all browsers, so I won’t have to write these adominations?</p>
<p>Please, <a href="https://opencollective.com/oddbird-open-source">sponsor Oddbird</a> so <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> could work more actively on the specs for native mixins!</p>
<p>And — experiment. I am already looking to write another post — or maybe an article on my main site — about another useful way we could use these mixins for. And I am not planning to stop. So I nudge you to try doing this as well. It is fun.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113719973911092688">on Mastodon</a>!</p>CSS Mixins Everywherehttps://blog.kizu.dev/css-mixins-everywhere/https://blog.kizu.dev/css-mixins-everywhere/On Monday, I published a new article: “Pure CSS Mixin for Displaying Values of Custom Properties”. It is a long one, but you don’t have to read it fully to get something out of it, as I also published an npm package that allows you to use the mixin described in the article right away. But then… I wondered. What if this mixin was available _everywhere_ in my browser?Wed, 29 Jan 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>kinoue64 — tomorrow, the world will end.</dd><dt>Current drink:</dt><dd>Herbal tea (“Tisane Fruits exotique”)</dd></dl><hr /><p>On Monday, I published a new article: <a href="https://kizu.dev/preview-mixin/">“Pure CSS Mixin for Displaying Values of Custom Properties”</a>. It is a long one, but you don’t have to read it fully to get something out of it, as I also published an <a href="https://github.com/kizu/mixins?tab=readme-ov-file#install--use">npm package</a> that allows you to use the mixin described in the article right away.</p>
<p>The mixin itself is for debugging stuff, and one way I envisioned it being used: have a template on CodePen that would include the mixin. Not super convenient (need to pre-select the template, can’t be used with other pre-existing CodePens, etc.), but works. It is also possible to just drop the</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@import</span></span>
<span class="line"><span style="color:#E1E4E8"> url("https://unpkg.com/@kizu/mixins@</span><span style="color:#79B8FF">0.2</span><span style="color:#E1E4E8">.</span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">/preview.css");</span></span></code></pre>
<p>I also included it in this blog, though, importing from <code>node_modules</code> instead of using the CDN. So now it is possible to preview any values here as well:</p>
<p><a href="https://blog.kizu.dev/css-mixins-everywhere/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--preview: pi"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>But then… I wondered. What if this mixin was available <em>everywhere</em> in my browser?</p>
<p>I am a fan of CSS overrides in general, and I am using the Stylus extension for this (<a href="https://addons.mozilla.org/en-US/firefox/addon/styl-us/">for Firefox</a>, <a href="https://chromewebstore.google.com/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?hl=en&pli=1">for Chrome</a>).</p>
<p>What if I would just… add a global override that would be available on every page, and will include the mixin? Now I can just open devtools on any page, add <code>--preview</code> to any element, and “inspect” any values! Or, when doing stuff in a CodePen, I can just use <code>--preview</code> as if it were available natively for me.</p>
<p>Of course, this will be something visible only <em>to me</em>, so if I would want to share such a CodePen with the previews visible, I would need to remember to include the mixin itself as well. But — for the most part, this mixin is purely for debugging. So why not have it available always?</p>
<p>This is the power of CSS mixins: if they do not do anything until you call them, we can always add them and use them when we see fit. A mixin like <code>--preview</code> becomes like a custom browser extension, made with just CSS!</p>
<p>And imagine when we will have native CSS mixins! We could do the same with them: include them always via overrides, and use them for debugging on any page.</p>
<p>Finally, this can be a great way for me to test how robust the mixin’s code is: does it introduce any performance overhead? Will it break in some cases? How annoying is it to have its styles always there in an inspector? Do I want to scope it in some way for this kind of usage, so I would have to add a custom class around something I want to debug?</p>
<p>I am excited to try this out, and adjust the mixin with what I will find. And if you will try this method as well — you’re welcome to, but be warned that it is highly experimental. But then — please, let me know if you have any feedback about it!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113911933363630753">on Mastodon</a>!</p>Photo Walk in Decemberhttps://blog.kizu.dev/walk-december-2024/https://blog.kizu.dev/walk-december-2024/I have a big backlog of photos, and now that I have an ability to embed them in my blog, I will occasionally do so! I am initially posting them on Pixelfed, and this post was originally published there. Pixelfed is cool, maybe you should join it, and post photos there, and not _somewhere else_. If you’re publishing them on your site — reposting them on Pixelfed could also be a good idea.Wed, 15 Jan 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Mammal Hands — Late Bloomer</dd><dt>Current drink:</dt><dd>Pepperming Tea</dd></dl><hr /><p>I have a big backlog of photos, and now that I have an ability to embed them in my blog, I will occasionally do so!</p>
<p>I am initially posting them on Pixelfed, and this post was <a href="https://pixey.org/i/web/post/785237288622073118">originally published there</a>. Pixelfed is cool, maybe you should join it, and post photos there, and not <em>somewhere else</em>. If you’re publishing them on your site — reposting them on Pixelfed could also be a good idea.</p>
<p>Anyways.</p>
<p><img src="pixelfed:785237288622073118/1" alt=""></p>
<p>On December 25 of last year, on the next day after publishing my latest article — <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a> — I went for a walk in a nearby park.</p>
<p>It is usually hard for me to go outside, but I got this habit recently: after I finish an article, I just try to go for a walk. Either on the same day, or the next one. This led to <a href="https://pixey.org/i/web/profile/546076540786363642">my Pixelfed account</a> having a bit more photos than usual in the last few months!</p>
<p>This time, there was another reason to go and take some photos — I bought myself a new lens. I am using an <a href="https://en.wikipedia.org/wiki/Olympus_OM-D_E-M5">Olympus OM-D E-M5</a> Camera — the Micro Four Thirds one from 2012.</p>
<p>Usually, I use the Olympus M.Zuiko Digital 45mm f/1.8 lens, but this was my first time trying their 25mm version. It was nice, although I got too used to the 45mm one.</p>
<p><img src="pixelfed:785237288622073118/2" alt=""></p>
<p>It was a nice walk, during twilight, after the sunset. I think, the park was closing soon, but hey, the gates were open, and there were people still inside, so I did sneak in for a bit.</p>
<p>The park is near <a href="https://en.wikipedia.org/wiki/Ch%C3%A2teau_de_Saint-Germain-en-Laye">Château de Saint-Germain-en-Laye</a> and has a long terrace that overlooks the towns below that stretch up to Paris on the horizon.</p>
<p><img src="pixelfed:785237288622073118/3" alt=""></p>
<p>There were either low clouds, or fog, or smog on the horizon — usually it is possible to see the Eiffel Tower there, on the right from <a href="https://fr.wikipedia.org/wiki/La_D%C3%A9fense">La Défense</a>. This time you couldn’t see them.</p>
<p><img src="pixelfed:785237288622073118/4" alt=""></p>
<p>But at this time you could see the city with the night lights starting to appear here and there, with cars driving on the bridge over the Seine somewhere below. It was a pleasant evening.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113834398506762601">on Mastodon</a>!</p>Intent to Experiment for Longerhttps://blog.kizu.dev/intent-to-experiment-for-longer/https://blog.kizu.dev/intent-to-experiment-for-longer/Today, Chrome published two “intents to ship”: for the new CSS `if()` function, and for custom CSS functions. I informally object to this.Tue, 25 Feb 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Ann Annie — By Morning</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><p>Today, Chrome published two “intents to ship”: <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/EOz7NK6Y0cE/m/VsZveC-fAwAJ">for the new CSS <code>if()</code> function</a>, and <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/bvi4D7eD7wI/m/djYVLu6OAwAJ">for custom CSS functions</a>.</p>
<p>I <em>informally</em> object to this.</p>
<p>Intent to prototype the <code>if()</code> function was <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/ySEBHgVlhBM/m/zO5OcgtWEgAJ">less than a month ago</a>. Its <a href="https://github.com/w3ctag/design-reviews/issues/1045">TAG review</a> has no resolution.</p>
<p>Intent to prototype custom functions was <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/b-BTxKD-Ldc/m/1pyobjq7AQAJ">a year ago</a>, and while there was <em>some</em> prototyping at the time, the new version of what is currently in Canary was started only <a href="https://issues.chromium.org/issues/325504770#comment6">in the last month</a>. Its <a href="https://github.com/w3ctag/design-reviews/issues/1031">TAG review</a> has no resolution as well.</p>
<p>Given how foundational and crucial these features are — I would strongly recommend Google to re-think how they’re planning to ship these features.</p>
<p>Just last year we had a situation where anchor positioning was shipped prematurely, with very substantial changes to its syntax later based on the later feedback. And this was after the feature was in a prototype stage for much longer than both <code>if()</code> and custom functions.</p>
<p>The absense of open issues in CSSWG for these features cannot be taken as a signal that they are ready to ship: authors just started to play with them, and I am not sure engineers and CSSWG members from other browsers had a chance to take an in-depth look into the specs and play with the prototypes just yet.</p>
<hr>
<p>I am very biased: I want these features more than many others. My first article about <a href="https://kizu.dev/conditions-for-css-variables/">“Conditions for CSS Variables”</a> was in 2016.</p>
<p>In 2023 and 2024 I published four articles about various ways we could write conditional CSS, prototyping conditions, functions and mixins:</p>
<ul>
<li><a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a></li>
<li><a href="https://kizu.dev/scroll-driven-state-transfer/">“Scroll-Driven State Transfer”</a></li>
<li><a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a></li>
<li><a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a></li>
</ul>
<p>For a few years, from around 2013 to 2016, I was also a maintainer of the Stylus CSS preprocessor. I wanted conditions, functions, and mixins for a long, long time.</p>
<p>And yet, I don’t want them to ship in Chrome — not right now.</p>
<p>I want these features to be in their <strong>perfect form</strong> when they ship. Maybe not complete — but one where we’re all certain that what we have will not change, and will be future-proof.</p>
<p>Just a month since the prototype to shipping the features is many months too soon. I just had a bit of time to play with them. The feedback that I have is already brewing in me, but I’ll need more time to express it properly. Other authors, I am pretty sure, will need this time too.</p>
<p>If Chrome is to ship these features in their stable browser versions — at the very least — do so under a feature flag that is disabled by default. Let authors play with the features, let other browsers to look into them and consider various use cases, let the Web Platform take a few breaths — and then think about shipping the features <em>for real</em>.</p>
<p>Please. Let us experiment with these features for longer.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/114066434845271193">on Mastodon</a>!</p>Future-Proofing Indirect Cyclic Conditionshttps://blog.kizu.dev/future-proofing-indirect-cyclic-conditions/https://blog.kizu.dev/future-proofing-indirect-cyclic-conditions/When working on another blog post, I noticed that my blog’s styles were broken in Chrome Canary. What happened? A change in how “short-circuiting” of custom property fallbacks works.Sat, 31 May 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Rökkurró — Innra</dd><dt>Current drink:</dt><dd>Yunnan Tea</dd></dl><hr /><p>When working on another blog post, I noticed that my blog’s styles were broken in Chrome Canary.</p>
<p>What happened? A change in how “short-circuiting” of custom property fallbacks works.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>For a bit of context, see <a href="https://github.com/w3c/csswg-drafts/issues/11500">“Short-circuit <code>if()</code> evaluation”</a> issue by <a href="https://github.com/andruud">Anders Hartvoll Ruud</a> in which CSSWG <a href="https://github.com/w3c/csswg-drafts/issues/11500#issuecomment-2669358882">resolved in February</a> to specify a new parsing behavior for all substitution functions. Including custom properties.</p>
<p>Before that change (and what is currently happening in all browsers), <a href="https://www.w3.org/TR/css-variables-1/#cycles">the algorithm for the dependency graph between custom properties in the specs</a> included the mention of the fallbacks:</p>
<blockquote>
<p>For each element, create a directed dependency graph, containing nodes for each custom property. If the value of a custom property <code>prop</code> contains a <code>var()</code> function referring to the property <code>var</code> (including in <strong>the fallback</strong> argument of <code>var()</code>), add an edge between <code>prop</code> and the <code>var</code>.</p>
<p>If there is a cycle in the dependency graph, all the custom properties in the cycle are invalid at computed-value time.</p>
</blockquote>
<p>The most recent <a href="https://drafts.csswg.org/css-values-5/">Editor’s Draft for CSS Values and Units Module Level 5</a> does not mention this and contains <a href="https://drafts.csswg.org/css-values-5/#substitution">a rewritted set of custom property substitution rules</a>.</p>
<p>The corresponding change followed the spec and landed in Chrome Canary <a href="https://github.com/chromium/chromium/commit/bdc06ec50523903db098fa80da5fe92f49e76ce5">in a commit from May 15
</a>. It was known that this <em>will</em> break backwards compat for anything that used this <em>for reasons</em>. However, the only reason we could think of at the time was my hacky technique: <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions”</a>, so we decided to try this, adding a use counter to track the usage of these fallbacks.</p>
<p>Anders did a <a href="https://docs.google.com/document/d/1qHOZr5PK9WQWZtPIQvmAqps74pyjMyZ7uOvqq6MxyZs/edit?tab=t.0#heading=h.f8voyi71vekm">thorough compat investigation</a> of pages that this use counter found.</p>
<p>Of course, my technique was spotted by this use counter, and was mentioned in the investigation:</p>
<blockquote>
<p>Roman invented a terrible (but great) mixin technique which relies on short-circuiting not happening […] This change would definitely break that approach, but Roman was part of the CSSWG decision to make this change, and has accepted the breakage.</p>
</blockquote>
<p>But other than this, the findings do now show any highly problematic use cases, and, if anything, this change could <em>fix</em> some of them.</p>
<p>Well, my blog and some articles on the main site broke, but — I knew about it — and it’s time to find a workaround!</p>
<h2 id="the-workaround">The Workaround</h2>
<p>One of the reasons I was ok with this change — the only use case for this past behavior that I found was for doing conditionals. With <code>if()</code> function being accepted — and even already shipped in Chrome 137 — we will eventually have a proper way of doing conditions, in a much more simple and non-hacky way.</p>
<p>But — the changes required to make <code>if()</code> performant lead to the past behavior — one my technique relied upon — to break. Can we somehow make it continue to work, while still using my technique for browsers that do not yet understand native conditions?</p>
<p>The first idea I had was to just use <code>@supports</code> and override the definition of the custom property that uses the <code>--WHEN</code> in code to use an <code>if()</code> instead. Note that we cannot use a regular override like</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">--color: pink var(--WHEN, var(--condition));</span></span>
<span class="line"><span style="color:#E1E4E8">--color: if(style(--condition): pink);</span></span></code></pre>
<p>as for non-registered custom properties (which we have), they accept <em>anything</em>, and even if the browser does not know about <code>if()</code>, it will only ever use the second declaration here. So, we need an <code>@supports</code>.</p>
<p>Let’s look at a minimal example that uses my technique:</p>
<p><a href="https://blog.kizu.dev/future-proofing-indirect-cyclic-conditions/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example1</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">: }</span></span>
<span class="line"><span style="color:#B392F0">.example1</span><span style="color:#B392F0"> .minimal</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --input</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--bg-value</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --bg-value</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--input</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--bg-value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#E1E4E8">>Pink</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--input: 1"</span><span style="color:#E1E4E8">>Green</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>If you look at this example today in Chrome Canary with the Experimental Web Platform Features flag on, you’ll see that it does not work: the first element there should be pink, as the always defined <code>--WHEN</code> means it will not go to the fallback, and will make the <code>--bg-value</code> valid for all cases.</p>
<h3 id="simple-fallback">Simple Fallback</h3>
<p>Just adding a fallback with <code>@supports</code> works:</p>
<p><a href="https://blog.kizu.dev/future-proofing-indirect-cyclic-conditions/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example2</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">: }</span></span>
<span class="line"><span style="color:#B392F0">.example2</span><span style="color:#B392F0"> .minimal</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --input</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--bg-value</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --bg-value</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--input</span><span style="color:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">: if(():)) {</span></span>
<span class="line"><span style="color:#FFAB70"> --bg-value</span><span style="color:#E1E4E8">: if(</span><span style="color:#79B8FF">style</span><span style="color:#E1E4E8">(--input): </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> background: var(--bg-value, var(--PINK));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#E1E4E8">>Pink</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--input: 1"</span><span style="color:#E1E4E8">>Green</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<aside>
I am using a very hacky-looking minimal `@supports` value — `if(():)`. Currently, it works in Chrome, although it is a bit difficult to understand whether it is _intended_ to work or not. If I’ll have an opportunity, I’ll dig into it, in the meantime, feel free to [read through its syntax](https://drafts.csswg.org/css-conditional-values-1/#condition) and let me know what you think!
</aside>
<p>However, it is a bit verbose — we have to repeat the declaration, and repeat everything inside as well, just in a different form.</p>
<p>Can we somehow keep just one declaration?</p>
<h3 id="complex-fallback">Complex Fallback</h3>
<p>We can, but we need to do two things:</p>
<ol>
<li>Define <code>--WHEN</code> conditionally.</li>
<li>Adjust how we use it.</li>
</ol>
<p><a href="https://blog.kizu.dev/future-proofing-indirect-cyclic-conditions/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example3</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --WHEN</span><span style="color:#E1E4E8">: ;</span></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">top</span><span style="color:#E1E4E8">: if(():)) {</span></span>
<span class="line"><span style="color:#FFAB70"> --WHEN</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">initial</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example3</span><span style="color:#B392F0"> .minimal</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --input</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--bg-value</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --bg-value</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--WHEN</span><span style="color:#E1E4E8">, if(</span><span style="color:#79B8FF">style</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--input</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--input</span><span style="color:#E1E4E8">)):));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--bg-value</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#E1E4E8">>Pink</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"minimal"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--input: 1"</span><span style="color:#E1E4E8">>Green</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Here, our definition of <code>--WHEN</code> with <code>@supports</code> will need to be added just once, and then, whenever we want to add this condition, we could do it by wrapping the value inside <code>--WHEN</code>’s fallback in a special <code>if()</code>.</p>
<p>Why this will work:</p>
<ul>
<li>
<p>When <code>if()</code> is supported, the <code>--WHEN</code> will be <code>initial</code>, so we will skip to the fallback. Then, we will check for the <code>--input</code> — and this check might create our short circuit if the <code>--bg-value</code> will reference it as expected, or, with almost any other valid value, will result in a “space” value as any value will be equal to itself.</p>
</li>
<li>
<p>When <code>if()</code> is not supported, the browser will still <em>accept</em> all the tokens, but will try to substitute all the custom properties, and will see the <code>var(--input)</code> inside the <code>--WHEN</code>’s fallback, which might create the short circuit.</p>
</li>
</ul>
<p>This requires us to repeat the <code>--input</code>’s name, but otherwise it’s coincise enough.</p>
<aside>
It might seem that using the value of some variable on both sides of `: ` in `style(--input: var(--input))` is cyclic, but it is not — this is not an assignment, but a check.
</aside>
<h2 id="an-unrelated-tanatan2-breakage">An Unrelated <code>tan(atan2())</code> Breakage</h2>
<p>Curiously, literally while I was working on this article, <a href="https://github.com/oddvernes">Oddbjørn Øvernes</a> <a href="https://front-end.social/@oddvernes/114602912044928080">reported</a> an issue with <a href="https://kizu.dev/preview-mixin/">“Pure CSS Mixin for Displaying Values of Custom Properties”</a> that uses this technique in Chrome. However, it was in <em>stable</em> Chrome, and unrelated to short-circuiting. After some debugging, I found out that it was an issue with how it handles <code>tan(atan2())</code>. I already published a <code>0.2.1</code> version of this mixin that has both issues fixed in it, and <a href="https://issues.chromium.org/issues/421559833">reported the bug to Chromium</a>.</p>
<h2 id="final-words">Final Words</h2>
<p>Who could’ve guessed that hacky code could have issues? Well, in this case we knew about it, and now accounted for it (although, I will still need to update the <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a> article with the corresponding changes).</p>
<p>And, now we now have a way to continue using this hacky — but mostly cross-browser — technique for a subset of inline conditions that check for an existance of some value.</p>
<p>I still hope you won’t use it in production!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/114604599433345921">on Mastodon</a>!</p>Functional Capturinghttps://blog.kizu.dev/functional-capturing/https://blog.kizu.dev/functional-capturing/Chrome currently has an experimental implementation of custom CSS functions in its Canary version. In a small series of blog posts, I’ll write about a few things I found interesting in the current prototype implementations of functions and conditions. This post is about one feature of custom functions that I will likely use all the time, but which might not be obvious at the first glance.Tue, 03 Jun 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>mudy on the sakuban — Newtype Theory</dd><dt>Current drink:</dt><dd>Jasmine Green Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>Chrome currently has an experimental implementation of <a href="https://drafts.csswg.org/css-mixins-1/#defining-custom-functions">custom CSS functions</a> in its Canary version and also recently shipped <a href="https://drafts.csswg.org/css-values-5/#if-notation"><code>if()</code> conditions</a> in stable Chrome 137.</p>
<p>In February, I wrote a quick post about them: <a href="/intent-to-experiment-for-longer/">“Intent to Experiment for Longer”</a> — more specificlaly, about how it is better to wait before shipping the features without sufficient developer feedback.</p>
<p>One thing I forgot to mention in that post: the features, as far as I tested them, worked pretty well, and I generally liked their design. My main blocker that was there for functions — a necessity to explicitly define dependencies for functions — was <a href="https://github.com/w3c/csswg-drafts/issues/10954#issuecomment-2623138036">resolved to be removed</a> (official resolution: “Kill <code>using</code> with fire”), and, with it, I did not yet find any other personal blockers, for now.</p>
<p>That said: even when the design and implementation are sound, with the Web Platform it is always better to be on a more cautious side, especially with foundational features. And while I did not yet find any other blocking issues, this does not mean they do not exist. I would be happy if there are none! But if you’re a web developer: please, play with these new features, and give your feedback.</p>
<p>In a small series of blog posts, I’ll write about a few things I found interesting in the current prototype implementations of functions and conditions.</p>
<p>This post is about one feature of custom functions that I will likely use all the time, but which might not be obvious at the first glance.</p>
<h2 id="basic-capturing">Basic Capturing</h2>
<p>Before continuing, I recommend reading my <a href="/captured-custom-properties/">“Captured Custom Properties”</a> post, in which I talk a bit about the registered custom properties, some use cases for them, and a pattern I currently use with them.</p>
<aside>
In short: a registered custom property, when registered with a certain type, can store the resolved value instead of the sequence of tokens which custom property usually pass around. A `1em` will expand to something like `16px`, losing the association with the element it’s used on.
<p>One notable use case for it that I <a href="/captured-custom-properties/#named-container-query-length-units-workaround">mentioned in the above article</a> is working around the absence of named container query length units, an <a href="https://github.com/w3c/csswg-drafts/issues/7858">issue about which</a> was initially opened by <a href="https://una.im/">Una Kravets</a>, and where <a href="https://github.com/w3c/csswg-drafts/issues/7858#issuecomment-1484103141">I originally shared this workaround</a> in the comments.</p>
<p>Recently, <a href="https://thebabydino.github.io/">Ana Tudor</a> wrote an article about this use case as well: <a href="https://frontendmasters.com/blog/using-container-query-units-relative-to-an-outer-container/">“Using Container Query Units Relative to an Outer Container”</a>.</p>
</aside>
<p>With custom functions, some of those use cases could be solved much more elegantly!</p>
<p>Let’s look at one example from my “Captured Custom Properties” post.</p>
<h3 id="registered-custom-property-example">Registered Custom Property Example</h3>
<p>In this example, we can use a custom property to “evaluate” its value on the element, so it will store the value of <code>1.5em</code> in pixels, so it could be used on its children through inheritance.</p>
<p><a href="https://blog.kizu.dev/functional-capturing/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@property</span><span style="color:#E1E4E8"> --registered-font-size {</span></span>
<span class="line"><span style="color:#E1E4E8"> syntax: "<length</span><span style="color:#F97583">></span><span style="color:#E1E4E8">";</span></span>
<span class="line"><span style="color:#85E89D"> initial-value</span><span style="color:#E1E4E8">: 0px;</span></span>
<span class="line"><span style="color:#E1E4E8"> inherits: true;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example-reg</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.666</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --registered-font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--registered-font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example-reg"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Outer:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Foo</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Inner:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Bar</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This is great, and while my pattern of having a dedicated suit of registered custom properties works well, we have to register new custom properties whenever we want to use multiple of them on the same element.</p>
<p>Even though you cannot register a custom property from inside a custom function, one of their features works similarly, and we can use it to simplify things a lot.</p>
<h3 id="custom-function-example">Custom Function Example</h3>
<aside class="warning warning--custom-functions">
Currently, custom functions are only available in [Chrome Canary](https://www.google.com/chrome/canary/) with an `Experimental Web Platform features` feature flag on at `chrome://flags/`.
</aside>
<p><a href="https://blog.kizu.dev/functional-capturing/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --capture-length(--value <length>) {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: var(--value);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example-fun</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.666</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-font-size</span><span style="color:#E1E4E8">: --capture-length(</span><span style="color:#79B8FF">1.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#79B8FF">span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-font-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> & </span><span style="color:#B392F0">.inner</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example-fun"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Outer:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Foo</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>Inner:</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>Bar</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This works the same! But now we have a reusable <code>--capture-length()</code> function, and with its parameter being <em>typed</em>, this parameter behaves like a registered custom property — capturing its value, and passing the evaluated value, and not the tokens in abstract.</p>
<p>The <a href="https://drafts.csswg.org/css-mixins-1/#evaluate-a-custom-function">spec text for the custom function evaluation</a> explicitly describes how exactly those parameters are registered:</p>
<blockquote>
<p>For each function parameter of <em>custom function</em>, create a custom property registration with the parameter’s name, a syntax of the parameter type, an inherit flag of “true”, and no initial value. Add the registration to <em>registrations</em>.</p>
</blockquote>
<p>Interestingly, if we define a <em>return type</em> for a function, it will also be “captured”, so those two are identical:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --capture-length(--value <length>) {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: var(--value);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --capture-length(--value) returns <length> {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: var(--value);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>But using the type for a parameter is just so slightly more compact.</p>
<h3 id="use-cases-for-capturing-length">Use Cases for Capturing Length</h3>
<p>I won’t repeat <a href="/captured-custom-properties/">everything I wrote in my original article about it</a>, but to sum up some common use cases:</p>
<ul>
<li>
<p><a href="/captured-custom-properties/#detecting-property-support">“Detecting <code>@property</code> Support”</a>.</p>
</li>
<li>
<p><a href="/captured-custom-properties/#named-container-query-length-units-workaround">“Named Container Query Length Units Workaround”</a>.</p>
</li>
<li>
<p><a href="/captured-custom-properties/#named-container-query-length-units-workaround">“Working Around Type Limitations”</a>.</p>
</li>
</ul>
<h2 id="universal-capturing">Universal Capturing</h2>
<p>The function above only captured a single type — <code><length></code>. But we can make it capture multiple different types at the same time!</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --capture(</span></span>
<span class="line"><span style="color:#E1E4E8"> --value type(<length>|<number>|<color>)</span></span>
<span class="line"><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: var(--value);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This will work just as well!</p>
<h3 id="more-use-cases">More Use Cases</h3>
<p>However, the use cases for things outside <code><length></code> are rare.</p>
<p>One example for <code><color></code> I also gave in my previous post on topic: <a href="/captured-custom-properties/#unlocking-style-queries">“Unlocking Style Queries”</a>.</p>
<p>Until now, if we wanted to check the value of some color, like inside a style query, we had to “normalize” it and use a registered custom property for this.</p>
<p>We can do this with our <code>--capture</code> function as well — and! — with conditions in CSS, we could implement a <code>--light-dark()</code> custom function similar to what I described in my <a href="/querying-the-color-scheme/">“Querying the Color Scheme”</a> post, but one that will work without the downside of style queries!</p>
<p>Here is a heavily modified example from the <a href="/querying-the-color-scheme/#single-source-of-truth">“Single Source of Truth”</a> section of that post, but now using the custom functions and <code>if()</code>:</p>
<p><a href="https://blog.kizu.dev/functional-capturing/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --capture(</span></span>
<span class="line"><span style="color:#E1E4E8"> --value,</span></span>
<span class="line"><span style="color:#E1E4E8"> --_value type(<length>|<number>|<color>):</span></span>
<span class="line"><span style="color:#E1E4E8"> var(--value)</span></span>
<span class="line"><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: var(--_value);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --light-dark(--a, --b) {</span></span>
<span class="line"><span style="color:#E1E4E8"> --captured-color:</span></span>
<span class="line"><span style="color:#E1E4E8"> --capture(light-dark(white, black));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> result: if(</span></span>
<span class="line"><span style="color:#E1E4E8"> style(--captured-color: --capture(</span><span style="color:#B392F0">#FFF</span><span style="color:#E1E4E8">)):</span></span>
<span class="line"><span style="color:#E1E4E8"> var(--a);</span></span>
<span class="line"><span style="color:#E1E4E8"> else:</span></span>
<span class="line"><span style="color:#E1E4E8"> var(--b);</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example--light</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">light</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example--dark</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> color-scheme</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">dark</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.example</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: Canvas;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: CanvasText;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583">px</span></span>
<span class="line"><span style="color:#E1E4E8"> --light-dark(</span><span style="color:#79B8FF">solid</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">dashed</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#FFAB70"> --light-dark</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">hotpink</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">layer</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#79B8FF">dark-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: --light-dark(</span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">, revert-layer);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0"> .light-only</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: --light-dark(revert-layer, </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example--light"</span><span style="color:#E1E4E8">>I should be always light. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"example example--dark"</span><span style="color:#E1E4E8">>I should be always dark. Current scheme: <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"light-only"</span><span style="color:#E1E4E8">>light</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dark-only"</span><span style="color:#E1E4E8">>dark</</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">>.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>We can see that our <code>--light-dark()</code> function works for any values — not just colors — and works perfectly on the same element on which we define the <code>color-scheme</code>!</p>
<p>There are a few interesting things going on that demand additional explanations.</p>
<h4 id="capturing-light-dark">Capturing <code>light-dark()</code></h4>
<p>You could notice that the CSS of the <code>--capture</code> function here is different from what I proposed initially: it has <em>two</em> arguments, with the second one having its value assigned from the first one by default.</p>
<p>What is this, and why? The reason: <code>light-dark()</code> works only for color contexts. It might be Chrome’s implementation bug, but just passing <code>light-dark (…)</code> to a custom function, even if the argument is typed, will not capture it.</p>
<p>But by doing this gambit, where we <em>reassign</em> that argument to another typed argument, we can work around this!</p>
<h4 id="revert-layer-for-now"><code>revert-layer</code>, for now</h4>
<p>I’m using a <code>revert-layer</code> and a custom cascade layer around the <code>if()</code>s that touch <code>display</code> property, but in the future we could use <code>revert-rule</code> for this.</p>
<p>If you don’t know what <code>revert-rule</code> is — in January CSSWG <a href="https://github.com/w3c/csswg-drafts/issues/10443#issuecomment-2627865962">resolved</a> to add it to CSS, following <a href="https://github.com/w3c/csswg-drafts/issues/10443">“New <code>!revertable</code> flag to mark a declaration as ‘can be reverted when IACVT’”</a> by <a href="https://lea.verou.me/">Lea Verou</a>, and an older proposal <a href="https://github.com/w3c/csswg-drafts/issues/5319">“Proposal: additional CSS-Wide Keyword, ‘ignore’ (primarily for css variable fallbacks)”</a> by <a href="https://kizu.dev/fit-to-width/">Jane Ori</a>.</p>
<p>This CSS-wide keyword will be <em>invaluable</em> for any conditional styles!</p>
<h4 id="if-evaluation"><code>if()</code> evaluation</h4>
<p>While the <code>if()</code> did ship in stable Chrome 137, it is not yet in its final form. Currently, you have to jump through a few hoops when you want to compare a return value of some function: assign it to another custom property, and also make sure the types match inside <code>style()</code> — <code>style(--captured-color: --capture(#FFF))</code> — here we have to explicitly call our <code>--capture()</code> around the <code>#FFF</code> to make sure it will be properly compared with the <code>--captured-color</code>.</p>
<p>This is a known “gotcha”: for example, <a href="https://css-articles.com/">Temani Afif</a> wrote a <a href="https://css-tip.com/inline-if/">“How to correctly use <code>if()</code> in CSS”</a> post about this, in which he points that we can use registered custom properties to fix this. Our <code>--capture()</code> function might be an even better solution to this!</p>
<p>And, in the future, the way <code>style()</code> is evaluated might change, so there is a chance we could simplify this place later.</p>
<h3 id="color-capturing-limitations">Color Capturing Limitations</h3>
<p>When exploring capturing the <code><color></code> type for <em>another</em> article, I discovered that it does not work for any colors that include <code>currentColor</code>.</p>
<p>I won’t repeat myself, but I welcome you to check the <a href="https://kizu.dev/svg-linked-parameters-workaround/#problem-of-the-current-color">“Problem of the Current Color”</a> section of my <a href="https://kizu.dev/svg-linked-parameters-workaround/">“Passing Data into SVG: Linked Parameters Workaround”</a> article (which I also recommend reading in full — it contains <em>many</em> fun bits!)</p>
<p>I imagine there might be other similar cases, where we couldn’t capture something that evaluates at <em>used</em> time, and not <em>computed</em> which both registered custom properties and typed function arguments care about.</p>
<h2 id="fun-future">Fun Future</h2>
<p>I can’t wait for what else we could do with custom functions, <code>if()</code>, <code>revert-rule</code>, and many other incoming features which will make the foundation of future CSS.</p>
<aside>
Big thanks to [Miriam Suzanne](https://www.miriamsuzanne.com/) for the [“CSS Mixins & Functions Explainer”](https://css.oddbird.net/sasslike/mixins-functions/#defining-a-mixin-the-mixin-rule) which kickstarted the current work on functions and future work on mixins. I can’t wait for her talk about all of that at [CSS Day](https://cssday.nl/) this week!
<p>If you want to support her work on CSS specs, I recommend supporting <a href="https://opencollective.com/oddbird-open-source">OddBird Open Source</a> on Open Collective.</p>
</aside>
<p>At the first glance, functions might seem to be just a syntax sugar over something you could otherwise achieve with preprocessors. But, their type capabilities, and the way they interact with everything else in CSS, allows us to abstract things in much more dynamic ways than previously possible in static CSS.</p>
<p>If you want to play with that future: I recommend trying Chrome Canary with its Experimental Web Platform Features flag, and give your feedback to <a href="https://github.com/w3c/csswg-drafts/issues/">CSS Working Group</a> and <a href="https://issues.chromium.org/issues/wizard">Chromium</a>. And me — I would love to look at your experiments as well!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/114619983960672910">on Mastodon</a>!</p>Fit-to-Width Status Update: Prototype and Issueshttps://blog.kizu.dev/text-fit-update/https://blog.kizu.dev/text-fit-update/In which I present the current state of things and share links and descriptions of issues I opened in the CSS Working Group’s GitHub following the Chrome team’s feedback.Thu, 02 Oct 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>S — Falling</dd><dt>Current drink:</dt><dd>Camomile Tea</dd></dl><hr /><style>{`
h1 {
font-size: 3.125rem;
}
`}</style>
<p>Since <a href="/fit-to-width-discussions-and-feedback/">my last post about fitting some text into a box</a>, Chrome’s team posted <a href="https://github.com/w3c/csswg-drafts/issues/2528#issuecomment-3336857019">their feedback</a> based on the work they did while prototyping.</p>
<p>I agreed with some of what they wrote, but I also strongly disagreed with a bunch of it.</p>
<p>To move things forward, I created four issues, <a href="https://github.com/w3c/csswg-drafts/issues/12885">one of them</a> is about a technical issue about which spec this feature should belong to, but the other three are something I’d invite you to read and consider:</p>
<ol>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/12886">“Text Fitting: Default scaling limit”</a> — about my proposed solution of adding a default 200% limit to the feature.</p>
<p>Chrome team’s does not think it will work, but did not yet elaborate on why. Since posting about my proposed solution, I’ve received zero feedback about it anywhere: neither positive nor negative.</p>
<p>If you care about accessibility and want to help — I’ll be happy if you will consider <a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/#the-problem-dependency-on-viewport">the problem</a> and the proposed solution. Is it enough? Is there an alternative? What do you think?</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/12887">“Text Fitting: Shrinking and Growing”</a> — about having one or two ways to approach the fitting thing.</p>
<p>My initial thought was that we should have just one <code>text-grow</code> property, and in my previous post I <a href="/fit-to-width-discussions-and-feedback/#problems-of-text-shrink">described why</a>.</p>
<p>Chrome team’s insists that authors want to have <code>text-shrink</code> too. I can see that there are use cases where approaching fitting from the <code>text-grow</code> will be awkward (although possible), and in this issue propose an alternative approach: to use a single <code>text-fit</code> property with two possible values of the used method — <code>text-fit: grow</code> and <code>text-fit: shrink</code>. This allows using only one of them, eliminating a bunch of possible issues (like the conflict with the 200% limit).</p>
<p>If you were to want to use this feature — how would you want to use it? Would you ever want to use both methods at the same time? Is the potential accessibility problems (not being able to rely on the 200% limit) worth doing so when having a single method will allow doing everything anyways?</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/12888">“Text Fitting: Scaling of things based on font-size”</a> — about the core of how the new feature should work.</p>
<p>My <a href="https://kizu.dev/fit-to-width/">hacky technique</a> works in a finite number of steps, and allows scaling the text in a “true” manner, where any elements or properties that have values based on our element’s font-size would follow the scaling change, including applying the optical sizing axis of variable fonts properly (although, with an acceptable approximation).</p>
<p>Chrome’s team argues that this won’t be possible to implement in a performant manner. I am not a browser engineer, and can’t argue about this, but I doubt it is impossible to implement a solution that won’t be faster than my hacky way of doing it via containers and copies of the content. Chrome’s team proposes to make this implementation-dependent, which I strongly opposed, as this undermines the predictibility and power this feature can give authors in controlling typography.</p>
<p>I don’t know what non-browser engineers can contribute to this discussion. Maybe provide their use cases for things scaling that Chrome team things are ok to omit? And if you’re a browser engineer, please, look at my technique, and tell me you want to see it used everywhere in place of the native subpar solution. Because this is what will happen if the native feature will not cover the common use cases that people have.</p>
</li>
</ol>
<hr>
<p>Initially, it was resolved that I will become a co-editor for this spec. I wanted to start a draft of things how I see them, but with the Chrome team’s prototype, I don’t really have anything to draft, as their vision is very far from mine. First, we need to find a common ground and only then I could try writing something. After all, I never edited a spec before, and starting from something <em>in this state</em> might not be a good idea.</p>
<p>If you care about typography and accessibility, please, provide any feedback, privately or publicly. It’s difficult to move in the darkness, without almost any feedback from authors. I am grateful for the critique of the accessibility issues that folowed the resolution to add the feature to CSS, but since then, it was silent so far, with proposed solutions not getting evaluated.</p>
<p>It would be great to have a constructive discussion, and work on making this feature a reality without compromising on anything.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115301367149898532">on Mastodon</a>!</p>November, Againhttps://blog.kizu.dev/november-again/https://blog.kizu.dev/november-again/For the third time, I am attempting to write a blog post for every day of November. I managed to do it for 2023 and 2024. I won’t promise I’ll manage to post every day this time, but I’ll try.Sat, 01 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — Seal Beach</dd><dt>Current drink:</dt><dd>Ceylon tea</dd></dl><hr /><p>For the third time, I am attempting to write a blog post for every day of November. I managed to do it for 2023 and 2024. I won’t promise I’ll manage to post every day this time, but I’ll try.</p>
<h2 id="apple-annie">Apple Annie</h2>
<p>I was not sure if I will do this attempt, but when thinking about the coming November, I couldn’t stop thinking about <a href="https://web.archive.org/web/20241214222059/https://anniegreens.lol/">Anne Sturdivant</a> <a href="https://neatnik.net/remembering-anne-sturdivant/">who passed at the beginning of this year</a> (post by <a href="https://adam.omg.lol/">Adam Newbold</a> — thanks for letting us know), and who was the constant presence for this challenge for the last years.</p>
<p>Annie was an inspiration, and I loved how many different topics she covered in her blogs. I mentioned her posts and experiments five times in my blog, and I am endlessly sad that no new posts of her will be mentioned here.</p>
<p>But I will try to at least continue doing this challenge: even though it was always very tough, it was always <em>productive</em>. For me, that challenge will now always be associated with Annie.</p>
<h2 id="burnout">Burnout</h2>
<p>I did not write about CSS a lot this year, right? Neither on my main site, nor in this blog. And I did not do many new experiments.</p>
<p>I am a perfectionist, and often it feels like, sometimes, I care too much about what I do. And then, when I expect the same care from others, and find that it is just not there, it can hurt.</p>
<p>My debt of spoons is big, and it is hard to find strength for doing anything.</p>
<p>So many drafts, so many of them are not finished, not published, covered by digital dust, crumbled in a corner between dropped anime series and unfinished video games.</p>
<p>My hope is that having to post each day of this month will at least produce <em>something</em>.</p>
<h2 id="the-plan">The Plan</h2>
<p>I have a big backlog of stuff I want to write about, but I also created a list of what I could write about this month specifically. I won’t post it here, but here is what I will <em>try</em> to do:</p>
<ul>
<li>Every weekend I will post something non-CSS related: more personal notes, thoughts, maybe game reviews? We’ll see.</li>
<li>Weekdays will be for more front-end related stuff. CSS. Maybe something else. Maybe will do some more work on this blog and post some dev logs?</li>
</ul>
<p>Other than that, I don’t think I will follow any specific structure. I hope that on the weekends I could manage start writing drafts for some of the future November posts, just so I will be not as pressed to do so on the actual days.</p>
<p>I want to say and write even more now that I started — as it often happens with me. The hardest thing is to begin, then words start flowing.</p>
<h2 id="thank-you">Thank You</h2>
<p>If you read this post — thank you. Sometimes it feels that the internet of old is gone. But anyone who has it in them to read random musings of people on the web contributes to the idea of independent network.</p>
<p>And if you’ll want to write a few more posts than usual this November — send them my way, regardless of the topic — I’ll be happy to read them.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115475111558013907">on Mastodon</a>!</p>Photo Walk in Marchhttps://blog.kizu.dev/walk-march-2025/https://blog.kizu.dev/walk-march-2025/Well… It is November, but I am sharing photos from my walk from this March. I already published them on my Pixelfed account almost right after taking them, but I really want to continue posting them here as well.Sun, 02 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — Dynamics of subway</dd><dt>Current drink:</dt><dd>Ceylon tea</dd></dl><hr /><p>Well… It is November, but I am sharing photos from my walk from this March. I already published them on my Pixelfed account almost right after taking them, but I really want to continue posting them here as well.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“A nice spring day” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>This was my first walk with both a new camera, and a new lens:</p>
<ul>
<li>Camera is <a href="https://en.wikipedia.org/wiki/OM_System_OM-3">OM System OM-3</a>.</li>
<li>Lens is OM System M.Zuiko Digital 17mm f/1.8 II.</li>
</ul>
<p>If you don’t know — “OM System” is the brand name for <a href="https://en.wikipedia.org/wiki/OM_Digital_Solutions">the company</a> that bought Olympus camera division, so they basically continuing doing the same: releasing new cameras and lenses for <a href="https://en.wikipedia.org/wiki/Micro_Four_Thirds_system">micro four thirds</a> system.</p>
<p>My last camera — <a href="https://en.wikipedia.org/wiki/Olympus_OM-D_E-M5">Olympus OM-D E-M5</a> — was released in 2012, and I bought it for myself in 2013. I don’t often upgrade my gear!</p>
<p><img src="pixelfed:809380728694054639" alt=""></p>
<p>This lens is now the widest lens I have, although in full frame equivalent it is not as wide — it would be 34mm there.</p>
<p>But, for me, it <em>is</em> wide: my favorite lens before that was 45mm in micro four thirds, so a 90mm equivalent.</p>
<p>I am not that used to this wide of an aperture, but I was glad that I went into the forest — unlike my past lens that allowed me to focus on details, this lens made it possible to get more of the surroundings into the frame.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Narrow footpath” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Winter was over, and while the trees did not yet get their leaves, the grass was already started to get greener, and, occasionally, small flowers started to show up among fallen leaves from the last year.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Tiny flower” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>It would’ve been harder to depict how tall are the trees in the forest without a wide lens: when you meet someone on the path, they can look very small in comparison.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Leafless trees” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>I really liked the texture of the sprawling oak branches against the sky. I hope the conditions in your code don’t look like this:</p>
<p><img src="pixelfed:810978614686558148" alt=""></p>
<p>While most of the trees were leafless, some smaller trees had leaves sprouting on them, and flowers starting to bloom.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Blooming flowers” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>That day the weather was nice, and there were several people in the forest, either walking by themselves, or with their dogs.</p>
<p><img src="pixelfed:811610229114043023" alt=""></p>
<p>To the east of the forest there is a long terrace that is overlooking Paris. It is a part of the park, and has a few entrances in the wall that surrounds its park area.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Entrance to the terrace” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>It is always a great view from the terrace.</p>
<p><img src="pixelfed:812393829869436641" alt="">
<img src="pixelfed:812986135263749555" alt="">
<img src="pixelfed:813797119357494978" alt=""></p>
<p>After walking through the terrace and the park, I entered the city again, and went back home through its narrow streets.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Well, that’s not a street, of course.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>I like to use different paths when getting back from my walks: it if nice to notice new things and places that you did not see before.</p>
<p><a href="https://blog.kizu.dev/walk-march-2025/">“Very cozy corner” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Courtyards are often closed off, but sometimes you can peek there, and they can be pretty interesting too.</p>
<p><img src="pixelfed:814417117161899268" alt=""></p>
<p>It is nice to revisit some of the older photos and older memories. I still have many photos posted on Pixelfed that I will share here in the future, and even more that I did not publish anywhere yet.</p>
<p>I need to get a habit to post more, and go out with a camera more.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115481041392382301">on Mastodon</a>!</p>Inline Custom Identifiershttps://blog.kizu.dev/inline-custom-identifiers/https://blog.kizu.dev/inline-custom-identifiers/This is a quick post about a pattern that I use more and more: a way to connect elements that require named custom or dashed identifiers for various CSS features.Mon, 03 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Doing the Right Thing</dd><dt>Current drink:</dt><dd>Green tea with bergamot, kiwi, yellow peach, orange blossom and violet flower</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>This is a quick post about a pattern that I use more and more: a way to connect elements that require named custom or <a href="/dashed-idents-for-everything/">dashed identifiers</a> for various CSS features.</p>
<p>I constantly use this pattern, but never explicitly wrote about it, even though I used it in many of my experiments.</p>
<p>The reason I finally do it now is because of <a href="https://mastodon.social/@Meyerweb/115472719015829847">a question</a> by <a href="https://meyerweb.com/">Eric Meyer</a> in Mastodon about how to connect two elements for anchor positioning in absence of the <code>anchor</code> attribute (which is <a href="https://github.com/whatwg/html/pull/9144">in limbo of standardization</a>: it is uncertain if we will ever have it).</p>
<h2 id="the-pattern">The Pattern</h2>
<p>The pattern is pretty simple: we use inline styles to add custom properties with the same custom identifier, and then use these custom properties in CSS.</p>
<p><a href="https://blog.kizu.dev/inline-custom-identifiers/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">strong</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--is: --hello"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">strong</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">em</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"--for: --hello"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"anchored"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> World</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">em</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">[</span><span style="color:#B392F0">style</span><span style="color:#F97583">*=</span><span style="color:#9ECBFF">'--is:'</span><span style="color:#E1E4E8">] {</span></span>
<span class="line"><span style="color:#79B8FF"> anchor-name</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--is</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.anchored</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">absolute</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> position-anchor</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--for</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> top</span><span style="color:#E1E4E8">: anchor(</span><span style="color:#79B8FF">outside</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: anchor(</span><span style="color:#79B8FF">outside</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The names I like to use: <code>--is</code> for naming something, and <code>--for</code> (similar to <code><label></code>’s <code>for</code> attribute) for referencing.</p>
<h3 id="inline-styles">Inline Styles?</h3>
<p>I often see people either neglect inline styles, or putting too much stuff into them. In my opinion, the proper way to use inline styles is for putting custom properties into them.</p>
<p>Regular properties will be too high in the cascade when put inline, which is why we should never use them there.</p>
<p>Custom properties, on the other hand, are much safer: we can use them as an API and abstract certain features through them. Of course, it is possible to have cascade conflicts with them as well, but it is up to use to design that API in a way the conflicts could be avoided.</p>
<p>That’s why I recommend this pattern, and recommend using inline styles for assigning unique custom properties per element.</p>
<h3 id="attribute-selector">Attribute Selector</h3>
<p>This is another pattern that I never wrote about, and an article about which is long overdue, although I gave a lightning talk about it at dotCSS 2019 conference (<a href="https://www.youtube.com/watch?v=ciu1rQjmnIA&list=PLMW8Xq7bXrG7h_ujkOx8wu6kb7vZsvcyv&index=8">video</a>, <a href="https://kizu.dev/inline/">slides</a>). Many things changed since then, and if I were to write about this approach properly, I’ll need to revisit many of my past assumptions.</p>
<p>But, in short, the idea is that we can use <a href="https://drafts.csswg.org/selectors/#attribute-selectors">attribute selectors</a> to match any elements with inline custom property definitions, like <code>[style*='--is:']</code> in the above example. The <code>*=</code> means that the part afterwards can be present at any place in the attribute, and if we match on the name of the custom property alongside the <code>:</code>, then unless we use very funky whitespace, or have variable names that include our name partially, like <code>--foo--is</code> for the above example, we can be pretty certain that we will only select elements that define such properties.</p>
<p>After matching, we know that we have this custom property, and can use it right away.</p>
<h2 id="other-examples">Other Examples</h2>
<p>I used this pattern at least in the following articles on my main site:</p>
<ul>
<li><a href="https://kizu.dev/anchor-positioning-experiments/">“Future CSS: Anchor Positioning”</a></li>
<li><a href="https://kizu.dev/scroll-driven-animations/">“Future CSS: Wishes Granted by Scroll-driven Animations”</a></li>
<li><a href="https://kizu.dev/scroll-driven-state-transfer/">“Scroll-Driven State Transfer”</a></li>
<li><a href="https://kizu.dev/shrinkwrap-problem/">“The Shrinkwrap Problem: Possible Future Solutions”</a></li>
</ul>
<p>I am pretty sure I used this pattern somewhere else, but I can’t remember where.</p>
<h2 id="try-itout">Try it Out!</h2>
<p>That’s it for today! We are getting more and more features in CSS that rely on connecting things through dashed idents, and, in the absence of something better, inline styles are a great way to do so.</p>
<p>If you evern find yourself needing these types of references — try this pattern, and let me know if it was helpful!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115485328234195494">on Mastodon</a>!</p>Renaming Outer Variables in CSS Functionshttps://blog.kizu.dev/renaming-outer-variables-in-functions/https://blog.kizu.dev/renaming-outer-variables-in-functions/In which I continue a series of posts about my initial experiments with custom CSS functions. This one is about a not very useful (but fun) nuance about their arguments.Tue, 04 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>österreich — I’ll Take You Everywhere</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>In <a href="https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1930463996">one of the first drafts</a> of the custom CSS functions by <a href="https://xanthir.com/">Tab Atkins-Bittner</a>, if you wanted to use variables from the outer scope, you had to explicitly list them when defining the function like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --foo(--arg1, --arg2) using (--var1, --var2) {…}</span></span></code></pre>
<p>There was some pushback from many people about this, <a href="https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1935575164">including from me</a>, and, eventually, this restriction was removed, with all custom properties from the outer scope now being available inside the custom functions without listing them. Great!</p>
<p>At the time, <a href="https://github.com/w3c/csswg-drafts/issues/9350#issuecomment-1939748123">I wondered</a> if we could reintroduce the <code>using</code> keyword or something similar as something that could allow us to <em>rename</em> the variables in the outer scope, allowing us to use them in the function’s scope with different names.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --foo() {</span></span>
<span class="line"><span style="color:#F97583"> @return</span><span style="color:#E1E4E8"> var(--bar);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --baz() using (--bar as --outer-bar) {</span></span>
<span class="line"><span style="color:#E1E4E8"> --bar: something;</span></span>
<span class="line"><span style="color:#6A737D"> /* will be `--a: something` */</span></span>
<span class="line"><span style="color:#E1E4E8"> --a: --foo();</span></span>
<span class="line"><span style="color:#6A737D"> /* We can still access outer `--bar` */</span></span>
<span class="line"><span style="color:#E1E4E8"> --b: var(--outer-bar);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Later, while playing with the currently specified custom functions in Chrome Canary, I found out that we already can kinda do the same with the optional arguments and defaults. The above example could be written as:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --foo() {</span></span>
<span class="line"><span style="color:#F97583"> @return</span><span style="color:#E1E4E8"> var(--bar);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --baz(--outer-bar: var(--bar)) {</span></span>
<span class="line"><span style="color:#E1E4E8"> --bar: something;</span></span>
<span class="line"><span style="color:#6A737D"> /* will be `--a: something` */</span></span>
<span class="line"><span style="color:#E1E4E8"> --a: --foo();</span></span>
<span class="line"><span style="color:#6A737D"> /* We can still access outer `--bar` */</span></span>
<span class="line"><span style="color:#E1E4E8"> --b: var(--outer-bar);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>And here is a live, although not very practical, example:</p>
<p><a href="https://blog.kizu.dev/renaming-outer-variables-in-functions/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --double() {</span></span>
<span class="line"><span style="color:#E1E4E8"> result: calc(2 </span><span style="color:#85E89D">*</span><span style="color:#E1E4E8"> var(--x));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --plus-one-and-double(--outer-x: var(--x)) {</span></span>
<span class="line"><span style="color:#E1E4E8"> --x: calc(var(--outer-x) </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> 1);</span></span>
<span class="line"><span style="color:#E1E4E8"> result: --double();</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"</span></span>
<span class="line"><span style="color:#9ECBFF"> --x: 2;</span></span>
<span class="line"><span style="color:#9ECBFF"> --preview: --double();</span></span>
<span class="line"><span style="color:#9ECBFF">"</span><span style="color:#E1E4E8">>2 * x = </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"</span></span>
<span class="line"><span style="color:#9ECBFF"> --x: 2;</span></span>
<span class="line"><span style="color:#9ECBFF"> --preview: --plus-one-and-double();</span></span>
<span class="line"><span style="color:#9ECBFF">"</span><span style="color:#E1E4E8">>2 * (x + 1) = </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>The problem we are solving: if we have some function like <code>--double()</code>, which does not use arguments, and is just accessing the variables from its outer scope, can we use it inside another function with a different <code>--x</code> without overriding it in that outer scope?</p>
<p>The solution: use an argument, and assign its default value using that variable. This way, the function will get that variable’s value and assign it to a different variable:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@function</span><span style="color:#E1E4E8"> --plus-one-and-double(--outer-x: var(--x)) {…}</span></span></code></pre>
<p>Now, inside that function’s body, we’re free to redefine that variable, with the original value staying accessible with the old value in our argument!</p>
<p>This allows us to redefine this variable, call our function in question, all without touching and modifying the outermost scope.</p>
<p>Neat. I don’t know if this will ever be useful, but hey!</p>
<hr>
<p>This is the second post from the series that I started with <a href="/functional-capturing/">“Functional Capturing”</a> about some of my initial experiments with custom functions. It was in my drafts for a long time, but because the feature is relatively useless, I did not end up finishing it.</p>
<p>Until now — all because with the ongoing work on <code>inherit()</code>, there was <a href="https://github.com/w3c/csswg-drafts/issues/12987">an issue</a> opened by <a href="https://github.com/andruud">Anders Hartvoll Ruud</a>, in which I managed to use this feature in an argument. Fun!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115493593122052461">on Mastodon</a>!</p>Zombie Styleshttps://blog.kizu.dev/zombie-styles/https://blog.kizu.dev/zombie-styles/Zombie Styles (noun): Dormant styles that break the UI after a configuration change.Wed, 05 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Burn It Down</dd><dt>Current drink:</dt><dd>Ceylon tea</dd></dl><hr /><style>{`
h1 {
font-size: 3.125rem;
}
`}</style>
<p>This is a short post about one thing I encounter a lot, but never saw explicitly defined for easy reference. This is my attempt:</p>
<dl style="display: block; font-size: 1em;">
<dt>Zombie Styles <em>(noun)</em></dt>
<dd>Dormant styles that break the UI after a configuration change.</dd>
</dl>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="what-do-zombie-styles-mean">What do <em>Zombie Styles</em> mean?</h2>
<p><em>Zombie Styles</em> refer to CSS styles that exist in the document’s stylesheet, but are <em>dead</em>, usually due to being overridden by other declarations. In their dormant form, they do not impact anything in the UI, and do not activate under normal circumstances.</p>
<p>However, some confuguration change can bring them to life unintentionally, and now that they’re applying, they affect the UI and wreak havoc.</p>
<h2 id="examples-of-zombie-styles">Examples of <em>Zombie Styles</em></h2>
<h3 id="forgotten-styles">Forgotten Styles</h3>
<p>The most common case of this happens when the same styles exist in multiple files, or in the same file but separated by other rules or declarations.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.Foo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D"> /* 100 very useful design-tokens */</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">lightgreen</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Or</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.Foo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">/* Many rules after, or maybe even in another file */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.Foo</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">lightgreen</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>When you look at a long stylesheet and only see a portion of styles, you might think “Maybe, I want the background of this <code>Foo</code> component to be transparent” and you then remove the <code>background: lightgreen</code> declaration. But somewhere there was a declaration hidden: it never applied before, but now it jumps and makes you spend another few minutes debugging your code.</p>
<p>The first case is easy to catch if you use <a href="https://stylelint.io/">Stylelint</a> via a <a href="https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-properties/"><code>declaration-block-no-duplicate-properties</code> rule</a>, but more complex cases can be harder to spot.</p>
<p>Generally, it is a good idea to never repeat selectors, separating styles that are applied together in the code.</p>
<h3 id="import-order-change">Import Order Change</h3>
<p>In SPAs (Shitty-Produced Applications) that load chunks of CSS based on the
Let’s say we have this HTML:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">section</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ComponentA"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ComponentB"</span><span style="color:#E1E4E8">>I am alive</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">section</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>And these two that components have the following styles:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.ComponentA</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> *</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.ComponentB</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">lightgreen</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Both of these styles have the same specificity, and a page can be built with the expectation that the <code>ComponentA</code> will always be imported before the <code>ComponentB</code>. The <code>background: pink</code> never applies.</p>
<p>Then, suddenly, somewhere in the app, <code>ComponentB</code> is included <em>before</em> the <code>ComponentA</code>, and now the styles’ order changes.</p>
<p>The declaration that was previously “dormant” activates. Oops. It might be the time to rethink your whole CSS architecture.</p>
<h2 id="were-you-also-bitten">Were You Also Bitten?</h2>
<p>Confess. Do you have bite marks from zombie styles? It is safe to confide in this: unlike normal zombies, zombie styles, usually, don’t convert you into CSS declarations.</p>
<p>Usually.</p>
<p>Please let me know which examples of zombie styles you have encountered. How did you fight them? Or did you just run away?</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115499498260229334">on Mastodon</a>!</p>Fixing Baselineshttps://blog.kizu.dev/fixing-baselines/https://blog.kizu.dev/fixing-baselines/Do you know how to center things in CSS? In year 2025? Easy! You just… align… or justify…, ok, maybe just place? your content… or items? …Forget it, this post is not about alignment. Or is it? This post is about another common alignment concept that might seem simple: baseline alignment. In it, I share a technique I have already used for twelve years.Fri, 07 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>夢中夢 — Unforgiven</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>Do you know how to center things in CSS? In year 2025? Easy! You just… align… or justify…, ok, maybe just place? your content… or items? …Forget it, this post is not about alignment. Or is it?</p>
<p>This post is about another common alignment concept that might seem simple: baseline alignment. In it, I share a technique I have already used for twelve years.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-definition">The Definition</h2>
<p>To quote from <a href="https://drafts.csswg.org/css-inline/#css-metrics">the specs</a>,</p>
<blockquote>
<p>A <dfn>baseline</dfn> is a line along the inline axis of a line box along which individual glyphs of text are aligned.</p>
</blockquote>
<figure>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 176.1 48.4" fill="currentColor">
<text transform="translate(0 31.091)"><tspan x="0" y="0" font-family="Arial, Helvetica" font-size="17">Apple</tspan><tspan x="46" y="0" font-family="Arial, Helvetica" font-size="35"> Orange</tspan></text>
<path fill="none" stroke="#3fa9f5" stroke-miterlimit="10" d="M0 31.7h175"></path>
<g fill="none" stroke="#2e3192" stroke-miterlimit="10">
<path d="M44.8 16.7v-1h-1"></path>
<path stroke-dasharray="2 2" d="M42 15.7H3"></path>
<path d="M1.5 15.7h-1v1"></path>
<path stroke-dasharray="2 2" d="M.5 19.2v15"></path>
<path d="M.5 34.7v1h1"></path>
<path stroke-dasharray="2 2" d="M4 35.7h39"></path>
<path d="M43.8 35.7h1v-1"></path>
<path stroke-dasharray="2 2" d="M44.5 33.2v-15"></path>
</g>
<g fill="none" stroke="#2e3192" stroke-miterlimit="10">
<path d="M175 1.5v-1h-1"></path>
<path stroke-dasharray="2 2" d="M172 .7H59"></path>
<path d="M58.2.5h-1v1"></path>
<path stroke-dasharray="2 2" d="M57.5 3.2v36"></path>
<path d="M57.2 40.7v1h1"></path>
<path stroke-dasharray="2 2" d="M60 41.7h113"></path>
<path d="M174 41.7h1v-1"></path>
<path stroke-dasharray="2 2" d="M174.5 38.2v-36"></path>
</g>
</svg>
<figcaption>Figure from the spec: Alphabetic text in two font sizes with the baseline and em-boxes</figcaption>
</figure>
<p>The specs go into many details, and if you will start reading them (or if you have enough practice), you’ll get that it <span style="display: inline-block; overflow: hidden">is</span> not <span style="display: inline-flex; place-items: center;"><span style="font-size: 2em;line-height: 0.5;">⭐️</span>simple</span>.</p>
<h2 id="the-problems--solutions">The Problems & Solutions</h2>
<p>If you pay a close attention to the previous sentence, you might get the idea.</p>
<h3 id="overflowing-inline-elements">Overflowing Inline Elements</h3>
<p>This is the simplest problem, which, today, has a simple solution. The problem: if you have an element with <code>inline-block</code>, giving it <code>overflow: hidden</code> (or <code>auto</code>, <code>scroll</code>, etc.) will break the baseline:</p>
<style>{`
figure > p::before {
content: "";
display: inline-block;
height: 1px;
background: deeppink;
width: 100cqw;
margin-left: -0.215em;
margin-right: -100cqw;
opacity: 0.75;
position: relative;
z-index: 1;
}
`}</style>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Hello, <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"block-world"</span><span style="color:#E1E4E8">>world</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>!</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.block-world</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The solution: use <code>inline-flex</code> or <code>inline-grid</code> instead. They will retain the baseline!</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Hello, <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"flex-world"</span><span style="color:#E1E4E8">>world</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>!</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.flex-world</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>More than eleven years ago — almost twelve — I wrote a dedicated article about this topic: <a href="https://kizu.dev/flex-baseline/">“Battle for Baseline”</a>. If you want to read about all the crossbrowser issues I had to dig through to make this work at that time, I invite you to read it.</p>
<p>But today, now that <code>inline-flex</code> and <code>inline-grid</code> are <a href="https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility"><em>baseline</em></a> (sorry), we no longer have the same bugs and issues. Hooray.</p>
<h3 id="icons-before-text">Icons Before Text</h3>
<p>The second problem can be much more pronounced today, and does <em>not</em> have a solution built into the specs (or — I don’t know about it).</p>
<p>It is what happens when you have some inline element, for example, a button, and then inside of it, but before its text, you add some icon. And then, you want to center everything vertically inside, but, at the same time, align this button’s content with the baseline of the nearby text. It doesn’t work:</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello,</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button-world"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> world</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">>!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.button-world</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> place-items</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">9</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> font</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> font-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>If the <code>font-size</code> of the icon that contains an emoji was the same as of the text, it would look ok. But if we modify this element’s font-size, or use an empty element or a replaced element instead, then <em>this element</em> will be used for determining the baseline of our button.</p>
<p>This is because, by default, the button uses the <em>first</em> “baseline set” for aligning that <code>inline-flex</code> element, and that first baseline will come from our icon!</p>
<h3 id="baseline-source"><code>baseline-source</code></h3>
<p>If we dig a bit into the specs, we could find a partial solution for our problem: the very obscure <a href="https://drafts.csswg.org/css-inline/#propdef-baseline-source"><code>baseline-source</code></a> property.</p>
<p>Why is it obscure?</p>
<p>First, it is not <a href="https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility"><em>baseline</em></a> (I am so sorry again), and is <a href="https://caniuse.com/wf-baseline-source">only supported</a> in Firefox and Chrome, with support missing from Safari. It is not even present on MDN.</p>
<p>Then, if we were to use it in browsers that <em>do</em> support it to address our problem, it will help for a simple case:</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello,</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button-world with-baseline-source"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> world</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">>!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.with-baseline-source</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> baseline-source</span><span style="color:#E1E4E8">: last;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>But — the only value other than <code>auto</code> and <code>first</code> is <code>last</code>. And, guess what will happen if we would also add an icon to the end of our button:</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello,</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button-world with-baseline-source"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> world</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🙀</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">>!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>And, the second problem will happen if we were to have a multiline button — and would want, for some reason, to still use the default behavior of aligning it via its <em>first</em> line:</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello,</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button-world with-baseline-source"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> wrapped<</span><span style="color:#85E89D">br</span><span style="color:#E1E4E8">/>world</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">>!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>It is not just the <em>last element</em> that defines the baseline now — it is the <em>last line box</em> of the last element. Oops.</p>
<aside>
Fun fact: before starting to write this article, I did not know about the `baseline-source` property! Now I know — and you know too. I hope Safari will pick this property up, and we will have it… everywhere.
<p>Even though it doesn’t resolve our problem, I can see how it can be useful in some other niche cases.</p>
</aside>
<h3 id="anextra-element-solution">An Extra Element Solution</h3>
<p>So, how can we solve this problem today, and more reliably?</p>
<p>The solution that I used for years, but I don’t think I ever shared (or saw mentioned elsewhere — if someone did write about it, please let me know!) — to just use an extra element <em>before</em> the element that otherwise breaks our baseline. That extra element should have the same font metrics as the real content, and we need to make this element to not contribute any space, but otherwise this works pretty well:</p>
<p><a href="https://blog.kizu.dev/fixing-baselines/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Hello,</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button-world with-extra-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> world</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">>!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.with-extra-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--gap</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.with-extra-element::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">'</span><span style="color:#79B8FF">\a0</span><span style="color:#9ECBFF">'</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* &nbsp; */</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> visibility</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">-1</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--gap</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>A few things to note:</p>
<ul>
<li>Because our element uses a <code>gap</code>, we have to <em>remove</em> the extra gap that will appear when we insert the pseudo-element.</li>
<li>I am using a <code>'\a0'</code> — a no-break space. I found it to work the best. Extra tip: whenever you use escaped characters in your CSS, add comments that communicate what they are.</li>
<li>For it to not impact anything other than the baseline, we give it <code>width: 0</code> and hide it via <code>visibility</code>.</li>
<li>Of course, if you don’t have a gap, you can skip the margin stuff.</li>
</ul>
<p>And that’s it!</p>
<h4 id="prior-art">Prior Art</h4>
<p>While I am using this technique for <a href="https://github.com/stylobate/stylobate/commit/9686fba68ec125fb472b9f54f7964c5d43081f52#diff-1ecb88dbb1890d2ca80274dc15f41eb5de8aefae213e8e50733cf44bb993287a">almost twelve years already</a>, I used <a href="https://marginalia-search.com/">Marginalia search</a> to look up if anyone else mentioned it elsewhere.</p>
<p>I might’ve missed something, but the closest thing I found is <a href="https://dimiterpetrov.com/blog/svg-icon-sizing-and-alignment/">“SVG icon sizing and alignment”</a> article by <a href="https://dimiterpetrov.com/">Dimiter Petrov</a>.</p>
<h2 id="could-there-beabetterway">Could There Be a Better Way?</h2>
<p>Currently, we can only control which baseline set is used for our element <em>on the wrapper</em> element.</p>
<p>But what if we could have something like <code>baseline-presence: exclude</code> that could be used on our inner elements, so we could add it to our icons, and then they won’t participate in the definition of our baseline?</p>
<p>Right after published this post, I opened <a href="https://github.com/w3c/csswg-drafts/issues/13080">an issue about this in CSSWG</a>, as I did not find any others that would cover this. I work on design systems for a very long time, and this problem appears over and over in all of them.</p>
<p>And — if you know of a different solution — please let me know, or — even better — write your own post about it and share it!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115510510399674122">on Mastodon</a>!</p>Photo Walk, End of Marchhttps://blog.kizu.dev/walk-end-of-march-2025/https://blog.kizu.dev/walk-end-of-march-2025/I am a bit out of it — did not sleep for quite a while, but not managing to fall asleep properly now. Staying in Europe and not going to this year’s TPAC, I am trying to shift my waking hours to match Japan. Not very successfully so far. Well, time to repost some older photos from Pixelfed!Sun, 09 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Tom Figgins — Clouds Do Part</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>I am a bit out of it — did not sleep for quite a while, but not managing to fall asleep properly now. Staying in Europe and not going to this year’s <a href="https://www.w3.org/2025/11/TPAC/">TPAC</a>, I am trying to shift my waking hours to match Japan. Not very successfully so far.</p>
<p>Well, time to repost some older photos from Pixelfed!</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“Magnolia, blooming.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>This was at the end of this March, when trees started to get their leaves, and blooming with flowers.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“The opposite of trees losing the leaves.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Weather was pretty nice that day: sunny, with some clouds. There were a bunch of people in the parks.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“People walking in the parks.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>I went a long way, intending to get a tram back. Passed between the viaduct with the tram line on top, and noticed some houses nested under it.</p>
<p><img src="pixelfed:818047444271492157" alt=""></p>
<p>Went pretty randomly, through some parks I never visited before.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“A lot of activity in the park.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Ended up going onto some hill with a dead end, but managed to find a private (but open) path between properties.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“A hidden path between private properties.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>I did not manage to make many good photos: I was still getting used to the wider lens, and unlike when I was in the forest, it was a bit harder to get good shots.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“Someone’s yard.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Funnily enough, the tram did not work that day, and some of the closest bus stops were closed because of some construction. Well.</p>
<p><a href="https://blog.kizu.dev/walk-end-of-march-2025/">“A tunnel.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>In the end, I just walked all the back home, and tested a nice hill climb with a staircase.</p>
<p><img src="pixelfed:818936118950300362" alt=""></p>
<p>That’s it. I’ll now go drink some tea, eat some food, and try to go sleep for a while.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115520491836319448">on Mastodon</a>!</p>Embedding Bandcamp Trackshttps://blog.kizu.dev/embedding-bandcamp-tracks/https://blog.kizu.dev/embedding-bandcamp-tracks/A long time ago, back in LiveJournal, sometimes people embedded various music players in their posts. It was fun! I already had a “Current music” field added to most of my posts, but now I also added a way to enrich this field by adding an optional Bandcamp track reference, and spent my evening updating existing posts in the blog to have it.Sat, 08 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — An Interview</dd><dt>Current drink:</dt><dd>Ceylon tea</dd></dl><hr /><p>A long time ago, back in LiveJournal, sometimes people embedded various music players in their posts. It was fun! You could read the posts of your online friends, and sometimes listen to random music they shared with everyone.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="what-i-did">What I Did</h2>
<p>I already had a <a href="/current-music/">“Current music”</a> field added to most of my posts, replicating one small bit from the LiveJournal experience, but now I also added a way to enrich this field by adding an optional Bandcamp track reference, and spent my evening updating existing posts in the blog to have it.</p>
<p><a href="https://get.bandcamp.help/hc/en-us/articles/23020711574423-How-do-I-create-a-Bandcamp-embedded-player">Bandcamp embeds</a> are just a <code><iframe></code>s, so by placing one inside an HTML <code><details></code> tag and adding the <code>loading="lazy"</code> to the <code><iframe></code> we can make it so the <code><iframe></code>’s code won’t be loaded before the details are open.</p>
<p>I didn’t use any APIs to retrieve the ID to embed, so I had to add the necessary metadata to this and other posts manually.</p>
<p>In total, unless I miscounted, I added Bandcamp links to a bit less than 70% of my ~78 posts with the “Current Music” field. Which is fun! Nice to see that many artists I listen to on Bandcamp. It went <em>almost</em> to the point where I could start thinking about the automation, but <a href="https://indieweb.org/manual_until_it_hurts">it did not hurt</a>, and whenever I added a track to another post, I always tested it out and nodded at my past choices.</p>
<h2 id="example">Example</h2>
<p>You can go to the top of this post, click on the track name that is prefixed by the disclosure triangle, and see what happens. Maybe even listen to that track that is there!</p>
<p>Or — here is another example, from <a href="/toc-scroll-markers/">another post</a>:</p>
<figure>
<div>Haru Nemuri — [Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/embedding-bandcamp-tracks/)</div>
<figcaption>Example of a minimal embed inside the details tag.</figcaption>
</figure>
<p>And, while I am not using this anywhere yet, I made it so it is possible to configure the same embed inside to expand in the bigger version that Bandcamp provides, this is yet <a href="/recent-css-bookmarks-017/">from another post</a>:</p>
<figure>
<div>This is The Kit — [Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/embedding-bandcamp-tracks/)</div>
<figcaption>Example of an embed with an album cover inside.</figcaption>
</figure>
<p>I remember in LiveJournal I sometimes posted custom embeds like that but the photos that I took instead of the album cover, trying to match the mood. Maybe I’ll implement something like that one day here as well.</p>
<h2 id="implementation">Implementation?</h2>
<p>I <a href="/november-again/#the-plan">kinda promised</a> not to talk a lot about frontend or CSS on weekends, even though I found there might be a lot to share while writing this post and implementing the embedded Bandcamp player. However, I’ll try to stick to my plan, and stop before going into more details.</p>
<p>I noted down a few things I’d want to share regardless, so, maybe, one day!</p>
<h2 id="potential-issues">Potential Issues</h2>
<h3 id="possible-future-bias">Possible Future Bias</h3>
<p>What I have now presents a slight problem: if some artist or a specific track is not present on the Bandcamp, I cannot currently link to it in any way. Having a “richer” experience for Bandcamp might make me choose artists who are present there more when adding them to my posts.</p>
<p>Some artists might be present on platforms I don’t want to link that much, like YouTube, but maybe it’s ok? Some of them might not be present anywhere outside the streaming platforms, which might make things even worse.</p>
<p>I need to contemplate what to do: should I add alternative types of metadata and presentation for other services? Just link to artists’ pages when possible? Hm hm.</p>
<h3 id="future-linkembed-rot">Future Link/Embed Rot</h3>
<p>Another thing that could happen because I am not self-hosting the Current Music (duh) — if the tracks will disappear from Bandcamp, the embeds will stop working. Which is not the end of the world, but I currently don’t have any tools to detect that.</p>
<h2 id="thats-it-for-now">That’s It, For Now</h2>
<p>Yep. What I like about having my own website — I can do whatever I want with it. Even the more independent and federated networks became very limited in what they allow. While I was not on it, I looked with interest at <a href="https://en.wikipedia.org/wiki/Cohost">Cohost</a> with all the <a href="https://css-tricks.com/the-lost-css-tricks-of-cohost-org/">CSS Crimes</a> you could do there (post by <a href="https://www.blackle-mori.com/">Blackle Mori</a> — author of many such contraptions).</p>
<p>The older, asocial, pseudonymous networks were much more relaxed in what you could post and do with your personal spaces. Custom themes, embeds, quizes, custom avatars per post, inline CSS.</p>
<p>I understand how in modern web there are now many concerns over privacy and security which close some of the past doors, but I hope that with newer CSS features like <code>@scope</code> we could maybe unlock some of them, and allow the chaotic creativity to invade our niche spaces.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115516133711218290">on Mastodon</a>!</p>Uneven Inline Paddingshttps://blog.kizu.dev/uneven-inline-paddings/https://blog.kizu.dev/uneven-inline-paddings/Today, I want to share one tiny design tweak you can do to your content styles. I have used it in my blog’s design for a while, and recently decided to improve it a bit, and will take this as an opportunity to share it.Mon, 10 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>COVET — Ares</dd><dt>Current drink:</dt><dd>Green tea with bergamot, kiwi, yellow peach, orange blossom and violet flower</dd></dl><hr /><p>Today, I want to share one tiny design tweak you can do to your content styles. I have used it in my blog’s design for a while, and recently decided to improve it a bit, and will take this as an opportunity to share it.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-ragged-edge">The Ragged Edge</h2>
<p>No, this is not about Babylon <span class="normal">5</span>’s 100<sup class="alt">th</sup> episode that had “The Ragged Edge” as its title, in which <q>Garibaldi’s relapse into alcoholism jeopardises a covert mission to the Drazi homeworld</q> (quoting Wikipedia’s <a href="https://en.wikipedia.org/wiki/List_of_Babylon_5_episodes#ep100">episode summary</a> that I found when doing some research; good show, <abbr>BTW</abbr>).</p>
<p>I will be talking about the left-aligned text, also known as “flush left” or “ragged right”. Actually, this could also work for right-aligned text — the main idea is that we need to have the rag, and not have the text justified.</p>
<p>The problem with the ragged edge — if the padding on both sides of your column of content is even, it will get perceived as uneven.</p>
<style>{`
.container {
position: relative;
isolation: isolate;
overflow: hidden;
resize: horizontal;
max-width: calc(100cqi + 2 * var(--padding));
box-sizing: border-box;
margin: calc(-1 * var(--padding));
margin-bottom: 0;
border-radius: var(--border-radius) var(--border-radius) 0 0;
box-shadow:
1px 0 color-mix(in oklch, var(--BLUE), transparent),
1px 0 var(--CONTENT-BG)
;
&:has(+ fieldset > label.with-background > input:checked) {
background: var(--GREEN);
}
&:has(+ fieldset > label.with-fix > input:not(:checked)) {
padding: 32px;
}
&:has(+ fieldset > label.with-edge > input:checked) {
&::before {
content: '';
position: absolute;
border-left: 1px solid var(--RED);
inset-block: 0;
inset-inline: auto 31px;
z-index: -1;
}
}
& p {
overflow: hidden;
margin: 0;
text-wrap: inherit;
& > span {
padding: 0.25em 0;
background: var(--CONTENT-BG);
}
}
}
`}</style>
<p><a href="https://blog.kizu.dev/uneven-inline-paddings/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.container</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">32</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"container"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>This is a paragraph of text that will wrap, and will create a ragged edge because it is not justified, which can result in the perceived uneveness of the paddings on both sides of it. If this doesn’t happen, then maybe the width of its lines matches very precisely the width of the container.</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>If you can resize your window or this example, you might have a better chance to be able to spot the difference.</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"controls"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Tweak this example</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-background"</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#B392F0"> checked</span><span style="color:#E1E4E8"> /> <</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">>with green background</</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-edge"</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#E1E4E8"> /> <</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">>highlight the padding edge</</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Very rarely any of the words in the text will get flush with its right edge: usually, they will wrap before reaching it, and thus will always leave some extra space.</p>
<p>In the above example, by default, all the padding around the paragraph is shown with a green background, excluding the background under the actual text content. This makes it easy to spot the unevenness: removing the background “hides” this, but only to an extent.</p>
<h2 id="the-solution">The Solution</h2>
<p>The solution for this is to apply a smaller padding to the ragged edge:</p>
<p><a href="https://blog.kizu.dev/uneven-inline-paddings/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.uneven-padding</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-end</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">16</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"container uneven-padding"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>This is a paragraph of text that will wrap, and will create a ragged edge because it is not justified, which can result in the perceived uneveness of the paddings on both sides of it. If this doesn’t happen, then maybe the width of its lines matches very precisely the width of the container.</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>If you can resize your window or this example, you might have a better chance to be able to spot the difference.</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"controls"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Tweak this example</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-background"</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#B392F0"> checked</span><span style="color:#E1E4E8"> /> <</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">>with green background</</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-edge"</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#E1E4E8"> /> <</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">>highlight previous padding edge</</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-fix"</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#B392F0"> checked</span><span style="color:#E1E4E8"> /> <</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">>with uneven padding fix</</span><span style="color:#85E89D">u</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>This might not look that impactful on a minimal example, but the more text you have, the bigger the change. This can be even more important for narrow contexts: on my blog I initially only applied this in the desktop version, but on smaller screens the padding ended up being equal.</p>
<h2 id="downsides">Downsides</h2>
<p>Should you go and change all your paddings? Probably not. Especially, given there might be potential issues with this solution:</p>
<ol>
<li>
<p>You could think that the bigger the padding, the bigger chunk of it we could remove. To an extent, this is true, but it can be very easy to shift the unevenness in the other direction. This is something that should be done “by an eye”, although as a rule of thumb a good starting point could be to apply a half of the original padding.</p>
</li>
<li>
<p>Often, people include things other than the text in their content. Images, code blocks, etc. If those have backgrounds or borders on their own, an uneven padding around those elements <em>will</em> look uneven. This is where you’d want to either add an extra margin to those elements to compensate, or invert things and keep the original even padding intact and only add a negative margin on the children that might need it like paragraphs, list items, and so on.</p>
</li>
<li>
<p>After addressing the problem with the full-width elements above, and if the padding is pretty large, then cutting it in half can lead to the unevenness being pretty obvious. These pronounced blocky elements will visually reinforce the “expected” edge, making the “hanging” text in the rag stick out.</p>
</li>
<li>
<p>If your text has <code>text-wrap: balance</code> or <code>pretty</code>, the effect of the fix will often be smaller because then all the lines will wrap sooner, so the chances of the text not going until the edge will be higher, and a small padding tweak won’t help. And if the width of the container will be equal to the longest wrapping lines, it is likely things could feel unbalanced, similar to if we had <code>text-align: justify</code>.</p>
</li>
</ol>
<aside>
For example, you can <label><input class="no-article-fix" type="checkbox"> <u>disable the fix for this whole post</u></label>,<br> or <label><input class="article-edge-highlight" type="checkbox"> <u>highlight the unfixed padding edge</u></label>!
<p>You will then see that I added a pretty small overhang for the content, especially compared to the padding itself on the wider screens.</p>
<style>{`
article:has(> aside > p > label > input.no-article-fix:checked) {
--ragged-margin-fix-override: 0;
}
article:has(> aside > p > label > input.article-edge-highlight:checked)::before {
background-image: linear-gradient(var(--RED));
background-size: 1px 100%;
background-repeat: no-repeat;
background-position: right calc(var(--content-padding) - 1px) top 0;
}
`}</style>
</aside>
<h2 id="closing-thoughts">Closing Thoughts</h2>
<p>I hope you found this short post interesting. I consider myself bad at design, but many people tell me that they like how my main website and this blog look. Blame all the years that I iterated on them!</p>
<p>Over these years, gradually, I implemented more and more ideas, small and big, regarding their design and typography. Did you spot some already? Or are they subtle enough that you’re now wondering what exactly do I mean? <del>Let me know in the comments down below.</del></p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115525890517691862">on Mastodon</a>!</p>Named Container Presence Checkhttps://blog.kizu.dev/named-container-presence-check/https://blog.kizu.dev/named-container-presence-check/I was doing some styling recently, and I wanted to know if my element was inside a certain container. While I could reuse the same selector that I used to apply the container with, this did not feel right: what if I were to apply the same container via a different selector? Or have a version of that element where the container is removed via some modifier? Can we somehow use just the container’s name for this?Tue, 11 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haisuinonasa — Shower</dd><dt>Current drink:</dt><dd>Cappuccino</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-task">The Task</h2>
<p>I was doing some <em>styling</em> recently, and I wanted to know if my element was inside a certain container.</p>
<div class="aside-wrapper" style="--span: 6; --position: static;">
<aside>
If you're new to _containers_, you can familiarize yourself with them via one of these resources:
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span> - [“An Interactive Guide to CSS Container Queries”](https://ishadeed.com/article/css-container-query-guide/) by [Ahmad Shadeed](https://ishadeed.com/).</span></span>
<span class="line"><span></span></span>
<span class="line"><span> - [“Container Queries Unleashed”](https://www.joshwcomeau.com/css/container-queries-unleashed/) by [Josh W. Comeau](https://www.joshwcomeau.com/).</span></span>
<span class="line"><span></span></span>
<span class="line"><span> - [“CSS Containers, What Do They Know?”](https://www.youtube.com/watch?v=-Fw8GSksUIo) — a talk by [Miriam Suzanne](https://www.miriamsuzanne.com/).</span></span>
<span class="line"><span></aside></span></span></code></pre>
</aside></div>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.my-container</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-container"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"some-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Where am I?</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"some-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> And me, what about me?</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>While I could reuse the same selector that I used to apply the container with, this did not feel right: what if I were to apply the same container via a different selector? Or have a version of that element where the container is removed via some modifier?</p>
<p>Given I already had <code>container-type: inline-size</code>, and I literally wanted to know if this exact containment from this exact element was applied, as a way to differentiate between it and the viewport, using a named container to check this was pretty obvious.</p>
<h2 id="checking-named-containers">Checking Named Containers</h2>
<p>Generally, named containers — ones with the <code>container-name</code> property — are used for differentiating between them. What if you have multiple containers around an element, and you need to check the dimensions on a specific container? Is this a query for a <em>card</em>, or for <em>content</em>?</p>
<p>Usually, you’d use these containers to query either elements’ dimensions, or, with style container queries, values of custom properties on them.</p>
<p>For my purpose, I don’t care about any specific values: I only need to know about the <em>presence</em> of some named container. For different types of them, we can do this differently.</p>
<h3 id="querying-a-size-container">Querying a Size Container</h3>
<p>For size containers things are pretty simple: if we have an established size container, we can add a <code>container-name</code> to it (or join the name with its type into a <code>container</code> shorthand), and then query it in an always-positive way alongside its name:</p>
<p><a href="https://blog.kizu.dev/named-container-presence-check/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.my-container</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> container</span><span style="color:#E1E4E8">: --my-container / inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@container</span><span style="color:#E1E4E8"> --my-container (min-width: 0) {</span></span>
<span class="line"><span style="color:#B392F0"> .some-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">3</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-container"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"some-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Where am I?</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"some-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> And me, what about me?</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Some notes:</p>
<ul>
<li>
<p>I am setting the name for our container using the shorthand. I am also using a dashed ident for it, even though containers allow any custom idents. I wrote a post about why I am doing this two years ago: <a href="/dashed-idents-for-everything/">“Dashed Idents for Everything”</a>.</p>
</li>
<li>
<p>A container cannot have a <em>negative</em> width, so a <code>min-width: 0</code> check will always match, but only if there is a <code>--my-container</code> somewhere in the tree around our <code>some-element</code>.</p>
</li>
<li>
<p>This will work only if we apply any <code>container-type</code> on our container: both <code>size</code> and <code>inline-size</code> will work for <code>min-width</code>, and if we’d want to check if our container is specifically <code>size</code> container, we’d need to check <code>min-height: 0</code>.</p>
</li>
</ul>
<h3 id="style-querying-any-container">Style Querying any Container</h3>
<p>Container style queries are <em>almost here</em>: Firefox should get them pretty soon. For querying <em>styles</em> of custom properties, we don’t need to have any containment, thus with container style queries we will be able to just name any element, and then query if we have this specific container somewhere in our element’s ancestors.</p>
<aside class="warning">
At the time of writing this, the style queries implementation in Firefox Nightly has [a bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1999555), where it considers this _always_ true without looking at the name of the container.
</aside>
<p><a href="https://blog.kizu.dev/named-container-presence-check/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.my-styletainer</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> container-name</span><span style="color:#E1E4E8">: --my-styletainer;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F97583">@container</span><span style="color:#E1E4E8"> --my-styletainer not (</span></span>
<span class="line"><span style="color:#E1E4E8"> style(--a:a) and style(--a:b)</span></span>
<span class="line"><span style="color:#E1E4E8">) {</span></span>
<span class="line"><span style="color:#B392F0"> .my-element</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">3</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--BLUE</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-styletainer"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Where am I?</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"my-element"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> And me, what about me?</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>In order to match a style container regardless of what its styles are, we can use a <code>not (style(--a:a) and style(--a:b))</code> condition: it will be always truthy, as it is not possible to have some custom property that has two different values at the same time.</p>
<h4 id="why-not-regular-style-queries">Why Not Regular Style Queries?</h4>
<p>One could ask a question: couldn’t we just use style queries and then check some custom property like <code>--container-name: --my-styletainer</code> instead?</p>
<p>If we wanted to check if that container is the <em>closest</em> to our element — sure, that would be the way. However, what we want is to check if the container is <em>present at all</em>, without checking for its proximity.</p>
<h2 id="arent-those-hacky">Aren’t Those Hacky?</h2>
<p>While the size containment check is pretty simple, we still <em>have to establish the size containment</em>. As for style queries, the check is very verbose. We could try to simplify it as <code>not style(--\-)</code> — use a name that will unlikely be present in our document, but it won’t be <em>guaranteed</em>.</p>
<p>Currently, <code>@container --my-container {}</code> won’t ever do anything: the follow-up condition is required. But what if we could use this simple notation to check for the named container’s presence? It will be pretty straighforward and simple.</p>
<p>I opened <a href="https://github.com/w3c/csswg-drafts/issues/13093">a CSSWG issue about this</a>. If you have any use cases for this, write about them in this issue, otherwise, if you think it is a good idea — please, upvote it!</p>
<p>And — that’s it for today’s post! As it often goes: I thought it will be a simple one, but then ended up filling a Firefox bug and a CSSWG issue. Even more: this post was actually a side effect from starting to write another post, in which I used this “technique”, so I wanted to first briefly explain it in a separate post.</p>
<h2 id="update-from-2025-11-12">Update from 2025-11-12</h2>
<p>After I published this post, <a href="https://www.miriamsuzanne.com/">Miriam</a> noted that CSSWG already <a href="https://github.com/w3c/csswg-drafts/issues/9192#issuecomment-1789850349">resolved on this</a> 2 years ago, and <a href="https://social.vivaldi.net/@rune">Rune Lillesveen</a> <a href="https://github.com/web-platform-tests/wpt/pull/49093">contributed WPT tests</a> a year ago, which, as also tested by me, are still <a href="https://wpt.fyi/results/css/css-conditional/container-queries/query-container-name.html?label=experimental&label=master&aligned">not passing</a>.</p>
<p>I closed the issue I created as a duplicate. Now, I guess, the onus is on browsers: this feels like a <em>very</em> low-hanging fruit, as all necessary for verifying the presence of a container should be already done, this new feature is only <em>excluding</em> some of the checks browsers do when there is a query present.</p>
<h2 id="update-from-2025-12-13">Update from 2025-12-13</h2>
<p>And now there will be a first implementation of the name-only container queries, thanks to <a href="https://frehner.me/">Anthony Frehner</a> who submitted <a href="https://github.com/WebKit/WebKit/pull/54667">a patch to WebKit</a> that is now merged! Looking at the code there — it really seems like a pretty simple thing, so, I hope, this will be in other browsers too sooner rather than later.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115533026440139284">on Mastodon</a>!</p>Responsive tab-sizehttps://blog.kizu.dev/responsive-tab-size/https://blog.kizu.dev/responsive-tab-size/There exists a not well-known CSS property: `tab-size`. It sets the width, in spaces, of the tab indentation, usually found in code blocks of authors who use tabs instead of spaces (good job, authors). However, who says that this value should be static?Wed, 12 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>This is The Kit — Birchwood Beaker</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-tab-size">The <code>tab-size</code></h2>
<p>There exists a not well-known CSS property: <a href="https://drafts.csswg.org/css-text/#tab-size-property"><code>tab-size</code></a>. It sets the width, in spaces, of the tab indentation, usually found in code blocks of authors who use tabs instead of spaces (good job, authors).</p>
<p>One of the benefits of using tabs for indentation: it is possible to control how big the indentation will be. CSS is not exception, and that’s why <code>tab-size</code> property is very useful. Especially, given its default value is the enormous <code>8</code> spaces. It is very likely you’d want to override it for your code blocks:</p>
<p><a href="https://blog.kizu.dev/responsive-tab-size/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> One default tab here!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">pre</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"tab-size: 4"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> One overridden tab here!</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.example</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.example</span><span style="color:#E1E4E8">[</span><span style="color:#B392F0">class</span><span style="color:#E1E4E8">] </span><span style="color:#85E89D">pre</span><span style="color:#B392F0">:not</span><span style="color:#E1E4E8">(</span><span style="color:#B392F0">:has</span><span style="color:#E1E4E8">(</span><span style="color:#F97583">></span><span style="color:#85E89D"> code</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> & + &,</span></span>
<span class="line"><span style="color:#E1E4E8"> &:is(div + div > *) {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">rem</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.example2</span><span style="color:#B392F0"> .container</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> resize</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">horizontal</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span></code></pre>
<h2 id="responsiveness">Responsiveness</h2>
<p>However, who says that this value should be static?</p>
<p><a href="https://blog.kizu.dev/responsive-tab-size/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"container"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">pre</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dynamic-tab"</span><span style="color:#E1E4E8">> One tab here!</</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"container"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: 66%"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">pre</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dynamic-tab"</span><span style="color:#E1E4E8">> One tab here!</</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"container"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: 33%"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">pre</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"dynamic-tab"</span><span style="color:#E1E4E8">> One tab here!</</span><span style="color:#85E89D">pre</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.container</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> container-type</span><span style="color:#E1E4E8">: inline-size;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.dynamic-tab</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --available-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --step-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">10</span><span style="color:#F97583">ch</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> @</span><span style="color:#79B8FF">supports</span><span style="color:#79B8FF"> not</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">z-index</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1</span><span style="color:#F97583">px/</span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--available-width</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --captured-length2</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--step-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --ratio</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">tan</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">atan2</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--captured-length2</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ));</span></span>
<span class="line"><span style="color:#79B8FF"> tab-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">round</span><span style="color:#E1E4E8">(up, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--ratio</span><span style="color:#E1E4E8">), </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#F97583"> @supports</span><span style="color:#E1E4E8"> (</span><span style="color:#79B8FF">z-index</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">1</span><span style="color:#F97583">px/</span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">)) {</span></span>
<span class="line"><span style="color:#85E89D"> tab-size</span><span style="color:#E1E4E8">: round(</span></span>
<span class="line"><span style="color:#E1E4E8"> up,</span></span>
<span class="line"><span style="color:#E1E4E8"> var(--available-width) / var(--step-size),</span></span>
<span class="line"><span style="color:#E1E4E8"> 2</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Ok, that CSS looks scary! If all browsers supported <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/calc#css_typed_arithmetic">typed arithmetic</a> — an ability to divide two values of the same type to get the unitless ratio between them — we could simplify it to just this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.dynamic-tab</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> tab-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">round</span><span style="color:#E1E4E8">(up, </span><span style="color:#79B8FF">100</span><span style="color:#F97583">cqi</span><span style="color:#E1E4E8"> / </span><span style="color:#79B8FF">10</span><span style="color:#F97583">ch</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">2</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now, that’s much more readable, right? We divide the available space by some length to get the number of times it fits in it, and then round it up to be even.</p>
<p>This makes the <code>tab-size</code> start from being two spaces wide, and increase with the available space. If needed, a <code>min()</code> could be added if we’d wanted to limit how high it could grow.</p>
<p>But — typed arithmetic is <em>not</em> currently available in all browsers. That said, we can work around this.</p>
<p>I am using the <a href="https://dev.to/janeori/css-type-casting-to-numeric-tanatan2-scalars-582j"><code>tan(atan2())</code> hack</a> by <a href="https://propjockey.io/">Jane Ori</a> alongside <a href="/captured-custom-properties/">“Captured Custom Properties”</a> to capture some values that compute to <code>px</code> and then get the ratio between them via <code>tan(atan2())</code>.</p>
<p>I am also using <code>@supports</code> for the browsers to see only what they need to based on the typed arithmetic support. If we were not abstracting the values into custom properties, we could rely on fallbacks, but when custom properties are present we can’t use them.</p>
<h2 id="thats-it">That’s It</h2>
<p>I first experimented with this <a href="https://codepen.io/kizu/details/QWYgbMZ">almost exactly 2 years ago</a>, and earlier this year <a href="https://front-end.social/@kizu/114587260534234618">shared</a> an updated version of this technique on Mastodon.</p>
<p>This time, I finally wrote a proper blog post about it, and at the same time slightly updated it to use the typed arithmetic alongside the <code>@supports</code> rule.</p>
<p>I also updated my blog’s CSS to use this, although here it only switches between values of <code>2</code> and <code>4</code> spaces, and maybe a bit overcomplicated due to some of my blog’s implementation details — I even used the <a href="/named-container-presence-check/">“Named Container Presence Check”</a> that I described in the previous post.</p>
<p>It is fun finding places where the typed arithmetic could help with responsiveness: any place you see an integer or a unitless number could be an opportunity to try it. How can we connect our container’s size with it? Maybe use for color components? <code>z-index</code>? Number of repeats in grid’s <code>repeat()</code>? Something else?</p>
<p>Go on, and experiment. We need more experiments!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115537439309401116">on Mastodon</a>!</p>Styles For Secondary Interactive Elementshttps://blog.kizu.dev/styles-for-secondary-interactive-elements/https://blog.kizu.dev/styles-for-secondary-interactive-elements/This is a post about another design tweak that I adopted while iterating on my site’s and blog’s designs over the years. I use it a lot, and really like how it feels and works — and I invite you to consider trying it as well.Thu, 13 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Raised By Swans — how do these hearts unfold</dd><dt>Current drink:</dt><dd>Lapsang Souchong tea</dd></dl><hr /><p>This is a post about another design tweak that I adopted while iterating on my site’s and blog’s designs over the years. I use it a lot, and really like how it feels and works — and I invite you to consider trying it as well.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="what-are-secondary-interactive-elements">What are “Secondary Interactive Elements”?</h2>
<p>I don’t know if there is a better term — this is just something I came up when trying to describe them. By “them” I mean interactive elements that are not <em>buttons</em> or <em>links</em>.</p>
<p>These — I know how to style: hover states, focus states, underlines for links, <code>cursor: pointer</code> for both. I know, I know, that last part is pretty contentious, but I stand by it <em>for a long time</em>, and wrote a <a href="https://kizu.dev/cursor-pointer/">“Correct Cursor on Active Elements”</a> article more than 12 years ago about this. Fun fact: <a href="https://github.com/w3c/csswg-drafts/issues/1936">my first CSSWG issue</a> was about this!</p>
<p>Regular text inputs could also be considered “primary”, and have established conventions over how to style them.</p>
<p>But what about <code><label></code>, <code><summary></code>? They’re also interactive! I will refer to them as “secondary”. And will try to convince you that they deserve some extra styling. Aside from the <code>cursor: pointer</code>, of course.</p>
<h2 id="dotted-underlines">Dotted Underlines</h2>
<p>Yes, dotted underlines. I don’t remember where exactly this came from, but in my early days of browsing cyrillic webs, dashed or dotted underlines were a thing, often for ligher JS-based interactive elements that are not exactly buttons and are not links.</p>
<p>I think, this type of styling fits the <code><label></code> and <code><summary></code> elements the best:</p>
<p><a href="https://blog.kizu.dev/styles-for-secondary-interactive-elements/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> for</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-checkbox"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-checkbox"</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"u"</span><span style="color:#E1E4E8">>Example of a label</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">details</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">summary</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"u"</span><span style="color:#E1E4E8">>Example of a summary</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">summary</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Demo details’ content. Hello.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">details</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Adding such underlines helps to communicate that these elements are, in fact, interactive. Especially for inputs because authors often forget to add proper labels, users might not know that they don’t have to be very precise and end up clicking only on the checkbox or radio buttons. We can help by adding extra affordance here.</p>
<h2 id="extra-inner-element">Extra Inner Element</h2>
<p>One thing you could notice: I have an extra <code>.u</code> span inside the label and summary, wrapping the actual text content, and applying the underline only to it:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.u</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> text-decoration</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">underline</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> text-decoration-style</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">dotted</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<aside class="warning">
In theory, we could have used just a `text-decoration: underline dotted` shorthand, but Safari does not support it yet.
</aside>
<p>The reason for this: this is the least hacky way for styling only the text. Here is what would happen if we were to apply the underlines to the <code><label></code> and <code><summary></code> on their own:</p>
<p><a href="https://blog.kizu.dev/styles-for-secondary-interactive-elements/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">label</span><span style="color:#B392F0"> for</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-checkbox2"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"u"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">input</span><span style="color:#B392F0"> id</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test-checkbox2"</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"checkbox"</span><span style="color:#E1E4E8"> /></span></span>
<span class="line"><span style="color:#E1E4E8"> Example of a label</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">label</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">details</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">summary</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"u"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Example of a summary</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">summary</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Demo details’ content. Hello.</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">details</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">label</span><span style="color:#B392F0">.u</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#85E89D">summary</span><span style="color:#B392F0">.u</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> text-decoration-style</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">dotted</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>In all browsers, the checkbox is treated as an inline element, and Firefox also treats the <code>summary</code>’s marker as such, and thus the <code>text-decoration</code> might go over them.</p>
<p>I found that adding an extra element around the content and delegating the underline to it is the most reliable way to handle this.</p>
<h2 id="why-not-dashed">Why Not Dashed?</h2>
<p>While this could seem like a personal preference, I consider dashed style to not work very well for thickier underlines. I also see more cross-browser difference for dashed underlines compared to the dotted ones.</p>
<p>Dotted underlines still look vastly different in all browsers, but because my main browser is Firefox — and it renders them the best — I ended up using them.</p>
<p>If I were to pursuit cross-browser styles, I would go for background images and used SVG with <code>stroke-dasharray</code> instead, alongside applying <a href="/box-decoration-break/">“Box Decoration Break”</a>.</p>
<h2 id="other-underline-styles">Other Underline Styles</h2>
<p>My blog’s design has more going on with the underlines: the color, the thickness, the hover, — but it is not limited only with dotted ones, but extends to regular links as well. That might be a topic on its own; I’ll blog about it on some other day.</p>
<p>But for today, that’s enough. Do you have styles that you apply to <code><details></code> and <code><summary></code>, or do you rely on browser defaults? I would be happy to hear from others!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115544286065414059">on Mastodon</a>!</p>It is OK to Say “CSS Variables” Instead of (or Alongside) “Custom Properties”https://blog.kizu.dev/css-variables/https://blog.kizu.dev/css-variables/TPAC 2025 just ended, and I am positively tired. Attending it remotely, my sleep schedule is chaotic right now. I have many ideas for CSS-related posts in my list of ideas for November, but almost all of them require at least some amount of research and crafting demos. Well! I found one note that I wanted to expand on, and which sounds tiny enough to be able to finish it in my altered state.Fri, 14 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Rökkurró — Sjónarspil</dd><dt>Current drink:</dt><dd>Ceylon Tea</dd></dl><hr /><style>{`
h1 {
font-size: 2.75rem;
}
`}</style>
<p><a href="https://www.w3.org/2025/11/TPAC/">TPAC 2025</a> just ended, and I am positively tired. Attending it remotely, my sleep schedule is chaotic right now. I have many ideas for CSS-related posts in my list of ideas for November, but almost all of them require at least some amount of research and crafting demos.</p>
<p>Well! I found one note that I wanted to expand on, and which sounds tiny enough to be able to finish it in my altered state.</p>
<p>Let me repeat the title of this post: <strong>it is OK to say “CSS Variables” instead of (or Alongside) “Custom Properties”</strong>.</p>
<p>I won’t say that this is something contentious, but it was always mostly a thing where I always stumbled a bit before continuing using the terminology.</p>
<p>The official name of the <a href="https://drafts.csswg.org/css-variables/">corresponding CSS module</a> is “CSS Custom Properties for Cascading Variables”. It’s URL’s slug is <code>css-variables</code>.</p>
<p>They are <em>variables</em>. More specifically: <em>cascading</em> variables. They change with the cascade: when different rules match, values can be overridden and change.</p>
<p>We can have animations that involve custom properties, or custom properties with values based on the viewport, containers, or something else — dynamic, responsive values that can <em>vary</em> for multitudes of reasons.</p>
<p>They are <em>also</em> custom properties, and even the more property-like when using <a href="https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule"><code>@property</code></a>. They can also be explicitly typed, while the rest of CSS is often typed implicitly. But — typed, unlike some other “programming languages”.</p>
<p>Ah, yes, CSS (and HTML) <em>are</em> <strong>programming</strong> languages, and anyone thinking otherwise is wrong. The <strong>best</strong> programming languages, according to me, by the way.</p>
<hr>
<p>Oh, I am tired. But also right after finishing this last <del>day</del> <ins>night</ins> of CSSWG <span class="normal">F2F</span>, I successfully experimented a bit with one ongoing idea of mine, and now planning to write a proper nice article, for my main site, like I sometimes do. Stay in touch.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115548474980668286">on Mastodon</a>!</p>My Most-Used Obsidian Pluginshttps://blog.kizu.dev/my-most-used-obsidian-plugins/https://blog.kizu.dev/my-most-used-obsidian-plugins/I’ve used Obsidian for quite a while. While my vault’s contents are a chaotic mess, it really helps me to be the place where I can put my notes and then find them when the need arises. I use a bunch of community plugins to improve a few workflows. And some of them I use more than others! That is a post about them!Sat, 15 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Helios — Dragonfly Across An Ancient Sky</dd><dt>Current drink:</dt><dd>Decaffeinated Earl Grey tea</dd></dl><hr /><style>{`h1 { font-size: 3rem; }`}</style>
<p>I’ve used <a href="https://obsidian.md/">Obsidian</a> for quite a while. While my vault’s contents are a chaotic mess, it really helps me to be the place where I can put my notes and then find them when the need arises.</p>
<p>I use a bunch of community plugins to improve a few workflows. And some of them I use more than others! That is a post about them!</p>
<p>The plugins will be in the alphabetical order. In the future, if I encounter another plugin that I will start using all the time, I’ll try to remember to update this list.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="advanced-uri">Advanced URI</h2>
<div class="aside-wrapper" style="--span: 3;">
<aside>
- [`obsidian-advanced-uri` on GitHub](https://github.com/Vinzent03/obsidian-advanced-uri)
- [Open in Obsidian](obsidian://show-plugin?id=obsidian-advanced-uri)
- By [Vinzent](https://github.com/Vinzent03)
</aside>
</div>
<p>A nice plugin, which I do not use by itself, but use it with my daily notes workflow — see the <a href="#calendar">Calendar</a> and <a href="#quickadd">QuickAdd</a> plugins.</p>
<p>Maybe I need to find some other uses for this plugin, as it can unlock some other useful actions as well.</p>
<h2 id="calendar">Calendar</h2>
<div class="aside-wrapper" style="--span: 2;">
<aside>
- [`obsidian-calendar-plugin` on GitHub](https://github.com/liamcain/obsidian-calendar-plugin)
- [Open in Obsidian](obsidian://show-plugin?id=calendar)
- By [Liam Cain](https://liamca.in/hello)
</aside>
</div>
<p>I use the core <a href="https://help.obsidian.md/plugins/daily-notes">“Daily Notes”</a> plugin, well, almost daily. Whenever I have some idea, I <a href="#quickadd">quickly add</a> it to my daily notes, where it goes with the exact time stamp of the idea in an unordered list. Then, I can go there and add any extra content or brainstorm a bit.</p>
<p>This plugin is very helpful both for accessing these daily notes, and for just having a calendar at hand. Usually, I can remember the approximate month/week when I wrote something down, and with this calendar, I can go and quickly look for it.</p>
<h2 id="hide-sidebars-on-window-resize">Hide Sidebars on Window Resize</h2>
<div class="aside-wrapper" style="--span: 3">
<aside>
- [`obsidian-hide-sidebars-on-window-resize` on GitHub](https://github.com/NomarCub/obsidian-hide-sidebars-on-window-resize)
- [Open in Obsidian](obsidian://show-plugin?id=obsidian-hide-sidebars-when-narrow)
- Originally by [Michael Hanson](https://work.michaelhanson.org/), <br>now maintained by [NomarCub](https://github.com/NomarCub)
</aside>
</div>
<p>This is a very tiny plugin that does just one thing. What thing? The one in its name. I use the <a href="https://rectangleapp.com/">Rectangle</a> app by <a href="https://ryanhanson.dev/">Ryan Hanson</a> to quickly resize windows or move them to a different screen. With the wider windows, I have both sidebars open at the same time. But when it becomes narrower, it is very convenient to remove those sidebars automatically.</p>
<p>One thing it doesn’t do and that could be improved: it does not consider vertically split tabs. It would’ve been great if it did consider not just the <em>window</em>’s width, but the number of vertically split tabs, and adjusted when to hide sidebars based on this, hiding them earlier.</p>
<p>Other than that, once installed, this plugin is mostly “invisible” and just works.</p>
<h2 id="paste-url-into-selection">Paste URL into selection</h2>
<div class="aside-wrapper" style="--span: 2">
<aside>
- [`obsidian-url-into-selection` on GitHub](github.com/denolehov/obsidian-url-into-selection)
- [Open in Obsidian](obsidian://show-plugin?id=url-into-selection)
- By [Denis Olehov](https://github.com/denolehov)
</aside>
</div>
<p>Another very simple plugin which also just does the thing in its title pretty well. You select some text, you have a link in your clipboard, you press paste — here you go. Nice.</p>
<h2 id="quickadd">QuickAdd</h2>
<div class="aside-wrapper" style="--span: 3">
<aside>
- [`quickadd` on GitHub](https://github.com/chhoumann/quickadd)
- [Open in Obsidian](obsidian://show-plugin?id=quickadd)
- By [Christian B. B. Houmann](https://bagerbach.com/)
</aside>
</div>
<p>Another useful addition to my daily notes workflow: allows adding new paragraphs to the today’s note.</p>
<p>I use it in combination with the <a href="#advanced-uri">Advanced URI</a> plugin and Alfred App, which allows me to open it, write <kbd>q</kbd> + <kbd>enter</kbd>, and start writing.</p>
<h2 id="recent-files-for-obsidian">Recent Files for Obsidian</h2>
<div class="aside-wrapper" style="--span: 3">
<aside>
- [`recent-files-obsidian` on GitHub](https://github.com/tgrosinger/recent-files-obsidian)
- [Open in Obsidian](obsidian://show-plugin?id=recent-files-obsidian)
- By [Tony Grosinger](https://grosinger.net/Home)
</aside>
</div>
<p>This is another very useful plugin that helps with my daily notes workflow. More specifically, it allows maintaining a list of recently open files that <em>excludes</em> the daily notes, as I already have quick access to them via <a href="#calendar">Calendar</a> plugin.</p>
<p>“Recent Files” allows me to have fewer open tabs and fewer pinned tabs, as opened files kinda “pin” themselves into this plugin’s list, and it becomes very simple to find something you return to a lot.</p>
<hr>
<p>That’s it! Do you use Obsidian? What plugins do you use all the time? Please let me know! While my practice is usually “look for a plugin once I want to automate something”, sometimes you might not know that you need something.</p>
<p>Maybe even you found something in the above list that you were “oh, I did not know I need this!”</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115556056444491600">on Mastodon</a>!</p>Preparing Images For Pixelfedhttps://blog.kizu.dev/preparing-images-for-pixelfed/https://blog.kizu.dev/preparing-images-for-pixelfed/I wanted to share for quite some time how I prepare photos before uploading them to Pixelfed, and now is a good opportunity to do so. There were a few things I noticed that made a difference in how pictures are displayed there.Sun, 16 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>mewithoutYou — January, 1979</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><style>{`h1 { font-size: 3.25rem; }`}</style>
<p>I wanted to post another batch of already published photos from <a href="https://pixey.org/kizu">my Pixelfed</a>, but something in its API does not allow me to fetch the photos as it previously allowed me to do, and I won’t have time to fix <em>that</em> part of my workflow for publishing them here.</p>
<p>However, I wanted to share for quite some time how I prepare photos before uploading them to Pixelfed, and now is a good opportunity to do so. There were a few things I noticed that made a difference in how pictures are displayed there.</p>
<p>I don’t know the details of how different Pixelfed instances can affect things, so what I will be talking about was tested on <a href="https://pixey.org/">Pixey.org</a>.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="problems">Problems</h2>
<p>In order, from the most impactful, to less.</p>
<h3 id="color-profiles">Color Profiles</h3>
<p>Pixelfed strips ICC color profiles from the photos, which can lead to them being less saturated and not looking how you would expect them to. There is an <a href="https://github.com/pixelfed/pixelfed/issues/4459">open issue about this</a> on Pixelfed’s GitHub.</p>
<p>This might be obvious, but it is pretty easy to forget about that.</p>
<p>**Solution: ** Export in sRGB, or, ideally, run the image through <a href="#squoosh">Squoosh</a>.</p>
<h3 id="images-dimensions">Image’s Dimensions</h3>
<p>Pixelfed instances have limits on the image dimensions, resizing the images when uploading, and doing it not with the best algorithm, resulting in images not being as sharp as you could want.</p>
<p>The limits for vertical and horizontal images (or — for the images’ width and height) can be different! On my instance, it is <code>1440px</code> for width, and <code>1350px</code> for height.</p>
<p>**Solution: ** Resizing images on your own before uploading, matching the limits. Then, Pixelfed will only <em>recompress</em> the image, but won’t <em>resize</em> it.</p>
<h3 id="image-compression">Image Compression</h3>
<p>Pixelfed will re-compress your images, regardless of how much you managed to optimize them before uploading.</p>
<p>This is the common issue I have with almost any services: it doesn’t matter how much you care and how much you optimize an image before uploading it. Services almost never look at the resulting size of the image you upload, and always run their optimization, replacing your image with it. Even if the new image will weight more, and result in a worse result visually!</p>
<p><strong>Solution:</strong> Export images in 100% quality. As Pixelfed will recompress the image anyways, this way you won’t lose on quality <em>twice</em>.</p>
<aside>
When checking, there was [an issue about this](https://github.com/pixelfed/pixelfed/issues/2342), but it was closed as fixed at the beginning of 2024. I will need to check if this is really fixed, at least for my workflow.
<p>When I last test the Pixelfed upload — in April of this year — I think I still noticed that Pixelfed did something to images that resulted in a worse quality after upload in not 100% quality. But, again, more testing is needed.</p>
</aside>
<h2 id="squoosh-app">Squoosh App</h2>
<p>I am using <a href="https://squoosh.app">Squoosh</a> to solve all these problems:</p>
<ol>
<li>
<p>It will save the image as sRGB by default, applying the color profile if it is present.</p>
</li>
<li>
<p>I </p>
</li>
<li>
<p>I use the “Resize” option and make sure width&height are not bigger than the limit.</p>
</li>
</ol>
<p>This results in an image that, in my opinion, looks the best once uploaded to Pixelfed.
This is a web app, it is free, it runs all the processing on your own device and doesn’t upload the image anywhere.</p>
<hr>
<p>I hope this helps someone! And maybe I am missing something that could make the images look even better? Do you have your own workflow that you use for this? Share it with me if so!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115561110924418186">on Mastodon</a>!</p>Whitespace in Codehttps://blog.kizu.dev/whitespace-in-code/https://blog.kizu.dev/whitespace-in-code/I always liked to pay a lot of attention to how I format my CSS, with the roots of it coming from the conventions that Vadim Makeev shared when we worked together in ~2007–2008. Currently, I don’t have spoons for formatting my CSS, but I try to polish my CSS examples that I put them in my articles, and, sometimes, for the components I am working on. If I were to give one advice for formatting CSS, it would be “use more whitespace”.Mon, 17 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Balmorhea — In the Rowans</dd><dt>Current drink:</dt><dd>Ginger & apple tea</dd></dl><hr /><p>I am working on a new article for my main site, for a new technique I invented, so this will be a shorter and lower-effort post (as, probably, those for the rest of the week).</p>
<p>I always liked to pay a lot of attention to how I format my CSS, with the roots of it coming from the conventions that <a href="https://pepelsbey.dev/">Vadim Makeev</a> shared when we worked together in ~2007–2008.</p>
<p>Some other conventions that I used at the time were enforced via the <a href="https://github.com/csscomb/csscomb.js">CSScomb formatter</a>, to which I even contributed a bit at the time. It is sad that this project is no longer maintained, and that Prettier does such a poor job of formatting CSS.</p>
<p>I also already wrote one post in this blog about formatting CSS: <a href="/calc-indent/">“Calculation Indentation”</a>.</p>
<h2 id="use-more-whitespace">Use More Whitespace</h2>
<p>Currently, I don’t have spoons for formatting my CSS, but I try to polish my CSS examples that I put them in my articles, and, sometimes, for the components I am working on.</p>
<p>If I were to give one advice for formatting CSS, it would be “use more whitespace”.</p>
<p>Put extra lines between rules:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.button</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> …</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> …</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Put extra lines before comments, but no additional lines after:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#6A737D">/* My beautiful button. */</span></span>
<span class="line"><span style="color:#B392F0">.button</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> …</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D">/* A responsive card component. */</span></span>
<span class="line"><span style="color:#B392F0">.card</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* We shrink the card to fit its contents. */</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">max-content</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* Without `width: auto`, we need to limit the max. */</span></span>
<span class="line"><span style="color:#79B8FF"> max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Group common groups of properties together:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.tooltip</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#6A737D"> /* It is year 42025, we support anchor positioning. */</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">absolute</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> position-anchor</span><span style="color:#E1E4E8">: --anchor;</span></span>
<span class="line"><span style="color:#79B8FF"> position-area</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">bottom</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#6A737D"> /* TODO: use design tokens, maybe. */</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> box-shadow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> 0.2</span><span style="color:#F97583">em</span><span style="color:#79B8FF"> 0.4</span><span style="color:#F97583">em</span><span style="color:#79B8FF"> -0.2</span><span style="color:#F97583">em</span><span style="color:#79B8FF"> deepPink</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>The reason to do all of these instead of lumping everything together is that having extra whitespace allows you to group related things together.</p>
<p>It is easier to tell two rules apart if they’re separated by extra lines, and especially if there are comments alongside: a comment will look more like a header when it has a bigger space before it and less after — and a common design principle is to “glue” headers to the content after.</p>
<p>Grouping common properties together makes it easier to tell what is going on, and makes it easier to put new declarations in the rule. That’s where CSScomb was very useful!</p>
<hr>
<p>Do you have your own rules for formatting your CSS? It is often a very subjective matter, but it would be great to hear if there is anything you do differently.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115566478177085986">on Mastodon</a>!</p>Minimal Reproductionshttps://blog.kizu.dev/minimal-reproductions/https://blog.kizu.dev/minimal-reproductions/I am continuing working on my new article, and while making examples for it, I stumbled upon a crash in Safari — both in its stable version and in Technology Preview. I managed to reduce it to a minimal reproduction and reported it — and in this post I want to encourage you to create minimal reproductions of any bugs you encounter too — for more than one reason.Tue, 18 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>GoGo Penguin — Murmuration</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>I am continuing working on my new article, and while making examples for it, I stumbled upon a crash in Safari — both in its stable version and in Technology Preview. I managed to reduce it to a minimal reproduction and reported it — and in this post I want to encourage you to create minimal reproductions of any bugs you encounter too — for more than one reason.</p>
<p>Here is the bug that I reported: <a href="https://bugs.webkit.org/show_bug.cgi?id=302703">“Tab crashes when an element containing a scoped scroll-driven animation from an inner pseudo-element repeatedly changes display while depending on cqw”</a>.</p>
<p>That’s a long title! But the conditions are also pretty specific — as it often goes with my experiments.</p>
<p>That said — the code I reported is as minimal of a reproduction as I could manage to reduce the original CSS to. From around 150 lines to around 30. There was a lot more going on before I stripped everything that did not impact the crash!</p>
<p>The first reason the minimal reproduction is helpful: you will understand what is going on much easier, and will be able to confirm to yourself if that’s really a bug, or some interaction in the specs you’re missing. Of course, for a crash this is not as important, but then by understanding what’s going on you will be able to report it better — with proper title and description. Not just “something is wrong”.</p>
<p>The second reason: it will be much easier to understand where the issue is for the engineers that will be working on fixing the bug. You’re likely already in the context of your code, you know what is likely to be not related, and it will be much faster for you to reduce it. You also know exactly about what the issue is, and could verify that it still happens with ease. And if the engineers working on the bug are more efficient with their time, and if the bug does not look intimidating to take from the backlog — the chances are it will be fixed much, much faster than otherwise.</p>
<p>The final reason: after creating a minimal reproduction, you will be left with a limited number of puzzle pieces that explode together. In CSS, it is always possible to do the same thing in multiple ways. Sometimes this is a hindrance which leads to the choice paralyzis, but in case of bugs, this is an advantage: for any code path that leads to the bug you can look for another road to your desired result. And anothe method might not cause the bug!</p>
<p>That’s what happened in my case: it wouldn’t be very nice if examples in my new article — and the technique at large — would cause random browser crashes. But by reducing things, I was able to identify a simple solution: while most conditions in the bug I reported related to the scroll-driven animations and setup around them, the simplest outlier was the presence of pseudo-element: simple tests shown that replacing a pseudo-element with a real element eliminated the crash. Oh well, the code will be not as efficient and with a more verbose HTML, but still working.</p>
<hr>
<p>So — please, whenever you encounter bugs, try to find the minimal reproduction, understand what’s going on, and then report it. This will make the fix to become available faster <em>for everyone</em>, but, specifically for you, a possible workaround will be closer as well.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115572959104443478">on Mastodon</a>!</p>Anchoring to a Containing Blockhttps://blog.kizu.dev/anchoring-to-a-containing-block/https://blog.kizu.dev/anchoring-to-a-containing-block/Today I stumbled upon a CSS issue that I and some others had in the past: an inability to use an anchored element’s containing block with anchor positioning. At least — to do so easily. This post is about how we can actually do so with just a few small changes to your usual anchor positioning setup.Wed, 19 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haru Nemuri — Lost Planet</dd><dt>Current drink:</dt><dd>Fruity infusion (pear, kiwi, mango, etc.)</dd></dl><hr /><style>{`h1 > :first-child { font-size: 4rem; }`}</style>
<p>I am still working on my new article! And today I stumbled upon an issue that I and some others had in the past: an inability to use an anchored element’s containing block with anchor positioning.</p>
<p>At least — to do so easily. This post is about how we can actually do so with just a few small changes to your usual anchor positioning setup.</p>
<p>I did not end up using this in my article, so decided to share today regardless.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>Look at this example:</p>
<p><a href="https://blog.kizu.dev/anchoring-to-a-containing-block/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">relative</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> anchor-name</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">legend</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">absolute</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> position-anchor</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: anchor(</span><span style="color:#79B8FF">inside</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(anchor(</span><span style="color:#79B8FF">outside</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-BG</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Some legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Here, we could expect the <code><legend></code> to be positioned correctly… but it doesn’t. It does not see the mentioned anchor, and thus the values for the corresponding inset properties become initial. This behavior is <a href="https://drafts.csswg.org/css-anchor-position-1/#acceptable-anchor-element">per spec</a>:</p>
<blockquote>
<p><em>possible anchor</em> and <em>positioned el</em> have the same original containing block and either</p>
</blockquote>
<p>Basically, if our anchor <em>is</em> our positioned element’s original containing block, this condition won’t match.</p>
<p>Last year, I opened <a href="https://github.com/w3c/csswg-drafts/issues/10412">an issue about this</a>, and I saw other people also stumble upon this issue, for example, <a href="https://jamessw.com/">James Stuckey Weber</a> also opened <a href="https://github.com/w3c/csswg-drafts/issues/11769">another issue</a> about this.</p>
<p>Eventually, it was <a href="https://github.com/w3c/csswg-drafts/issues/11769#issuecomment-2776545248">resolved</a> to not change anything, but consider a way to adjust the containing block in the future.</p>
<p>But what can we do today?</p>
<h2 id="the-solutions">The Solutions</h2>
<h3 id="not-using-anchor-positiong">Not Using Anchor Positiong</h3>
<p>Ok, in this exact case we don’t even have to use anchor positioning, and could do just this:</p>
<p><a href="https://blog.kizu.dev/anchoring-to-a-containing-block/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">relative</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">legend</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">absolute</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">-1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-BG</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Some legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>If you compare the two examples, you’ll notice one difference: where the “magical” <code>1px</code> goes. In the non-working example it was in the <code>bottom</code> property, but in the working example it moves to <code>left</code>.</p>
<p>This is because anchor positioning takes borders into account, while regular absolute positioning uses a padding box for positioning.</p>
<p>In my today’s experiments, I actually wanted to <em>measure</em> the width of the border, so I needed to anchor to the <em>outside</em> of the containing block.</p>
<p>Basically, whenever we need to take the border into account, anchor positioning could help — but not easily if our anchor is our containing block.</p>
<h3 id="using-position-fixed">Using <code>position: fixed</code></h3>
<p>The proper solution: to use <code>position: fixed</code>, as then we won’t be bound by the same containing block.</p>
<h4 id="without-scoping">Without Scoping</h4>
<p>However, we can’t just replace <code>absolute</code> with it: if we’d have several elements, then their containing block will become the viewport, and both anchored elements will use the same last visible anchor for the positioning:</p>
<p><a href="https://blog.kizu.dev/anchoring-to-a-containing-block/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">relative</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> anchor-name</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">legend</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">fixed</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* The only change */</span></span>
<span class="line"><span style="color:#79B8FF"> position-anchor</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: anchor(</span><span style="color:#79B8FF">inside</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(anchor(</span><span style="color:#79B8FF">outside</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-BG</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>First fieldset’s legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Second legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>We don’t want that!</p>
<h4 id="adding-scoping">Adding Scoping</h4>
<p>Thankfully, we have an <code>anchor-scope</code> property, and if we add it to our anchor with the same name, this element will be the last elements any children will see when looking for the corresponding anchor name, and use it:</p>
<p><a href="https://blog.kizu.dev/anchoring-to-a-containing-block/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">relative</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> anchor-name</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> anchor-scope</span><span style="color:#E1E4E8">: --fieldset; </span><span style="color:#6A737D">/* Required! */</span></span>
<span class="line"><span style="color:#79B8FF"> margin-top</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1.5</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">legend</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> position</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">fixed</span><span style="color:#E1E4E8">; </span><span style="color:#6A737D">/* Not `absolute` */</span></span>
<span class="line"><span style="color:#79B8FF"> position-anchor</span><span style="color:#E1E4E8">: --fieldset;</span></span>
<span class="line"><span style="color:#79B8FF"> left</span><span style="color:#E1E4E8">: anchor(</span><span style="color:#79B8FF">inside</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(anchor(</span><span style="color:#79B8FF">outside</span><span style="color:#E1E4E8">) - </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> padding-inline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border-bottom</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-BG</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>First fieldset’s legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">>Second legend</</span><span style="color:#85E89D">legend</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">>Some fieldset’s content</</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">fieldset</span><span style="color:#E1E4E8">></span></span></code></pre>
<h4 id="the-only-issue">The Only Issue…</h4>
<p>If you look at this example in Safari (even in Technology Preview) or Firefox Nightly, then you might notice a few rendering issues with the anchored elements that use <code>position: fixed</code>.</p>
<p>Sometimes it works there, sometimes it doesn’t, with the position not updating correctly from time to time.</p>
<p>I will open bugs about this, but not today (unless someone else will beat me to it, wink wink).</p>
<h5 id="update-from-2025-12-31">Update from 2025-12-31</h5>
<p>Good news: at least in the latest Firefox Nightly, the above example seems to work well! In Safari, it is still glitchy, mostly when there is a smooth scroll going on, but it is <em>tolerable</em>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>While it might seem that anchor positioning is already present in some stable versions of browsers, in reality it is further from being even baseline. If, today, Firefox would release anchor positioning into its stable version, even if Firefox itself will be perfect, there are enough issues, starting from feature’s usability (absent features like being able to change the containing block) to bugs in stable versions of browsers that prevent many use cases from being viable.</p>
<p>The Safari bug above is not the only issue I found when testing anchor positioning: Chrome also has at least <a href="https://issues.chromium.org/issues/425894800">one blocker</a> that prevents many use cases. Maybe I will write about it some other day.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115578454406848256">on Mastodon</a>!</p>Scope for Exampleshttps://blog.kizu.dev/scope-for-examples/https://blog.kizu.dev/scope-for-examples/With yesterday’s post, — “Anchoring to a Containing Block” — I started to use `@scope` for my CSS code examples.Thu, 20 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Jenn Champion — Going Nowhere</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>With yesterday’s post, — <a href="/anchoring-to-a-containing-block/">“Anchoring to a Containing Block”</a> — I started to use <code>@scope</code> for my code examples.</p>
<p>This is one of the most exciting use cases I saw for the <code>@scope</code> — an ability to do something like this:</p>
<p><a href="https://blog.kizu.dev/scope-for-examples/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Hello!</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>See how I render this code inline in my post, and the <code>p</code> selector is not applying to this literal paragraph that I am writing right now?</p>
<p>And, actually, let me show you how this looks like in my markdown:</p>
<div class="aside-wrapper" style="--span: 2;">
<aside>
I am not mentioning it in this post, but I also have a `require` prop to signify the support of the feature and add a warning to browsers that do not support it yet.
</aside>
</div>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="mdx"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><LiveExample isScoped require="at-scope"></span></span>
<span class="line"><span style="color:#9ECBFF">```</span><span style="color:#B392F0">css</span></span>
<span class="line"><span style="color:#85E89D">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#9ECBFF">```</span></span>
<span class="line"><span style="color:#9ECBFF">```</span><span style="color:#B392F0">html</span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">>Hello!</</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#9ECBFF">```</span></span>
<span class="line"></span></code></pre>
<p>This is how I write all the examples in my blog: I have my custom Astro <code>[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/scope-for-examples/)</code> component, which takes the Markdown code blocks inside, and both shows the corresponding code, but also outputs these code blocks’ content on the page, so I can just write my examples once, have their code visible, and not have to duplicate the effort when I need to update something.</p>
<p>In the above case you can see the <code>isScoped</code> prop: before I had it, all examples did output their code <em>literally</em>, so whenever I had to have similar examples, I had always to come up with some prefix or unique class names for them.</p>
<p>With <code>isScoped</code>, I wrap the content of the inner CSS block with just <code>@scope {}</code>, so that code will be equivalent to</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">@scope</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#85E89D"> p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Which can be called “local scoping”, see the <a href="https://drafts.csswg.org/css-cascade-6/#scope-limits">“Identifying Scoping Roots and Limits”</a> section of the Cascading and Inheritance Module 6.</p>
<p>How it works is: if we add an HTML <code><style></code> tag in our HTML, and inside this tag there will be an <code>@scope</code> without the scope start selector, it will be scoped to that <code><style></code>’s parent element:</p>
<blockquote>
<p>If no <code><scope-start></code> is specified, the scoping root is the parent element of the owner node of the stylesheet where the <code>@scope</code> rule is defined.</p>
</blockquote>
<p>And that is very useful for any blog posts with code examples — this makes every example to work independently of others.</p>
<p>There are a few things I will need to improve with how I use these types of examples:</p>
<ul>
<li>
<p>Sometimes, there is a need to share some styles across different examples. Possible solution: use named scopes, and overload the prop to allow also doing <code>isScoped="foo"</code>, where I could mention some ident, and then both the example will get this ident automatically added as a class name to the example’s wrapper, and it will go into the <code>@scope</code> like <code>@scope (.scope-foo)</code> or something.</p>
</li>
<li>
<p>It can still be useful for understanding of the examples to have their full code, so maybe there could also be something done on the LiveExample’s side to add some automatic diffing of consequtive examples, where we could highlight the changed lines in some way? In yesterday’s post, that would’ve been pretty handy.</p>
</li>
</ul>
<h2 id="but-scope-is-not-baseline">But… <code>@scope</code> is not Baseline?</h2>
<p>Yeah, but I also write about non-baseline things. When writing about CSS features like anchor positioning or scroll-driven animations, or anything newer, there is no reason <em>not</em> to use <code>@scope</code>.</p>
<p>If you have a blog, write about modern CSS, and create inline demos there (not by embedding CodePens or anything else as <code><iframe></code>s), I highly recommend you to try <code>@scope</code>. It is cool.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115583835739738989">on Mastodon</a>!</p>I Want to Rewrite Everythinghttps://blog.kizu.dev/i-want-to-rewrite-everything/https://blog.kizu.dev/i-want-to-rewrite-everything/This whole week, I am switching between writing posts in this blog and working on my next article for my main site. My blog has a much more modern setup for writing posts. The old setup? It is an abomination. I really would like to rewrite everything that I have there to use the same architecture I am using for my blog.Fri, 21 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>COVET — falkor</dd><dt>Current drink:</dt><dd>Fruity infusion (pear, kiwi, mango, etc.)</dd></dl><hr /><style>{`h1 { font-size: 3.75rem; }`}</style>
<p>This whole week, I am switching between writing posts in this blog and working on my next article for my <a href="https://kizu.dev/">main site</a>.</p>
<p>My blog has a much more modern setup for writing posts: it is based on <a href="https://astro.build/">Astro</a>, and I enjoy tweaking the components that I use with it, like with my yesterday’s <a href="/scope-for-examples/">“Scope for Examples”</a> post.</p>
<p>Writing posts with this setup is a joy, where it is effortless to add new interactive examples, and adjust things.</p>
<p>The old setup? It is an abomination of some old <a href="https://gulpjs.com/">gulp</a> custom config, with a bunch of custom JS and <a href="https://gohugo.io/">Hugo</a> on top of it. The templating system that it has? One of the worst I used. Honestly, screw React, but JSX and the idea of components are a much better fit for what I usually want for building complex HTML pages. And with Astro not outputting any actual JS and pre-building everything in HTML is just great.</p>
<p>So, all of this might be one of the reasons why I am not writing longer and more polished articles on my site as often. I really would like to rewrite everything that I have there to use the same architecture I am using for my blog.</p>
<p>There are still many features that my old setup has that I did not yet implement here: sidenotes are much better there, examples with screenshots/video alternatives, some other aspects. But, eventually, I would really like to have just one system I maintain and use in both places. Ideally, in the same repo: currently, the sources for both are separate, and this makes it harder to maintain things or deploy things simultaneously.</p>
<p>If only I had more time! My current paid time off is running out, but I am already planning to return to this idea of rewriting everything at the end of December.</p>
<p>I need to still find a way to somehow keep the old setup alongside the new one, as it is likey impossible to (quickly) migrate <em>everything</em> from the old system to the new one. So what I am planning is to try and make it possible to <em>merge</em> both, and keep the old posts rendered with the old system, while allow writing new posts with Astro. We’ll see if it will work out!</p>
<p>I guess, this was a much less useful post for anyone reading, but I really want to just document — even if for myself — the process of me working on my website.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu">on Mastodon</a>!</p>On Perfectionism and Chaotic Messeshttps://blog.kizu.dev/on-perfectionism-and-chaotic-messes/https://blog.kizu.dev/on-perfectionism-and-chaotic-messes/I don’t have a topic for today, so I decided to ramble a bit on a random topic: wondering how the two things in the title of today’s post can live at the same time in me. I have a tendency for perfectionism. At the same time, I often surround myself with various degrees of chaotic mess.Sat, 22 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Keaton Henson — You</dd><dt>Current drink:</dt><dd>Ginger & apple tea</dd></dl><hr /><style>{`h1 { text-align: center }`}</style>
<p>I don’t have a topic for today, so I decided to ramble a bit on a random topic: wondering how the two things in the title of today’s post can live at the same time in me. I have a tendency for perfectionism. At the same time, I often surround myself with various degrees of chaotic mess.</p>
<p>I think the answer is in the availability of <a href="https://en.wikipedia.org/wiki/Spoon_theory">spoons</a>.</p>
<p>Would I want this chaotic mess that is my room, or my file system, or obsidian vault, or everything else, to be less messy, organized, structured, and <em>perfect</em>? Oh, I would.</p>
<p>Do I know what to do and how to approach achieving this? Yep.</p>
<p>Would I do it? I can’t: I don’t have enough spoons for <em>everything</em>. I think I might’ve lost all of them in CSS (Cascading Spoons Supply).</p>
<p>In my notes for the November ideas, almost everything is about CSS. I am on “vacation”, and that means that I can, finally, spend as much as I want on CSS. Although, it appears that I can’t do it too many days in a row — need some rest time, after all. But oh how I wish I could do all of this every work day, just work on CSS.</p>
<p>CSS is in the foundation of my hierarchy of needs, it is physiological at this point.</p>
<p>Any spoons that do not feed the CSS demon are wasted.</p>
<p>The problem: CSS is so large, I don’t even have enough spoons to put them into every declaration. There is just so much to think about, to experiment, to delve into!</p>
<p>Oh, well.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115595328576807309">on Mastodon</a>!</p>Photo Walk, Aprilhttps://blog.kizu.dev/walk-april-2025/https://blog.kizu.dev/walk-april-2025/I am back with reposting some of my old photos from my Pixelfed, but now in my blog. I did not fix the API issue that prevented me from doing it the last time, but made a workaround that worked well enough.Sun, 23 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Flip Grater — Hymns</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>I am back with reposting some of my old photos from my Pixelfed, but now in my blog. I did not fix the API issue that prevented me from doing it the last time, but made a workaround that worked well enough.</p>
<p>Curiously, the first two images from this post can illustrate what I was talking a week ago in my <a href="/preparing-images-for-pixelfed/">“Preparing Images For Pixelfed”</a> post.</p>
<p>The first image from this series was published before I saw the issue with the color profiles and resizing/recompression:</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“A blossoming tree.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>It has a bit of a flatter profile than what I inteded to have, and is not as sharp as it could be.</p>
<p>After this image, I changed my workflow, and here is, hopefully, the quality of photos that I’ll try to post from this point on (unless I will report some of the older ones, of course):</p>
<p><img src="pixelfed:819153360222415327" alt=""></p>
<p>If the last two posts that I shared had photos made with the 17mm prime lens, this time I went to the opposite side: I bought a second-hand lens from <a href="https://www.mpb.com/en-eu">MPB</a> — Olympus M.Zuiko 75mm f/1.8.</p>
<p>Before that, my favorite lens was the 45mm one, but I think fell in love with this lens after my first walk with it. I really like to hunt for details, and I am fascinated by the out-of-focus rendering this lens produces.</p>
<p><img src="pixelfed:819278910423709262" alt=""></p>
<p>This metal lens is pretty big for Micro Four Thirds, and is quite heavy: a bit more than 300g. Initially, I thought that it would not be as comfortable as other lenses on my OM-3, which doesn’t have the best grip, but at some point I stopped noticing it.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“Over the wall.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>This time I went first to the park, then with a goal to go down the hill to the Seine and then back.</p>
<p>I am usually shy, and try to avoid being obvious when shooting people, but this lens really allows being very far away, not feel like you intrude, and catch some nice small scenes.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“In the park.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>The next photo, especially with that crop, demonstrates the background compression that 75mm — 150mm equivalent on full frame — can achieve. This is the edge of the terrace, with the <a href="https://en.wikipedia.org/wiki/La_D%C3%A9fense">La Défense</a> in the background, around ten kilometers afar.</p>
<p><img src="pixelfed:819657198652892960" alt=""></p>
<p>Scyscrapers? They look nice in the distance, but that’s it. I would rather be closer to the tiny buildings like this one:</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“I wonder what’s there inside” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>And closer to these fellows as well:</p>
<p><img src="pixelfed:819967576422198838" alt=""></p>
<p>In this park there are always people, and there is always someone standing there at the edge and marvelling the views.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“People on the terrace.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Though, some are not that interested in them.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“Dog.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Going through the park, I started to go down the hill. One notable thing there is this pavillon visible:</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“With not that old buildings behind it.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>The telephoto lens makes it possible to catch some nice details, like the statues in this pavillon’s garden with maze hedges.</p>
<p><img src="pixelfed:821724817813925020" alt=""></p>
<p>The views are very nice both on the terrace, and on the way down: bridges, trees, old buildings, a lot of things to look at.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“A Bridge.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Not that many people walk this way, uphill or downhill. I once went there, and the path is generally pleasant.</p>
<p><img src="pixelfed:822373303163935317" alt=""></p>
<p>There are many ways down, and I used the one I chose for the second time, as the last time I saw a bunch of squirrels there. This time I also saw them, but did not manage to make any good photos, oops.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“Another dog!” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>It is always nice down by the river, although, while 75mm is nice, it is just barely enough to catch some birds there: would need a much more powerful lens for that. But not sure if I want one.</p>
<p><img src="pixelfed:822748381239615063" alt=""></p>
<p>The riverbank is pretty diverse, with boardwaks, pathways, etc. It is rather nice there.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“A boardwalk.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>The river is wide, there are islands on it, with trees almost falling into the water.</p>
<p><img src="pixelfed:823539067871018024" alt=""></p>
<p>Some tall trees on the other side, and some tiny trees on this one.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“Green grass.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>And some dinosaurs swimming in the river.</p>
<p><img src="pixelfed:824343465583386512" alt=""></p>
<p>Managed to catch this composition in the end, with the lens allowing to get it without too much cropping.</p>
<p><a href="https://blog.kizu.dev/walk-april-2025/">“A rectangle.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>That’s it for now! I don’t have other full photo walks I did afterwards, but I have a lot of older photos that I will be slowly publishing, so it is likely the next photo posts will have photos from my older camera and lenses.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115600822289000660">on Mastodon</a>!</p>Play With Inherit Functionhttps://blog.kizu.dev/play-with-inherit-function/https://blog.kizu.dev/play-with-inherit-function/One of the things that might flight under many people’s radars is the incoming `inherit()`. Not the `inherit` keyword — we had it for quite a while already. Now it is available in Chrome Canary with the “experimental web platform features” flag, so, if you want, you can go play with it!Mon, 24 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>MASS OF THE FERMENTING DREGS — New Order</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><p>One of the things that might flight under many people’s radars is the incoming <a href="https://drafts.csswg.org/css-values-5/#inherit-notation"><code>inherit()</code> functional notation</a>. Not the <code>inherit</code> keyword — we had it for quite a while already.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>In 2018, <a href="https://lea.verou.me/">Lea Verou</a> opened an <a href="https://github.com/w3c/csswg-drafts/issues/2864">“inherit() function: like var() for parent value, for any property”</a> issue in CSSWG GitHub, in 2021 CSSWG <a href="https://github.com/w3c/csswg-drafts/issues/2864#issuecomment-816280875">resolved to adopt it</a>, and was stale since then, until, finally, last month, <a href="https://github.com/andruud">Anders Hartvoll Ruud</a> sent an <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/nCUNGmfAOMU/m/YOCfBQV6BwAJ">Intent to Prototype</a> for it, and <a href="https://issues.chromium.org/issues/452071846">started implementing</a> it in Chromium. Did this happen because I pestered him at this year’s <a href="https://cssday.nl/">CSS Day</a> asking how hard it would be to do? Who knows!</p>
<p>But now it is available in Chrome Canary with the “experimental web platform features” flag, so, if you want, you can go play with it! It only works for custom properties for now, for similar reasons of why we don’t have style queries for regular properties, but maybe one day this will change, although I won’t wait for this.</p>
<p>So, yeah, experiment!</p>
<p>Like, for example, <a href="https://www.alwaystwisted.com/">Stuart Robson</a> already did with his <a href="https://www.alwaystwisted.com/articles/making-context-aware-components">“Making Context-Aware Components: How CSS <code>inherit()</code> Could Simplify Design Systems”</a> article.</p>
<p>Or — how I did last year with my <a href="https://kizu.dev/self-modifying-variables/">“Self-Modifying Variables: the <code>inherit()</code> Workaround”</a>, although there I wrote about a workaround that we can use instead today. This workaround relies on container style queries though, so not really production-ready, but still better than nothing!</p>
<h2 id="some-examples">Some Examples</h2>
<p>The following examples will not work anywhere where the <code>inherit()</code> is not supported — so, you can open Chrome Canary if you want to look at them!</p>
<p>I will just adapt some of the examples I had in <a href="https://kizu.dev/self-modifying-variables/">my article about its workaround</a>, so nothing too new. But, hey, that article was not super popular, so maybe you missed it.</p>
<p>I won’t provide any screenshots here — if you want to check how things should look like, go to the above article — it has both live examples and screenshots for them.</p>
<h3 id="element-depth">Element Depth</h3>
<p>I slightly adjusted <a href="https://kizu.dev/self-modifying-variables/#the-technique">my original example</a>: we can have a <code>--depth</code> custom property, and bump its value for every component of the same type that is nested inside itself:</p>
<p><a href="https://blog.kizu.dev/play-with-inherit-function/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.test</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --depth</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">(--depth, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">) + </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FFAB70"> --padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> oklch</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> from </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--BG-FROM</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> l c</span></span>
<span class="line"><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 127</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> )</span></span>
<span class="line"><span style="color:#E1E4E8"> ;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 4.5</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> -</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#79B8FF"> border-start-start-radius</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0.5</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">));</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &::before {</span></span>
<span class="line"><span style="color:#E1E4E8"> counter-reset: depth </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">counter</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">depth</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"bar"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"test"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>With the <code>--depth</code> incrementing on every element, we can then use it for <em>anything</em>: adjust colors via their <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Colors/Using_relative_colors">relative syntax</a>, make the border-radius decrease with the depth level, and so on.</p>
<h3 id="nested-menu-lists">Nested Menu Lists</h3>
<p>I love my second example from this article: this is the use case that I very often stumble in my practice — the need to have a nested list, where the indentation of elements grows, but each line should be interactive from start to end. Without <code>inherit()</code> or its workaround, we generally had to express the depth in HTML in some way, but now this <em>just works</em>:</p>
<p><a href="https://blog.kizu.dev/play-with-inherit-function/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">ul</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --depth</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">(--depth, </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">) + </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">fit-content</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#F97583"> !important</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> auto</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">li</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#F97583"> !important</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> list-style-type</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#85E89D">li</span><span style="color:#B392F0">::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">""</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#85E89D">li</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> a</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-block</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.25</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding-inline-start</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 2</span><span style="color:#F97583">em</span><span style="color:#F97583"> -</span><span style="color:#79B8FF"> 1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> oklch</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#E1E4E8"> from </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--BG-FROM</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> l c</span></span>
<span class="line"><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 127</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> )</span></span>
<span class="line"><span style="color:#E1E4E8"> ;</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> transparent</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> background-clip</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">padding-box</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> text-decoration</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">none</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> color</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--color</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> &:is(:hover, :focus-visible) {</span></span>
<span class="line"><span style="color:#79B8FF"> border-color</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> oklch</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">30</span><span style="color:#F97583">%</span><span style="color:#79B8FF"> 1</span><span style="color:#79B8FF"> calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--depth</span><span style="color:#E1E4E8">) </span><span style="color:#F97583">*</span><span style="color:#79B8FF"> 75</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"#"</span><span style="color:#E1E4E8">>Menu item</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Again, the only thing we need to do here is this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">--depth: calc(inherit(--depth, 0) </span><span style="color:#F97583">+</span><span style="color:#E1E4E8"> 1);</span></span></code></pre>
<p>And then we’re free to use that custom property in any way we want.</p>
<h3 id="swapping-values">Swapping Values</h3>
<p>The last example is a fun one: an ability to swap variables around:</p>
<p><a href="https://blog.kizu.dev/play-with-inherit-function/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:scope</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --a</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#FFAB70"> --b</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.swapped</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --a</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">(--b);</span></span>
<span class="line"><span style="color:#FFAB70"> --b</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">(--a);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.a</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--a</span><span style="color:#E1E4E8">); }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.b</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--b</span><span style="color:#E1E4E8">); }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">p</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.25</span><span style="color:#F97583">em</span><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Regular:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"a"</span><span style="color:#E1E4E8">>A: green</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"b"</span><span style="color:#E1E4E8">>B: pink</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"swapped"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> Swapped:</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"a"</span><span style="color:#E1E4E8">>A: pink</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"b"</span><span style="color:#E1E4E8">>B: green</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>Again, without <code>inherit()</code> or my workaround this is not possible.</p>
<h2 id="go-on">Go On!</h2>
<p>This is a really great feature: I hope that other browsers will also look into experimenting and implementing it. It might be simple, but it unlocks many nifty use cases.</p>
<p>And even if you can’t think of one now — when you will be writing CSS, try to remember that we will get this in the future.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115607054648933293">on Mastodon</a>!</p>Responsive Cyclic Marginshttps://blog.kizu.dev/responsive-cyclic-margins/https://blog.kizu.dev/responsive-cyclic-margins/The title of this post might not seem like a big deal, but the problem I will talk about was pretty fun to work out: how do you make a margin between elements responsive based on the available space in their parent, and such that it does not collapse in a `min-content` context?Tue, 25 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Mitski — Pearl Diver</dd><dt>Current drink:</dt><dd>Infusion of hibiscus, apples, rosehip, and orange peels, with cherry flavor.</dd></dl><hr /><p>The title of this post might not seem like a big deal, but the problem I will talk about was pretty fun to work out: how do you make a margin between elements responsive based on the available space in their parent, and such that it does not collapse in a <code>min-content</code> context?</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>That might seem to be pretty specific, but let’s say we have an element with two parts like a button, with the text disappearing when there is not enough space:</p>
<div class="aside-wrapper" style="--span: 2">
<aside>
I won’t touch on if using ellipsis in cases like this one is a good idea. In an ideal world, you would have a better content strategy, but in Hell…
</aside>
</div>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:scope</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">8</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --icon-size</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --min-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--icon-size</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--border</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#F97583"> +</span></span>
<span class="line"><span style="color:#79B8FF"> 2</span><span style="color:#F97583"> *</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">p</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> resize</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">horizontal</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> outline</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--PINK</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">min-content</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#85E89D">button</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-flex</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> max-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> min-width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--min-width</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> padding</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--padding</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--border</span><span style="color:#E1E4E8">) </span><span style="color:#79B8FF">solid</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--GREEN</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> background</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--CONTENT-BG</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> border-radius</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">lh;</span></span>
<span class="line"><span style="color:#79B8FF"> font</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inherit</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> cursor</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">pointer</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.ellipsis</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">hidden</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> white-space</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">nowrap</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> text-overflow</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">ellipsis</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.icon</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">inline-block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--icon-size</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#79B8FF"> text-align</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">center</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> flex-shrink</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>What we want is to add a margin between the text and icon here, but make it disappear when the button collapses.</p>
<p>Any static margin added to either span there will be still there when we collapse the button to be narrower than the available space:</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width);"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis with-margin"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon with-margin"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.ellipsis.with-margin</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-right</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"><span style="color:#B392F0">.icon.with-margin</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>And, because our buttons has to shrink to fit its contents, we can’t use <code>inline-size</code> containment and size the margin via container query length units. So, what to do?</p>
<h2 id="an-attempt">An Attempt</h2>
<p>You could think: hey, we can use <code>%</code> in CSS, which will be evaluated based on the width of the parent element… Could we use it in some way, like with a calculation?</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon with-naive-percentage"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon with-naive-percentage"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.icon.with-naive-percentage</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin-left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> 0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#79B8FF"> 100</span><span style="color:#F97583">%</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--min-width</span><span style="color:#E1E4E8">),</span></span>
<span class="line"><span style="color:#79B8FF"> 0.5</span><span style="color:#F97583">em</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>It seems to wor— oh wait, why is there an ellipsis? And even when we expand our resizable paragraph, it stays this way?</p>
<p>What we attempted to do is to make it so we will have a margin that depends on the parent’s width, and goes from <code>0.5em</code> to <code>0px</code>. By subtracting the <code>--min-width</code> variable we can make it go to zero when approaching that min-width.</p>
<p>And it kinda works: when it is narrow, there is no margin, when it is wider — margin appears, but something breaks.</p>
<h2 id="percentage-evaluation">Percentage Evaluation</h2>
<p>The answer to what is happening — why we have the text truncated even though it seems like we should have space available, lies in the <a href="https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution">“Intrinsic Contributions of Percentage-Sized Boxes”</a> section of the <a href="https://drafts.csswg.org/css-sizing-3/">“CSS Box Sizing Module Level 3”</a> spec, specifically the <a href="https://drafts.csswg.org/css-sizing-3/#min-percentage-contribution">paragraph “d.”</a>:</p>
<blockquote>
<p>[…] for margins and paddings (and gutters), a cyclic percentage is resolved against zero for determining intrinsic size contributions.</p>
</blockquote>
<p>Because the button shrunks to its max-content width when it is <code>inline-…</code>, this width is calculated by adding up all the childrens’s contibutions, and for our <code>margin</code> we substitute any <code>%</code> inside with <code>0</code>. So, for calculating this width, the following:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">margin-left</span><span style="color:#E1E4E8">: clamp(</span></span>
<span class="line"><span style="color:#E1E4E8"> 0px,</span></span>
<span class="line"><span style="color:#E1E4E8"> 100% - var(--min-width),</span></span>
<span class="line"><span style="color:#E1E4E8"> 0</span><span style="color:#B392F0">.5em</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span></code></pre>
<p>Can be treated as</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">margin-left</span><span style="color:#E1E4E8">: clamp(</span></span>
<span class="line"><span style="color:#E1E4E8"> 0px,</span></span>
<span class="line"><span style="color:#E1E4E8"> 0px - var(--min-width),</span></span>
<span class="line"><span style="color:#E1E4E8"> 0</span><span style="color:#B392F0">.5em</span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span></code></pre>
<p>And so it will become just <code>0px</code>, so the total width of the whole button will consist of its borders, paddings, text content, and the icon. Plus zero for our margin.</p>
<p>Then, knowing this width, we start to layout everything inside, and according to our formula the <code>margin</code> becomes <code>0.5em</code> as the width is quite large… but that <em>reduces</em> the space available for our text, so it becomes truncated!</p>
<h2 id="the-solution">The Solution?</h2>
<p>To solve this, we can <em>introduce even more percentages</em> but in reverse!</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon with-percentage"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon with-percentage"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.icon.with-percentage</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> margin-left</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> max</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--margin</span><span style="color:#E1E4E8">) </span><span style="color:#FFAB70">-</span><span style="color:#79B8FF"> 100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ,</span></span>
<span class="line"><span style="color:#79B8FF"> 100</span><span style="color:#F97583">%</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--min-width</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ,</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--margin</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Now it works! When wide — without collapsing — the margin is <code>0.5em</code>, when narrow — it is zero.</p>
<p>What we did is replaced the lower boundary of our <code>clamp()</code> with a <code>max()</code> that, when considered in a <em>cyclic percentage context</em> results in <code>0.5em</code>, and otherwise results in <code>0px</code>. Whoa!</p>
<h2 id="except-for-the-safari-bug">…Except for the Safari Bug</h2>
<p>Ooops. That’s what happens when you test out an obscure place in CSS, and check how it behaves in different browsers. Instead of only evaluating the <code>%</code> as zero, Safari just throws the whole calculation away and replaces the whole <em>margin</em> with zero T_T</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">>button</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#85E89D">button</span><span style="color:#F97583"> ></span><span style="color:#85E89D"> span</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> margin</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">calc</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#F97583">%</span><span style="color:#F97583"> +</span><span style="color:#79B8FF"> 50</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Safari renders this example not as you would expect… Of course, I <a href="https://bugs.webkit.org/show_bug.cgi?id=303109">opened a bug</a> about this.</p>
<h2 id="the-working-solution">The Working Solution</h2>
<p>Right after I published this post, I suddenly decided to test what will happen if, instead of a margin, we would use a <code>gap</code>? **It works! **</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-gap"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"with-gap"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.with-gap</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> gap</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">clamp</span><span style="color:#E1E4E8">(</span></span>
<span class="line"><span style="color:#79B8FF"> max</span><span style="color:#E1E4E8">(</span><span style="color:#79B8FF">0</span><span style="color:#F97583">px</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--gap</span><span style="color:#E1E4E8">) </span><span style="color:#FFAB70">-</span><span style="color:#79B8FF"> 100</span><span style="color:#F97583">%</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ,</span></span>
<span class="line"><span style="color:#79B8FF"> 100</span><span style="color:#F97583">%</span><span style="color:#FFAB70"> -</span><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--min-width</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> ,</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--gap</span><span style="color:#E1E4E8">)</span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>So, this is the solution I will recommend: instead of a <code>margin</code>, use a <code>gap</code>, with the rest of our calculations remaining in place: without the negative cyclic percentage condition the button would still collapse, but now the <code>gap</code> works the same in all browsers — likely because it was implemented later than <code>margin</code>. Ooof.</p>
<h2 id="an-alternative-flex-solution">An Alternative Flex Solution</h2>
<p>While I like the solution with the <code>gap</code>, and when Safari will fix the bug with margins/paddings, this technique could be potentially used in non-flex contexts (what about floats?), the next morning after publishing this article, I decided to think of possible alternative solutions.</p>
<p>Thinking about <code>gap</code> and flexbox, I found a solution that was likely one people use to achieve this effect right now: having a shrinking spacer element.</p>
<p><a href="https://blog.kizu.dev/responsive-cyclic-margins/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"spacer"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">p</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"width: var(--min-width)"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">button</span><span style="color:#B392F0"> type</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"button"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"ellipsis"</span><span style="color:#E1E4E8">>Hello, world!</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"spacer"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"icon"</span><span style="color:#E1E4E8">>🌐</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">button</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">p</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.spacer</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.5</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Well, that’s pretty simple! The main con of this solution is that it requires one additional element per gap that you want to make responsive, but there are a few pros as well:</p>
<ul>
<li>Unlike <code>gap</code> and similar to <code>margin</code>, it is possible to style each gap separately.</li>
<li>In previous solution, we had to know the min-width to describe the gap, here we rely on the default <code>flex-shrink</code> behavior.</li>
<li>The shrinking itself is much smoother, and we can control the ratio of how the gap shrinks compared to the other elements by using different values of <code>flex-shrink</code>.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Not always you stumble over a <em>cyclic percentage</em> issues, and not always you can overcome them by exploiting the same substitution to zero with conditional calculations.</p>
<p>I feel this is just a glimpse of what these kinds of calculations could achieve, and I invite you to also try and hack any similar places in the same way. Maybe you’ll stumble over something fun too!</p>
<p>As usual, it is also fun how we can find different solutions for the same problem in CSS, each with its own pros and cons. Similar to what I wrote in <a href="/minimal-reproductions/">“Minimal Reproductions”</a>, knowing what exactly does not work allows you to pursue alternative solutions and find one that works.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115612725378654218">on Mastodon</a>!</p>Conditional JSX in Astrohttps://blog.kizu.dev/conditional-jsx-in-astro/https://blog.kizu.dev/conditional-jsx-in-astro/This is me documenting the way I am handling some of the more complex conditional rendering in Astro’s JSX. Well, not strictly _JSX_ — but its “Component Template” part of `.astro` components and assigning them to variables.Thu, 27 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Will Driving West — Walls</dd><dt>Current drink:</dt><dd>Lemongrass, Ginger & Black Pepper tea</dd></dl><hr /><p>This is me documenting the way I am handling some of the more complex conditional rendering in <a href="https://astro.build/">Astro</a>’s JSX. Well, not strictly <em>JSX</em> — but its “Component Template” part of <code>.astro</code> components and assigning them to variables.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>In React/Preact, inside a <code>.jsx</code>/<code>.tsx</code> it is possible to save snippets of JSX code to variables and then use them conditionally, like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="jsx"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> MyComponent</span><span style="color:#E1E4E8"> ({ linkText, </span><span style="color:#79B8FF">isDiv</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> false</span><span style="color:#E1E4E8"> }) </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#B392F0"> someContent</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"#hello"</span><span style="color:#E1E4E8">>{linkText}</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"wrapper"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {isDiv </span><span style="color:#F97583">?</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> ) </span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> )}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>This example is nonsensical, but you should get an idea: we’re able to define some JSX code in the function body, and then reuse it inside various conditionals in the component’s return.</p>
<p>This is very useful when you have some complex content, but then in different setups it could be rendered in different contexts, or in a different order.</p>
<p>In <a href="https://docs.astro.build/en/basics/astro-components/#component-structure"><code>.astro</code> components</a>, if you’re coming from React or Preact, it is easy to misunderstand the component’s <em>Script</em> part as being the function’s body, and the <em>Template</em> as the return.</p>
<p>But the problem: it is not possible to save snippets of HTML in the <em>Script</em> part! So it can be pretty awkward to work with more complex HTML structures.</p>
<p>If you were to try writing something like this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code style="tab-size: 2;"><span class="line"><span style="color:#6A737D">---</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">linkText</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">isDiv</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> false</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> Astro.props;</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#B392F0"> someContent</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#F97583"> <</span><span style="color:#E1E4E8">a href</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"#hello"</span><span style="color:#F97583">></span><span style="color:#E1E4E8">{linkText}</span><span style="color:#F97583"></</span><span style="color:#E1E4E8">a</span><span style="color:#F97583">></span></span>
<span class="line"><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#6A737D">---</span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"wrapper"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {isDiv </span><span style="color:#F97583">?</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> ) </span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> )}</span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>You would get an error:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="log"><code style="tab-size: 2;"><span class="line"><span style="color:#9ECBFF">[ERROR]</span><span style="color:#E1E4E8"> Unexpected </span><span style="color:#9ECBFF">";"</span></span></code></pre>
<h2 id="the-solution">The Solution</h2>
<p>The solution for this that I found: good old <a href="https://developer.mozilla.org/en-US/docs/Glossary/IIFE">IIFE</a>, or “Immediately Invoked Function Expressions”.</p>
<p>Astro allows <em>JavaScript Expressions</em> inside the <em>Temlpate</em> part. Those are usually there for conditions, maps, and so on. And — they support HTML inside, so you could do things like <code>{list.map (item => <li>{item}</li>)}</code> that you could be used to.</p>
<p>But that means that nothing stops us from doing this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="astro"><code style="tab-size: 2;"><span class="line"><span style="color:#6A737D">---</span></span>
<span class="line"><span style="color:#F97583">const</span><span style="color:#E1E4E8"> { </span><span style="color:#79B8FF">linkText</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">isDiv</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> false</span><span style="color:#E1E4E8"> } </span><span style="color:#F97583">=</span><span style="color:#E1E4E8"> Astro.props;</span></span>
<span class="line"><span style="color:#6A737D">---</span></span>
<span class="line"><span style="color:#E1E4E8">{(() </span><span style="color:#F97583">=></span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#F97583"> const</span><span style="color:#B392F0"> someContent</span><span style="color:#F97583"> =</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"#hello"</span><span style="color:#E1E4E8">>{linkText}</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#F97583"> return</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"wrapper"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {isDiv </span><span style="color:#F97583">?</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> ) </span><span style="color:#F97583">:</span><span style="color:#E1E4E8"> (</span></span>
<span class="line"><span style="color:#E1E4E8"> <</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#F97583">=</span><span style="color:#9ECBFF">"inner"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> {someContent}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> )}</span></span>
<span class="line"><span style="color:#E1E4E8"> </</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"> );</span></span>
<span class="line"><span style="color:#E1E4E8">})()}</span></span></code></pre>
<p>This works! The HTML is correctly parsed and assigned to the <code>someContent</code> variable, which then can be reused as you wish.</p>
<p>A good way to think about it if you’re approaching to this from React/Preact mindset:</p>
<ul>
<li>
<p>Treat the <code>Script</code> part as the <em>outside</em> of your component’s function body. All the imports, helper functions, and static calculations could go there.</p>
</li>
<li>
<p>The function body of IIFE is now the place where you could define any reusable snippets of JSX. Nice.</p>
</li>
<li>
<p>Its return is what will be rendered. That means that you could also benefit from early returns, and simplify your conditions!</p>
</li>
<li>
<p>You could even put the <code>Astro.props</code> as the argument of that IIFE, and then destructure props as if you were authoring a React component… But why?</p>
</li>
</ul>
<h2 id="offtopic-upgrading-astro">Offtopic: Upgrading Astro</h2>
<p>I love that Astro is prebuilt statically by default, so all this logic will exist only before build, and the final HTML will be clean and nice.</p>
<p>Before writing this post, I upgraded Astro from <code>4.14.4</code> to <code>5.16.2</code> and did not encounter almost any problems… Or so I wrote initially, only to find out I couldn’t publish my blog, even though <code>npm run dev</code> worked perfectly.</p>
<p>There were a few issues:</p>
<h3 id="random-lightningcss-warnings">Random LightningCSS Warnings</h3>
<p>I noticed that when running <code>npm run dev</code> I got the following warnings from LightningCSS:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="log"><code style="tab-size: 2;"><span class="line"><span style="color:#FDAEB7">[WARN]</span><span style="color:#E1E4E8"> [vite] [vite:css][lightningcss] …</span></span></code></pre>
<p>Solution: I suppressed them by passing <code>logLevel: 'error'</code> to <code>vite</code> inside <code>astro.config.mjs</code>.</p>
<h3 id="nodejs-version-requirement">Node.js Version Requirement</h3>
<p>I use Netlify, and apparently it runs an older version of Node.js by default, and Astro 5 stopped supporting it.</p>
<p>Solution: add a supported node version via <code>.nvmrc</code>.</p>
<h3 id="highlightercodetohtml-is-not-a-function"><code>highlighter.codeToHtml is not a function</code></h3>
<p>Ooof, this one was a hard one! I found one post that mentioned this issue: <a href="https://www.danielcorin.com/til/astro/code-toggle-component/">“Astro Code Toggle Component”</a> by <a href="https://www.danielcorin.com/">Daniel Corin</a>, but there the author did not debug what exactly is going on, stopping at noticing that the issue was in the Astro’s Code component, and reimplementing the highlighter on their own.</p>
<p>Debugging it myself, and logging what’s going on, I noticed that the <code>highlighter</code> in question had a different method available, which worked. The types did complain — and this seemed like an issue of something in dependencies.</p>
<p>Looking at my <code>package-lock.json</code> I found that the library that should provide that <code>highlighter</code> was <code>@astrojs/markdown-remark</code>, and it was not on the latest version. Trying to force the latest version in my <code>package.json</code> shown the reason why it wasn’t the latest: another package — <a href="https://github.com/astro-community/md"><code>@astropub/md</code></a> by <a href="https://jonneal.dev/">Jonathan Neal</a> had an earlier <code>@astrojs/markdown-remark</code> version as its peer dependency!</p>
<p>The solution: override the dependency specifically for <code>@astropub/md</code> in my <code>package.json</code> while adding a newer version by default:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="json"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#79B8FF"> "dependencies"</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF"> "@astrojs/markdown-remark"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"^6.3.9"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#79B8FF"> "overrides"</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF"> "@astropub/md"</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#79B8FF"> "@astrojs/markdown-remark"</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"5.3.0"</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>Oof, this worked! Ideally, I guess, it might be time to remove the <code>@astropub/md</code> — I only use it to render markdown for RSS, and I think there is now a better way to do it through Astro, so maybe one day (when my solution stops working?) I’ll return to this.</p>
<p>Ah, and I had to add <code>--legacy-peer-deps</code> to the <code>NPM_FLAGS</code> environmental variable in Netlify to make it run <code>npm install --legacy-peer-deps</code> as otherwise it was erroring out.</p>
<h2 id="thats-it">That’s It</h2>
<p>I also looked at my other dependencies, noticed that there was Preact, which I experimented for a while years ago, and decided to remove it and its Astro integration as well — after all, I did not end up using it for anything.</p>
<p>I hope that this post will help you if you’re working with Astro, and, like me, is unfortunate to come to it with React preconceptions. Although, even if not, I think this IIFE pattern inside Astro templates is still fun!</p>
<p>And — debugging the build issues took much longer than I wanted, and three times as long as it took writing the rest of this post. Oh hey, it is modern front-end for you.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115624098241233770">on Mastodon</a>!</p>Bolder Linkshttps://blog.kizu.dev/bolder-links/https://blog.kizu.dev/bolder-links/This is another post about a small design tweak that I made around two years ago to both my blog and main website. I never shared it, because, well, it feels very small. But I liked it a lot, and I don’t think I could ever come back, so why not write about it? I wonder if you ever, while visiting my websites, noticed this tiny aspect of it?Fri, 28 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Steve Pardo — Wave Dancer</dd><dt>Current drink:</dt><dd>Thyme, rosemary & lemon infusion</dd></dl><hr /><style>{`
h1 {
font-size: 3rem;
}
`}</style>
<p>This is another post about a small design tweak that I made around two years ago to both my blog and <a href="https://kizu.dev/">main website</a>. I never shared it, because, well, it feels very small. But I liked it a lot, and I don’t think I could ever come back, so why not write about it?</p>
<p>The tweak is, you’ve guessed — make the <code>font-weight</code> of most links on my website <strong>bolder</strong>. That’s it, that is the crux of the change.</p>
<p><a href="https://blog.kizu.dev/bolder-links/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">ul</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"margin:0"</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"./#test2"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"font-weight: unset"</span><span style="color:#E1E4E8">>This is a regular normal link</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">>, alongside some text.</</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"./#test"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"font-weight: 600"</span><span style="color:#E1E4E8">>This is a nice, slightly bolder link</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">>, alongside some text.</</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"./#test2"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"font-weight: bold"</span><span style="color:#E1E4E8">>Regular bold link</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">>, alongside some text.</</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">><</span><span style="color:#85E89D">a</span><span style="color:#B392F0"> href</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"./#test2"</span><span style="color:#B392F0"> style</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"font-weight: 900"</span><span style="color:#E1E4E8">>This one maybe too bold</</span><span style="color:#85E89D">a</span><span style="color:#E1E4E8">>, alongside some text.</</span><span style="color:#85E89D">li</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">ul</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>I chose the <code>600</code> weight for my blog — slightly less than the default <code>700</code> for the <code>bold</code> keyword. And, for sure, not the <em>boldest</em> <code>900</code>.</p>
<p>The small bump in weight gives links a tiny buff in contrast, while not making them stand out too much. One of the reasons I wanted to give them that bump in contrast is because I carefully chose the text color for both regular and visited links.</p>
<p>I wanted to keep a more vivid hue while not making it too dull, at the same time keeping enough contrast with both the page background, and the surrounding text. Even though I have underlines on my links, I dim them slightly, and having an extra affordance feels good in addition.</p>
<aside>
I already wrote about how I do the dotted underlines for some pseudo-links in the [“Styles For Secondary Interactive Elements”](/styles-for-secondary-interactive-elements/) post, and I already mentioned that I want to write about the way I do underlines in general… I am still planning to do so, but let me talk about weight first, haha.
</aside>
<p>As I already mentioned, I kept this style for at least two years now, and I don’t think I would go back. I got used to it, and I like having this small barely noticeable tweak present in my blog and site’s designs.</p>
<p>I wonder if you ever, while visiting my websites, noticed this tiny aspect of it?</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115629682160945790">on Mastodon</a>!</p>Build Bridgeshttps://blog.kizu.dev/build-bridges/https://blog.kizu.dev/build-bridges/This is a very quick shout-out to the Bridgy Fed project by Ryan Barrett. If you know people who are only present on one of the networks and are not bridging their accounts — nudge them to do so!Sat, 29 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>36 — Inside (2:56AM Mix)</dd><dt>Current drink:</dt><dd>Lemongrass, Ginger & Black Pepper tea</dd></dl><hr /><style>{`
h1 {
font-size: 3rem;
}
`}</style>
<p>This is a very quick shout-out to the <a href="https://fed.brid.gy/">Bridgy Fed</a> project by <a href="https://snarfed.org/">Ryan Barrett</a>.</p>
<p>Its goal is to connect people across otherwise unrelated federated network: <a href="https://en.wikipedia.org/wiki/Fediverse">Fediverse</a>, <a href="https://bsky.social/about">Bluesky</a>, and even <a href="https://indieweb.org/">IndieWeb</a> sites.</p>
<p>After the exodus from more corporate and capitalist networks, people ended up in different parts of the web. Each segment could be well-connected inside, but if you want to participate <em>everywhere</em> where people are now, you often need to create and maintain multiple accounts.</p>
<p>I often see people reposting the same thing in multiple places — which is fine, but not everyone has the spoons to do so. Not everyone is also ready to create an account in a network they do not understand or do not like.</p>
<p>That’s where Bridgy can really help: it is the <em>easiest</em> and most straightforward way to connect your account to other networks.</p>
<ul>
<li>
<p>If you’re on Mastodon or elsewhere in the Fediverse and want to make it possible for people from Bluesky to follow you, you can either <a href="https://fed.brid.gy/login">log in with your account here</a> or just follow the <code>@[email protected]</code> account from your client (you can use search to find it there via its handle).</p>
</li>
<li>
<p>If you’re on Bluesky, and want to make it possible for people on Mastodon and the Fediverse at large to follow you, you can either <a href="https://fed.brid.gy/login">log in with your account here</a>, or just follow <a href="https://bsky.app/profile/ap.brid.gy">@ap.brid.gy</a> from Bluesky.</p>
</li>
</ul>
<p>That’s it. Bridgy works as opt-in — nothing is bridged without your consent, and by default it will only bridge your public posts.</p>
<p>Here is, for example, <a href="https://bsky.app/profile/kizu.front-end.social.ap.brid.gy">my bridged account on Bluesky</a>, where the posts from <a href="https://front-end.social/@kizu">my Mastodon profile</a> go automatically.</p>
<p>And here is <a href="https://bsky.app/profile/did:plc:jz4h5jq5ksajcp5ysqp6id5z">my bridged Pixey (Pixelfed instance) account</a> where the photos from <a href="https://pixey.org/kizu">my Pixey gallery</a> go.</p>
<p>Bridgy even handles replies, DMs, and more. It is zero maintenance, and there is zero reason not to use it.</p>
<p>If you know people who are only present on one of the networks and are not bridging their accounts — nudge them to do so!</p>
<p>The more interconnected our web is, the more powerful it is. I find it awesome that vastly different networks can talk to each other thanks to projects like that.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115635420381963409">on Mastodon</a>!</p>Third Complete Novemberhttps://blog.kizu.dev/third-complete-november/https://blog.kizu.dev/third-complete-november/For the third time, third year in a row, I managed to write a post for every day of November. I was tired at the end, and postponed writing many posts until the end of the day, but it felt easier than the last two previous years.Sun, 30 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Balún — Camila</dd><dt>Current drink:</dt><dd>White tea with peppermint</dd></dl><hr /><p>For the third time, third year in a row, I managed to write a post for every day of November.</p>
<p>I was tired at the end, and postponed writing many posts until the end of the day, but it felt easier than the last two previous years.</p>
<p>The hardest part was: I decided not to post about CSS or frontend on weekends, and I ended up with more notes for what to write about CSS, and couldn’t find many topics for non-CSS posts.</p>
<p>However, I still did write some CSS on weekends.</p>
<p>Anyways, I don’t think the quality of the posts was that good, but it is <em>better than nothing</em>, right? The necessity to write posts was nice as a way to push myself to actually publish stuff.</p>
<p>I won’t go through all the posts that I wrote about CSS, but will recommend you check out these three if you missed them:</p>
<ul>
<li>
<p><a href="/fixing-baselines/">“Fixing Baselines”</a> — a small technique that I used for a very long time, and finally found an opportunity to write about.</p>
</li>
<li>
<p><a href="/inline-custom-identifiers/">“Inline Custom Identifiers”</a> — a post about an approach to naming things and connecting them to other elements that require unique identifiers in CSS via inline custom properties.</p>
</li>
<li>
<p><a href="/anchoring-to-a-containing-block/">“Anchoring to a Containing Block”</a> — the way to fix a very common anchor positioning issue that I stumble over and over again.</p>
</li>
</ul>
<p>I also wrote a few posts about some of the design tweaks I ended up using for my blog and website through the iteration over the years:</p>
<ul>
<li>
<p><a href="/uneven-inline-paddings/">“Uneven Inline Paddings”</a> — usually a not noticeable thing to visually balance the left-ragged text.</p>
</li>
<li>
<p><a href="/styles-for-secondary-interactive-elements/">“Styles For Secondary Interactive Elements”</a> — a more noticeable thing, which I don’t see people using often.</p>
</li>
<li>
<p><a href="/bolder-links/">“Bolder Links”</a> — a more subtle thing I do for around two years.</p>
</li>
</ul>
<p>There are more posts that I could write about, but I think I’ll stop. Usually, in these last few years, I do a roundup of things I did for the whole year, and I will likely write about some of them there.</p>
<p>The best part: I have more notes about CSS than I could write about. Many of those topics were a tiny bit too big for a quick daily post, so I hope I will manage to start writing and publishing them over time.</p>
<p>And there is also one big article that I started writing, but did not manage to finish, partially because some of my time was dedicated to those daily posts. But — I for sure want to finish and publish this article in December. It should be a pretty good one, I think.</p>
<p>See you next month.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115640997876309687">on Mastodon</a>!</p>My 2025 in CSShttps://blog.kizu.dev/my-2025-in-css/https://blog.kizu.dev/my-2025-in-css/For me, 2025 was a much less productive year than 2024. A mix of industry and world frustrations, personal issues, and just certain people being mean — all of that made me live on borrowed spoons for most of the year. This post won’t have any of that, of course, but will contain a roundup of everything I wrote about CSS, so if you missed something — it is a good way to catch up!Wed, 31 Dec 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Every Gentle Air — Under Water, Under Ice</dd><dt>Current drink:</dt><dd>Yunnan tea</dd></dl><hr /><style>{`
h1 {
font-size: 2.75rem;
}
`}</style>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="intro">Intro</h2>
<p>For me, 2025 was a much less productive year than <a href="/my-2024-in-css/">2024</a> and <a href="/my-2023-in-css/">2023</a>. A mix of industry and world frustrations, personal issues, and just certain people being mean — all of that made me live on borrowed spoons for most of the year.</p>
<p>Oh well! I am not sure if I will recover fully in 2026, but I’ll try to do what I can. And it is not like 2025 was without its bright sides.</p>
<p>This post is a roundup of everything I wrote about CSS, so if you missed something — it is a good way to catch up!</p>
<h2 id="my-articles-and-techniques">My Articles and Techniques</h2>
<style>{`
p.starts-with-tag:has(> a.has-left-overhang.has-right-overhang:only-child) {
text-wrap: balance;
}
`}</style>
<p>Compared to the six articles I published in 2024, I managed to get out only two new ones — both at the beginning of the year. That said, I really like how both of them ended up, and if you missed them — I recommend finding time and reading them. You will likely need a lot of time — my articles do not become shorter — but, I promise, even beyond their premise, they contain many curiosities that I did not see anyone talk about.</p>
<ul>
<li>
<p><a href="https://kizu.dev/preview-mixin/">“Pure CSS Mixin for Displaying Values of Custom Properties”</a></p>
<p><em>January 27.</em> This was one of the most complex things I did. Even though it is not strictly practical, I still find myself using it while working on my experiments. It works! While it is based on my 2024’s <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a> technique, there are many other small things to learn from the way I wrote this mixin.</p>
</li>
<li>
<p><a href="https://kizu.dev/svg-linked-parameters-workaround/">“Passing Data into SVG: Linked Parameters Workaround”</a></p>
<p><em>March 24.</em> In some way, this article was twelve years in the making. This is a topic that is still not solved in the Web Platform, and while there is a spec for it, no browser implemented it yet. There are many moving parts and approaches that I describe in this article. While the overall experimental technique is far from being practical, some of those details can be applied wider.</p>
</li>
</ul>
<h2 id="some-of-my-blog-posts">Some of My Blog Posts</h2>
<p>I was unable to return to posting <a href="/tags/bookmarks/">bookmarks</a>, so I wrote fewer posts than in 2024. I still managed to do the whole November challenge, where I wrote one post every day for the whole month, making it the third year I completed it. I find this challenge pretty useful, as it allows getting out some of the things I could not find an opportunity to write about otherwise — especially this time, I managed to share many small but impactful things.</p>
<p>Here are some of these posts that I recommend you to read:</p>
<ul>
<li>
<p><a href="/future-proofing-indirect-cyclic-conditions/">“Future-Proofing Indirect Cyclic Conditions”</a></p>
<p><em>May 31.</em> This is a follow-up to my <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions”</a> article that I already mentioned, in which I had to find a way to fix it to work with the changes in the spec and implementation that broke my technique.</p>
</li>
<li>
<p><a href="/functional-capturing/">“Functional Capturing”</a></p>
<p><em>June 3.</em> This is also a follow-up, now to my <a href="/captured-custom-properties/">“Captured Custom Properties”</a> post, but now looking at how we could use custom functions in CSS to achieve a similar capturing behavior.</p>
</li>
<li>
<p><a href="/inline-custom-identifiers/">“Inline Custom Identifiers”</a></p>
<p><em>November 3.</em> A post in which I name and share a pattern I used for a few years. I continue using it, and highly recommend look at it if you’re planning to work with scroll-driven animations, anchor positioning, and other newer CSS features that require unique identifiers.</p>
</li>
<li>
<p><a href="/renaming-outer-variables-in-functions/">“Renaming Outer Variables in CSS Functions”</a></p>
<p><em>November 4.</em> A post about hidden mini-feature of custom functions. It might not be something very useful in practice, but as we start to experiment with custom functions and mixins more, I believe this will find its use.</p>
</li>
<li>
<p><a href="/zombie-styles/">“Zombie Styles”</a></p>
<p><em>November 5</em>. A post that names a problem that happens occasionally with CSS, especially when complex build steps are involved.</p>
</li>
<li>
<p><a href="/box-decoration-break/">“Box-Decoration-Break”</a></p>
<p><em>November 6</em>. A post reminding about a not very common CSS property which is yet to become baseline in theory, but which can be already used for many use cases alongside its <code>-webkit-</code> prefixed version.</p>
</li>
<li>
<p><a href="/fixing-baselines/">“Fixing Baselines”</a></p>
<p><em>November 7</em>. This one could’ve been an article on my main site, potentially. While the technique itself is not novel, I did not see many people write about it, and I find it returning to it year over year.</p>
</li>
<li>
<p><a href="/uneven-inline-paddings/">“Uneven Inline Paddings”</a></p>
<p><em>November 10</em>. While I can’t say I am good at design, over the years I gathered a few barely noticeable design tweaks that, I thought, are worthy to be shared. This is one of them.</p>
</li>
<li>
<p><a href="/named-container-presence-check/">“Named Container Presence Check”</a></p>
<p><em>November 11</em>. A post about how we can check for the presence of some named containers today, while the corresponding native CSS feature for this is not yet available in all browsers.</p>
</li>
<li>
<p><a href="/responsive-tab-size/">“Responsive tab-size”</a></p>
<p><em>November 12</em>. A fun way to use typed arithmetic for making the <code>tab-size</code> property be responsive to some container’s width.</p>
</li>
<li>
<p><a href="/styles-for-secondary-interactive-elements/">“Styles For Secondary Interactive Elements”</a></p>
<p><em>November 13</em>. Another design tweak, one that I also use for a while, and recommend you to try as well.</p>
</li>
<li>
<p><a href="/whitespace-in-code/">“Whitespace in Code”</a></p>
<p><em>November 17</em>. A very short post about a small tip for improving the formatting of your code.</p>
</li>
<li>
<p><a href="/anchoring-to-a-containing-block/">“Anchoring to a Containing Block”</a></p>
<p><em>November 19</em>. A post about one anchor positioning gotcha, where it is not possible to anchor an element to its <em>containing block</em> with absolute positioning, and a workaround that involves fixed positioning and <code>anchor-scope</code>.</p>
</li>
<li>
<p><a href="/scope-for-examples/">“Scope for Examples”</a></p>
<p><em>November 20</em>. A short post about an <code>@scope</code> use case that I expect will be very popular, especially in blogs of those who write about CSS, as it simplifies creating examples for articles <em>a lot</em>!</p>
</li>
<li>
<p><a href="/play-with-inherit-function/">“Play With Inherit Function”</a></p>
<p><em>November 24</em>. A post about how <code>inherit()</code> function is now available for testing in Chrome Canary. I expect this function to be tremendously useful once it is in all browsers, as it unlocks some of the API designs and ways to write code that were not possible without <a href="https://kizu.dev/self-modifying-variables/">complex hacks</a> before.</p>
</li>
<li>
<p><a href="/responsive-cyclic-margins/">“Responsive Cyclic Margins”</a></p>
<p><em>November 25</em>. A post about a few ways of making some margins or gaps collapsible to zero without compromising the <code>max-content</code> dimension of the element they’re used in.</p>
</li>
<li>
<p><a href="/border-2px-double/">“Border: 2px double”</a></p>
<p><em>November 26</em>. A tiny “fun fact” about how <code>2px double</code> borders are rendered. No interop in sight.</p>
</li>
<li>
<p><a href="/bolder-links/">“Bolder Links”</a></p>
<p><em>November 28</em>. Last design tweak I shared this year for increasing the contrast of links compared to the body text style.</p>
</li>
</ul>
<h2 id="css-working-group">CSS Working Group</h2>
<p>A big part of my involvement with CSSWG this year was thinking about potential standardisation of the “fit to width” technique.</p>
<p>After my 2024’s article <a href="/fit-to-width/">“Fit-to-Width Text: A New Technique”</a>, in April of this year <a href="https://github.com/w3c/csswg-drafts/issues/2528#issuecomment-2769621512">it was resolved</a> to start working on a native CSS feature for it.</p>
<p>There was a lot of valuable feedback from the community, as well as a Google Chrome team’s explainer and experimental implementation, which were followed by more discussions and issues, some of which are still ongoing.</p>
<p>I wrote two blog posts about some of that:</p>
<ul>
<li>
<p><a href="/fit-to-width-discussions-and-feedback/">“Fit-to-Width Discussions & Feedback”</a></p>
<p><em>May 1</em>. A post with my critique of Google’s explainer and a proposal for fixing one of the accessibility issues.</p>
</li>
<li>
<p><a href="/text-fit-update/">“Fit-to-Width Status Update: Prototype and Issues”</a></p>
<p><em>October 2</em>. A post with the status update and a list of new CSSWG issues I opened that are related to “fit to width”.</p>
</li>
</ul>
<p>Aside from the above work, I opened a few new CSSWG issues about an array of topics.</p>
<ul>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/11741">“[css-values-5] typeof() or something similar to be used inside if() conditionals to check types of custom properties”</a></p>
<p><em>February 19</em>. In some way, a follow-up to my <a href="https://kizu.dev/preview-mixin/">“Pure CSS Mixin for Displaying Values of Custom Properties”</a> article, in which I did many hacks for trying to understand the type of some custom property.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/11798">“[css-scoping] Scoping of functions, other name-defining at-rules and custom idents”</a></p>
<p><em>February 27</em>. I consider global scoping of idents in CSS to be one of the last issues that require external tooling. While this issue started from an attempt to use <code>@scope</code> for this, a more likely direction would be to use a dedicated lexical scoping at-rule, maybe even reuse the <code>@namespace</code>.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/12604">“[css-contain-3] Container Variables”</a></p>
<p><em>August 13</em>. We have an ability to name containers with the <code>container-name</code> property. We have an ability to query custom properties from such named containers. But what if we had an ability to <em>use</em> the values of such custom properties directly with something like <code>container-var()</code>?</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/12631">“[css-mixins-1] Expose environmental variables inside apply’s contents block”</a></p>
<p><em>August 20</em>. There is currently a lot of work dedicated to native CSS mixins. This issue is about one of their aspects for usage, with passing rules inside mixins when calling them.</p>
</li>
<li>
<p><a href="https://github.com/w3c/csswg-drafts/issues/13080">“[css-inline-3] A property to exclude an element from the baseline calculation”</a></p>
<p><em>November 7</em>. There are currently only indirect ways of adjusting the baseline participation of some element. As a part of writing my <a href="/fixing-baselines/">“Fixing Baselines”</a> post, I opened this issue with a proposal to add a built-in way of handling this.</p>
</li>
</ul>
<p>Aside from these, I participated in some other issues and discussions, and some of my older issues were resolved in CSSWG meetings.</p>
<h2 id="my-browser-bug-reports">My Browser Bug Reports</h2>
<p>With this year not being as productive, there were not as many opportunities to stumble upon bugs. And, in the same way I had fewer spoons for actual experiments, I was unable to find them to report the issues I encountered.</p>
<p>That said, a fun fact: with fifteen bugs reported, they were distributed equally among all browser engines.</p>
<ul>
<li><a href="https://issues.chromium.org/issues?q=reporter:[email protected]%20created:2025-01-01..2025-12-31">5 Chrome bugs</a> (<a href="https://issues.chromium.org/issues?q=reporter:[email protected]%20created:2024-01-01..2024-12-31">13 in 2024</a>)</li>
<li><a href="https://bugzilla.mozilla.org/buglist.cgi?emailreporter1=1&email1=kizmarh%40gmail.com&chfieldfrom=2025-01-01&chfieldto=2025-12-31&chfield=%5BBug%20creation%5D&emailtype1=substring">5 Firefox bugs</a> (<a href="https://bugzilla.mozilla.org/buglist.cgi?emailreporter1=1&email1=kizmarh%40gmail.com&chfieldfrom=2024-01-01&chfieldto=2024-12-31&chfield=%5BBug%20creation%5D&emailtype1=substring&list_id=17371297">8 in 2024</a>)</li>
<li><a href="https://bugs.webkit.org/buglist.cgi?email1=kizmarh%40ya.ru&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&list_id=11875877&chfieldfrom=2025-01-01&chfieldto=2025-12-31&chfield=%5BBug%20creation%5D">5 Safari bugs</a> (<a href="https://bugs.webkit.org/buglist.cgi?chfield=%5BBug%20creation%5D&chfieldfrom=2024-01-01&chfieldto=2024-12-31&email1=kizmarh%40ya.ru&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&list_id=11875877">6 in 2024</a>)</li>
</ul>
<h2 id="plans-for-2026">Plans for 2026</h2>
<p>Since November, I am actively working on a new proper article for my website. It takes a while, mostly due to the necessity to come up with good examples, but I hope the result will be worth it.</p>
<p>I also have material for another big article, though it will likely need a bit more research.</p>
<p>It becomes harder and harder to find “unsolvable” problems and hack the solutions to them, but hey, you never know what you will stumble upon.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115815774115686213">on Mastodon</a>!</p>Fixing Obsidian’s Markdown Display with CSShttps://blog.kizu.dev/fixing-obsidians-markdown-display-with-css/https://blog.kizu.dev/fixing-obsidians-markdown-display-with-css/I am sharing a CSS snippet I wrote for Obsidian, which makes the default Markdown display better for me by always showing the corresponding formatting symbols.Sun, 16 Jul 2023 00:00:00 GMT<dl><dt>Current music:</dt><dd>The Album Leaf — Pinky’s Storage</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="introduction">Introduction</h2>
<p>In my previous blog post — <a href="/apps-with-presence-on-mastodon/">“Apps with Presence on Mastodon”</a> — I did write about what ended up being the decisive feature leading to me starting to use <a href="https://obsidian.md/">Obsidian</a>:</p>
<blockquote>
<p>I knew that it was possible to create plugins for Obsidian, but only now has it clicked for me that it is based on the web platform: plugins can be written with JS and everything can be styled with CSS, with CSS snippets being a thing that people actively share.</p>
</blockquote>
<p>In this post, I will describe how I managed to already start using this to fix the first problem I encountered.</p>
<h2 id="the-problem">The Problem</h2>
<p>The default Obsidian’s display mode is implemented in a way that hides the Markdown syntax unless you’re editing the corresponding lines.</p>
<p><a href="https://blog.kizu.dev/fixing-obsidians-markdown-display-with-css/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>In the video above, we can see how when we move the caret in this mode, things jump, like <code>em</code> becoming <code>_em_</code> when we focus on it. And the source code for the images or other embeds makes things jump vertically.</p>
<p>Personally, I find this to be a poor experience, with this jumping getting in my way. Additionally, it can be very hard to edit the links, as the only clickable part of them is the actual link. If I used the “Source Mode” this won’t be a problem, but I like the expanded embeds, so I went to see if I could make things better.</p>
<h2 id="the-solution">The Solution</h2>
<p>I did not find any <a href="https://help.obsidian.md/Extending+Obsidian/Community+plugins">community plugins</a> or pre-made <a href="https://help.obsidian.md/Extending+Obsidian/CSS+snippets">CSS snippets</a> that would fix this (let me know if there is something like this already!), so I decided to throw some CSS at the problem.</p>
<p>Obsidian’s ability to add CSS overrides is <strong>the</strong> feature that sold me on it, so it is time for me to start using it. With Obsidian being an electron app, it is very easy to develop for it: I just pressed <kbd>CMD+Shift+I</kbd> and got to the Chromium DevTools. Then, in the options, at the bottom of the “Appearance” tab, there is a “CSS Snippets” field, which allows us to add any CSS overrides there.</p>
<p>Here is how it looks with my CSS snippet being applied:</p>
<p><a href="https://blog.kizu.dev/fixing-obsidians-markdown-display-with-css/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>I did end up leaving the full URL of a link hidden, resulting in a jump, but at least now, only the later part of it is changing, with the start part of the link code always being there.</p>
<p>There are other benefits that I found due to this change:</p>
<ol>
<li>
<p>I can now easily edit the links by clicking on their code part; a click on it goes into editing them instead of going through the link. Very handy!</p>
</li>
<li>
<p>It is now easier to distinguish between external and internal links; internal ones would get wrapped with <code>[[]]</code>, and there could be other cases where the more explicit, visible Markdown code would help.</p>
</li>
</ol>
<p>Here is the code that I ended up writing (for now):</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">:root</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --_fmd-opacity</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">0.2</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.cm-link</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">.cm-hmd-internal-link</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">.cm-em</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">.cm-strong</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">.cm-inline-code</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#B392F0">.cm-header</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(.cm-formatting, &.cm-formatting + &) {</span></span>
<span class="line"><span style="color:#E1E4E8"> &::before {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#79B8FF"> var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-pseudo</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF"> opacity</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-opacity</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> &</span><span style="color:#B392F0">::after</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-after</span><span style="color:#E1E4E8">, </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-pseudo</span><span style="color:#E1E4E8">));</span></span>
<span class="line"><span style="color:#79B8FF"> opacity</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-opacity</span><span style="color:#E1E4E8">);</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.cm-header-1</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"# "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-header-2</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"## "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-header-3</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"### "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-header-4</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"#### "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-header-5</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"##### "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-header-6</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"###### "</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-em</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-pseudo</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"_"</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-strong</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-pseudo</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"**"</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0">.cm-inline-code</span><span style="color:#E1E4E8"> { </span><span style="color:#FFAB70">--_fmd-pseudo</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"`"</span><span style="color:#E1E4E8"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.cm-link</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#FFAB70"> --_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"["</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --_fmd-after</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"](…)"</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.cm-hmd-internal-link</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(</span></span>
<span class="line"><span style="color:#E1E4E8"> .cm-hmd-embed,</span></span>
<span class="line"><span style="color:#E1E4E8"> .cm-link-alias-pipe,</span></span>
<span class="line"><span style="color:#E1E4E8"> .cm-link-alias-pipe + &,</span></span>
<span class="line"><span style="color:#E1E4E8"> .cm-formatting-link + &</span></span>
<span class="line"><span style="color:#E1E4E8"> ) {</span></span>
<span class="line"><span style="color:#FFAB70"> --_fmd-before</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"[["</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#FFAB70"> --_fmd-after</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"]]"</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#B392F0">.internal-embed</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#E1E4E8"> &:not(</span></span>
<span class="line"><span style="color:#E1E4E8"> .cm-line:has(.cm-hmd-internal-link) + &,</span></span>
<span class="line"><span style="color:#E1E4E8"> .</span><span style="color:#79B8FF">cm-formatting-link-end</span><span style="color:#E1E4E8"> + * + &</span></span>
<span class="line"><span style="color:#E1E4E8"> )::before {</span></span>
<span class="line"><span style="color:#79B8FF"> content</span><span style="color:#E1E4E8">: </span><span style="color:#9ECBFF">"![["</span><span style="color:#79B8FF"> attr</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">src</span><span style="color:#E1E4E8">) </span><span style="color:#9ECBFF">"]]"</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> opacity</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">var</span><span style="color:#E1E4E8">(</span><span style="color:#FFAB70">--_fmd-opacity</span><span style="color:#E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#B392F0"> .cm-line</span><span style="color:#F97583"> +</span><span style="color:#E1E4E8"> &</span><span style="color:#B392F0">::before</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> display</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">block</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>I probably have not covered all the cases yet. I’ll try to update this when I encounter other places that would require fixing, but I’m pretty happy with how it works.</p>
<h2 id="how-it-works">How It Works</h2>
<p>A few notes on that CSS I did write:</p>
<ul>
<li>
<p>Because Obsidian is using Chromium v112 at the moment, it comes with support for native <a href="https://www.w3.org/TR/css-nesting-1/">CSS nesting</a>, allowing me to just go and use it.</p>
<p>As I’m writing this CSS only for Obsidian, I don’t need to care about cross-browser compatibility: Obsidian can use anything present from Chrome v112 at the moment.</p>
</li>
<li>
<p>As I’m writing this CSS only for Obsidian, I don’t need to care about cross-browser compatibility. In one place, I used <a href="https://drafts.csswg.org/selectors/#relational"><code>:has()</code></a>, which is not yet available in Firefox.</p>
<p>I expect Obsidian to be a very nice practical playground for some of my wild <a href="https://kizu.dev/tags/experiment/">CSS experiments</a> (though I’ll need to wait until the newer features like <a href="https://kizu.dev/scroll-driven-animations/">scroll-driven animations</a> and <a href="https://kizu.dev/anchor-positioning-experiments/">anchor positioning</a> first land in Chrome, and then that version will land in Obsidian).</p>
</li>
<li>
<p>I’m using <a href="https://drafts.csswg.org/css-variables/#defining-variables">CSS custom properties</a> to make the code leaner: defining them for all elements I would style at once and then assigning the variables I need for the specific elements. This allows me to not duplicate the complicated selector for each of the elements.</p>
<p>Important note: this relies on the way Obsidian renders Markdown, and the actual selector after expanding the nesting is not ideal in a lot of senses — I would not use it in a production site, but it works perfectly fine. For now.</p>
</li>
<li>
<p>Some features require a bit more complicated code, like the embeds, but otherwise, most of the things are handled similarly: we just “restore” the Markdown syntax by placing the <code>::before</code> and <code>::after</code> pseudo-elements in the correct places at the right conditions.</p>
</li>
</ul>
<h2 id="limitations">Limitations</h2>
<p>Sadly, with the way Markdown is rendered in Obsidian, some cases are not covered by my CSS snippet. Simple example:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="md"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8;font-weight:bold">**</span><span style="color:#E1E4E8;font-style:italic">_em inside bold_</span><span style="color:#E1E4E8;font-weight:bold">**</span></span>
<span class="line"><span style="color:#E1E4E8;font-style:italic">_</span><span style="color:#E1E4E8;font-weight:bold">**bold inside em**</span><span style="color:#E1E4E8;font-style:italic">_</span></span></code></pre>
<p>In Obsidian, right now, the above Markdown renders into the same HTML, with the only difference being the text content inside:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">span</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"cm-em cm-strong"</span><span style="color:#E1E4E8">>…</</span><span style="color:#85E89D">span</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>It is not possible to tell how this HTML was written in Markdown. Things are even worse in cases where some parts of a text are only inside the topmost tag and some are not.</p>
<p>For example, the following Markdown:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="md"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8;font-weight:bold">**strong </span><span style="color:#E1E4E8;font-style:italic">_em </span><span style="color:#79B8FF;font-style:italic">`with code`</span><span style="color:#E1E4E8;font-style:italic"> inside_</span><span style="color:#E1E4E8;font-weight:bold"> strong**</span></span></code></pre>
<p>Would display as this:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="md"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8;font-weight:bold">**strong </span><span style="color:#E1E4E8;font-style:italic">**</span><span style="color:#E1E4E8;font-weight:bold">**</span><span style="color:#E1E4E8">em** </span><span style="color:#79B8FF">`with code`</span><span style="color:#E1E4E8"> ** inside*</span><span style="color:#E1E4E8;font-weight:bold">*** strong**</span></span></code></pre>
<p>All of this is because Obsidian unwraps all elements one after another, making it impossible to tell if some inline element is nested into another.</p>
<p>While it is not possible to fix with CSS, I wonder if it is possible to somehow hook up into the way Obsidian renders Markdown from its plugins API with JS, in which case it could be possible to just output the actual symbols right away, maybe even without touching CSS (or, as I did it with my snippet, fade these symbols, making them less noisy).</p>
<h2 id="conclusion">Conclusion</h2>
<p>This CSS snippet, while not ideal, was very quick to write, and I’m much happier now while editing Markdown in Obsidian.</p>
<p>If I find time, I’ll try to investigate its plugin API to see if this problem could be solved from a different angle, but in the meantime, if you also struggle with this default Obsidian behavior, feel free to copy this CSS snippet!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/110725768019867424">on Mastodon</a>!</p>Never Use “Scroll” Value for Overflowhttps://blog.kizu.dev/never-use-overflow-scroll/https://blog.kizu.dev/never-use-overflow-scroll/This post is prompted by the website for the new “monaspace” family of fonts. The problem there is the scroll value for any of the overflow properties. Don’t use it.Fri, 10 Nov 2023 00:00:00 GMT<dl><dt>Current drink:</dt><dd>Camomile tea</dd></dl><hr /><p>This post is prompted by <a href="https://monaspace.githubnext.com/">the website for the new “monaspace” family of fonts</a> (it was fixed since I started to write my article — nice!)</p>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>The problem there is the <strong><code>scroll</code></strong> value for any of the <code>overflow</code> properties. Don’t use it.</p>
<p>What you want to use instead in <strong>99.9%</strong> of cases is the <strong><code>auto</code></strong> value.</p>
<p>Here is a screenshot of the issues from the “monaspace” website:</p>
<p><a href="https://blog.kizu.dev/never-use-overflow-scroll/">“A screenshot of the stylistic set lists from the Monaspace website” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>In the above screenshot, there are only two blocks with actual scrollbars: on the bottom right, but every other similar element that does not have enough content for an overflow to happen still has a rectangle in the scrollbar’s place.</p>
<p>This is because the developers did use the <code>scroll</code> value, and did not test with the “Show scroll bars: Always” preference.</p>
<p>Here it is in the macOS “Appearance” System Settings tab:</p>
<p><a href="https://blog.kizu.dev/never-use-overflow-scroll/">“A screenshot of one “Show scroll bars” settings in macOS” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>The default value for macOS there is “Automatically based on mouse or trackpad”, making most of the scrollbars everywhere to have the “overlay” styles.</p>
<p>Changing this setting to “Always” makes it easy to spot this mistake. Highly recommend.</p>
<h2 id="the-solution">The Solution</h2>
<p><strong>Just use the <code>auto</code> value.</strong></p>
<h2 id="but-what-if">But What If…</h2>
<p>Do you need to reserve some space for the scrollbar? Ok, maybe then you’re excempt from this rule! As with anything, if you know absolutely what you’re doing — go for it.</p>
<p>Though, in the future, I would recommend using the <a href="https://drafts.csswg.org/css-overflow/#scrollbar-gutter-property"><code>scrollbar-gutter</code></a> property with the <code>stable</code> value instead. Or, if you, for some reason, <a href="https://caniuse.com/?search=scrollbar-gutter">don’t need Safari support</a>, you can go ahead and use it now.</p>
<h2 id="prevention">Prevention</h2>
<p>I did add this as a <a href="https://stylelint.io/">Stylelint</a> rule to our codebase.</p>
<p>The rule I did chose for this is <a href="https://stylelint.io/user-guide/rules/declaration-property-value-disallowed-list/"><code>declaration-property-value-disallowed-list</code></a>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="js"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8">{</span></span>
<span class="line"><span style="color:#B392F0"> rules</span><span style="color:#E1E4E8">: {</span></span>
<span class="line"><span style="color:#9ECBFF"> 'declaration-property-value-disallowed-list'</span><span style="color:#E1E4E8">: [</span></span>
<span class="line"><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#9ECBFF"> '/^overflow(-(x|y|inline|block))?$/i'</span><span style="color:#E1E4E8">:</span></span>
<span class="line"><span style="color:#9ECBFF"> /</span><span style="color:#F97583">\b</span><span style="color:#DBEDFF">scroll</span><span style="color:#F97583">\b</span><span style="color:#9ECBFF">/</span><span style="color:#F97583">i</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8"> ]</span></span>
<span class="line"><span style="color:#E1E4E8"> }</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>That’s it! If you’re using Stylelint — I recommend adding this rule yourself. If you’re not — I’ll strongly recommend starting using it, especially if you’re working in a team.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/111387693119706767">on Mastodon</a>!</p>Updated Scroll Markers in the Table of Contentshttps://blog.kizu.dev/toc-scroll-markers/https://blog.kizu.dev/toc-scroll-markers/I’ve spent most of the day inside the delayed and cancelled trains (thanks, Deutsche Bahn). I did not have an opportunity to come up with a good post for today, but both yesterday (and a bit today) I hacked on my blog, as a part of the IndieWebCamp. I did the thing I wanted to do during this weekend: update my blog’s Table of Contents to be similar to what I have on my main site.Sun, 10 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Haru Nemuri — Shunka Ryougen - Audiotree Live Version</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="quick-update">Quick Update</h2>
<p>I’ve spent most of the day inside the delayed and cancelled trains (thanks, Deutsche Bahn). I did not have an opportunity to come up with a good post for today, but both yesterday (and a bit today) I hacked on this blog, as a part of the IndieWebCamp.</p>
<p>I did the thing I wanted to do during this weekend: update my blog’s Table of Contents to be similar to what I have on my <a href="https://kizu.dev/">main site</a>. Actually, it was already working like that, but only in Chrome.</p>
<h2 id="what-i-had">What I Had</h2>
<p>What I am talking about: the small finger marker that appears in the Table of Contents, pointing to the current section:</p>
<p><a href="https://blog.kizu.dev/toc-scroll-markers/">Component is not available in RSS, visit the the site to access it.</a></p>
<p>Before this update, it worked only in Chrome: I was using a heavily modified variation of <a href="https://kizu.dev/scroll-driven-animations/#table-ofcontents-with-highlighted-current-sections">my scroll-driven animations experiment</a> for scroll markers.</p>
<h2 id="the-update">The Update</h2>
<p>Now — it is all the same, but also works in Firefox and Safari!</p>
<p>All thanks to some JS, delivered via a custom element. This is something I briefly mentioned in <a href="https://www.youtube.com/watch?v=ZC_WS05t2lI">my CSS Day talk</a>: instead of trying to cover the whole technology, like scroll-driven animations, with a polyfill, we can only <a href="https://github.com/sindresorhus/ponyfill">ponyfill</a> a single technique with a custom element and implement only the missing parts.</p>
<p>This is what I did: the technique requires scroll-driven animations, particularly, <code>timeline-scope</code>, which Firefox Nightly does not yet support in its outdated experimental implementation of them.</p>
<p>I used an intersection observer and a window resize event to implement what is missing, while keeping most of the styles intact.</p>
<p>I won’t go into the details of the implementation today. Maybe the code behind it could be polished and published as a package? Maybe, one day. Maybe, not. Let me know.</p>
<p>If you’re interested at peeking at the source code of this (far from polished, but at least with some comments), here it is:</p>
<ul>
<li><a href="https://github.com/kizu/kizu-blog/blob/main/src/styles/features/scroll-markers.css">CSS</a></li>
<li><a href="https://github.com/kizu/kizu-blog/blob/main/src/components/ScrollMarkers.astro">Astro component with the custom element inside</a></li>
</ul>
<h2 id="the-specs">The Specs</h2>
<p>Interestingly, <a href="https://github.com/flackr">Robert Flack</a> opened a <a href="https://github.com/w3c/csswg-drafts/issues/10720">CSSWG issue</a> about scroll-markers as a part of the work they did alongside <a href="https://www.miriamsuzanne.com/">Miriam Suzanne</a> and <a href="https://www.stubbornella.org/">Nicole Sullivan</a> on the “carousels” — <a href="https://css.oddbird.net/overflow/explainer/">“CSS Overflow - Broad Research”</a>.</p>
<p>With it, things like that will become <em>trivial</em>, and I cannot wait for it to be specified and in the browsers.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113461136166848833">on Mastodon</a>!</p>My 2024 in CSShttps://blog.kizu.dev/my-2024-in-css/https://blog.kizu.dev/my-2024-in-css/This was another productive year for me. After 2023, I was afraid that I couldn’t get anywhere close. After all, innovation is hard, and you never know if you will stumble over something exciting. Looking back at 2024, I can safely say that I managed to continue doing what I was doing. And, as it will be obvious from the post, there were things that would be difficult to top.Tue, 31 Dec 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>MASS OF THE FERMENTING DREGS — Aoi, Koi, Daidaiiro No Hi</dd><dt>Current drink:</dt><dd>Sencha tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="intro">Intro</h2>
<p>This was another productive year for me. After <a href="/my-2023-in-css/">2023</a>, when I explored <a href="https://kizu.dev/tags/anchor_positioning/">anchor positioning</a>, <a href="https://kizu.dev/tags/scroll_driven_animations/">scroll-driven animations</a>, and came up with <a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a>, I was afraid that I couldn’t get anywhere close. After all, innovation is hard, and you never know if you will stumble over something exciting.</p>
<p>Looking back at 2024, I can safely say that I managed to continue doing what I was doing. And, as it will be obvious from the next sections, there were things that would be difficult to top.</p>
<h2 id="joining-the-css-working-group">Joining the CSS Working Group</h2>
<p>For someone who built their entire career by focusing on CSS, getting an email titled “Would you like to be a CSS WG Invited Expert?” at the beginning of February was surreal, and equally gratifying.</p>
<p>Obviously, I accepted. A bit later, in June, the company I am working in — <a href="https://www.datadoghq.com/">Datadog</a> — joined W3C, so now I’m a regular member of <a href="https://www.w3.org/Style/CSS/">CSS Working Group</a>.</p>
<p>I try to participate in every meeting I can, although I am not sure if I manage to contribute much. Being among people who write CSS specs and implement them in browsers is a good opportunity to keep the impostor syndrome that I had my whole life going strong.</p>
<p><a href="https://blog.kizu.dev/my-2024-in-css/">“A photo showing a group of people walking from left to right on a hill overlooking a city on a peninsula, with blue water, rolling green hills and slightly cloudy sky.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>In June, I traveled to A Coruña for a few days of face-to-face meetings and met many people I previously only talked to or followed virtually. I still need to publish the photos that I took there, oops.</p>
<h2 id="speaking-at-css-day-2024">Speaking at CSS Day 2024</h2>
<p>Another thing that happened at the beginning of 2024 was getting an invitation to speak at <a href="https://cssday.nl/">CSS Day</a> conference, and then speaking at it in June.</p>
<p>I’ve yet to watch <a href="https://www.youtube.com/watch?v=ZC_WS05t2lI">my talk</a>, but I am planning to eventually do it, as I want to do a text version of it. I have no idea how it went other than that I almost fell from the stage, haha.</p>
<p><a href="https://www.youtube.com/playlist?list=PLjnstNlepBvO0-I7iwqpkOY_fwAop6Pl-">All other talks</a> from this conference, were, as usual, great — I can highly recommend you to watch them!</p>
<h2 id="my-articles-and-techniques">My Articles and Techniques</h2>
<style>{`
p.starts-with-tag:has(> a.has-left-overhang.has-right-overhang:only-child) {
text-wrap: balance;
}
`}</style>
<p>While 2023 was for me mostly a year of playing with experimental features, I spent most of 2024 thinking about custom properties, ways we can do APIs with them, and many related topics like conditional CSS and mixins. Most of it stemmed from my <a href="https://kizu.dev/cyclic-toggles/">“Cyclic Dependency Space Toggles”</a> from 2023: both the first and the last articles I published are a continuation of them.</p>
<ul>
<li>
<p><a href="https://kizu.dev/layered-toggles/">“Layered Toggles: Optional CSS Mixins”</a></p>
<p><em>April 9.</em> Probably the weakest article from this year, but about an important topic — I published it as soon as I discovered the technique. While the usage of <code>revert-layer</code> for optional styles was not new, using it in combination with space and cyclic toggles is a much more powerful concept, which I will depend on in the future.</p>
</li>
<li>
<p><a href="https://kizu.dev/alternating-style-queries/">“Alternating Style Queries”</a></p>
<p><em>April 16.</em> An article about a simple but powerful trick with style container queries. Once they become available in all browsers (Firefox, I’m looking at you), I expect this technique to be very common. Initially, it was meant to be a part of the next article I published, but I saw how it is more important to separate it from the more gimmicky and complicated parts.</p>
</li>
<li>
<p><a href="https://kizu.dev/self-modifying-variables/">“Self-Modifying Variables: the <code>inherit()</code> Workaround”</a></p>
<p><em>April 18.</em> The article that flew under the radar the most, even though the effect it talks about is very useful and powerful and is not possible to achieve in any other way. Looking at how we can work around the things that will eventually be in CSS was a theme for me this year, and the <code>inherit ()</code> function is something I wish browsers started to prototype. The workaround based on alternating style queries from the previous article is tricky, but once we have style container queries, I expect it to be an important and invaluable tool.</p>
</li>
<li>
<p><a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a></p>
<p><em>July 19.</em> The most popular article from any that I ever published. The solution for fit-to-width text was something of a holy grail in CSS, and I still can’t believe I found a key to it — and that it is fully cross-browser. It is imperfect as it requires duplication of content, but I don’t think we will come anywhere closer with pure CSS. Let’s hope this will one day be possible with native CSS!</p>
</li>
<li>
<p><a href="https://kizu.dev/tree-counting-and-random/">“Possible Future CSS: Tree-Counting Functions and Random Values”</a></p>
<p><em>October 22.</em> The article that took the longest to finish. But it also has the best interactive examples! It does not really introduce new techniques, but it combines many concepts that I did not see used together before. I can’t wait for the native CSS in question to be available, but, for now, I am planning to use the workarounds described in this article in my other experiments.</p>
</li>
<li>
<p><a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a></p>
<p><em>December 24.</em> The article is about a technique that is a culmination of many different things. In some way, it was another holy grail that I pursued for a long time, and I’m thrilled that I managed to get to the solution. Yes, we will eventually have native conditions, functions, and mixins, but what I unveiled in this article will allow us to close the gap and experiment with these concepts <em>today</em>. And, hopefully, it could also push browsers to start prototyping sooner rather than later.</p>
</li>
</ul>
<h2 id="some-of-my-blog-posts">Some of My Blog Posts</h2>
<p>While I did manage to write a blog post every day for the whole of November again, I did not manage to do it consistently in other months. At some point, I got overwhelmed with the <a href="/tags/bookmarks/">bookmarks</a> backlog and will need to work on some kind of solution (I still want to share them more often — and first read them, as I never share things that I did not read).</p>
<p>I did also post a few noteworthy CSS-related posts here. Some of them were <em>almost</em> good enough to be articles on the main site, but I explicitly wanted them to be a bit less polished. I wanted to work on my blog’s engine (mostly Astro), so I needed to have some posts with live code examples.</p>
<p>Here are the posts that, if you missed, I recommend to check out:</p>
<ul>
<li>
<p><a href="/cap-height-align/">“Cap-Height Vertical Align”</a></p>
<p><em>January 3.</em> That was a nice post to start the year from. A rather simple technique, but also something that I wanted to write for a while.</p>
</li>
<li>
<p><a href="/querying-the-color-scheme/">“Querying the Color Scheme”</a></p>
<p><em>August 29.</em> A fun, but not very practical trick. Requires style container queries — another sign we need them as soon as possible.</p>
</li>
<li>
<p><a href="/captured-custom-properties/">“Captured Custom Properties”</a></p>
<p><em>September 2.</em> A post about a pattern that I use more often for my registered custom properties.</p>
</li>
<li>
<p><a href="/forced-wrapping/">“Observation: Forced Wrapping”</a></p>
<p><em>November 5.</em> A short post about one rare use case for <code>flex-basis</code>. I want to publish posts like these more: there are many neat interactions that can happen with various CSS properties.</p>
</li>
<li>
<p><a href="/non-defined-custom-elements/">“A good way to hide non-defined custom elements”</a></p>
<p><em>November 14.</em> While I do not yet use custom elements a lot, this was one of the first things I tried when seeing the issues of other similar implementations.</p>
</li>
<li>
<p><a href="/sticky-anchor-navigation/">“Observation: Sticky Anchor Navigation”</a></p>
<p><em>November 25.</em> A few test cases and a workaround for one weird issue with anchored navigation. This is a topic that I hope to delve more into, as there are numerous interoperability issues related to it.</p>
</li>
<li>
<p><a href="/css-math-eval/">“Observation: CSS Math Eval”</a> and <a href="/css-math-eval-2/">“CSS Math Eval, now Better and Weirder”</a></p>
<p><em>November 28</em> and <em>November 29</em>. Posts looking at how we can use the powers of CSS calculations to safely evaluate user input with everything that is available inside <code>calc()</code>.</p>
</li>
<li>
<p><a href="/splash-colour-mixin/">“Splash Colour Mixin”</a></p>
<p><em>December 26</em>. One of the first native mixin prototypes I did after publishing <a href="https://kizu.dev/indirect-cyclic-conditions/">“Indirect Cyclic Conditions: Prototyping Parametrized CSS Mixins”</a>. More to come!</p>
</li>
</ul>
<h2 id="my-browser-bug-reports">My Browser Bug Reports</h2>
<p>Almost every time I work on an article or post, I encounter some bugs. I am not always diligent in reporting them, but I try to do it when I have the spoons for this. This year, I matched the number of bugs I reported in 2023: a total of 27 across all browsers then and now.</p>
<ul>
<li><a href="https://issues.chromium.org/issues?q=reporter:[email protected]%20created:2024-01-01..2024-12-31">13 Chrome bugs</a> (<a href="https://issues.chromium.org/issues?q=reporter:[email protected]%20created:2023-01-01..2023-12-31">16 in 2023</a>)</li>
<li><a href="https://bugzilla.mozilla.org/buglist.cgi?emailreporter1=1&email1=kizmarh%40gmail.com&chfieldfrom=2024-01-01&chfieldto=2024-12-31&chfield=%5BBug%20creation%5D&emailtype1=substring">8 Firefox bugs</a> (<a href="https://bugzilla.mozilla.org/buglist.cgi?emailreporter1=1&email1=kizmarh%40gmail.com&chfieldfrom=2023-01-01&chfieldto=2023-12-31&chfield=%5BBug%20creation%5D&emailtype1=substring&list_id=17371297">6 in 2023</a>)</li>
<li><a href="https://bugs.webkit.org/buglist.cgi?email1=kizmarh%40ya.ru&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&list_id=11875877&chfieldfrom=2024-01-01&chfieldto=2024-12-31&chfield=%5BBug%20creation%5D">6 Safari bugs</a> (<a href="https://bugs.webkit.org/buglist.cgi?chfield=%5BBug%20creation%5D&chfieldfrom=2023-01-01&chfieldto=2023-12-31&email1=kizmarh%40ya.ru&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&list_id=11875877">5 in 2023</a>)</li>
</ul>
<p>I think I have a few unreported bugs here and there in my notes and drafts; I’ll try to be even more diligent in 2025.</p>
<h2 id="plans-for-2025">Plans for 2025</h2>
<p>Speaking of notes and drafts. While I don’t have any specific plans for the next year, what I have is a pile of drafts and experiments on various stages.</p>
<p>While there is nothing <em>groundbreaking</em> among them, there are some things that I find curious enough to be content with what I could publish in 2025. I do not intend — and can’t imagine — topping this past year. After all, you can’t force discoveries — only work towards them.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113749199908155314">on Mastodon</a>!</p>I Added Lightning CSS to This Bloghttps://blog.kizu.dev/added-lightning-css/https://blog.kizu.dev/added-lightning-css/After I published my “My Mastodon Starter Pack” post, it got boosted a bunch in Mastodon. This led to more people trying to read it, and some — not successfully. All because in this not very polished blog I used a lot of a bit too-modern CSS, for example, native CSS nesting. And — this resulted in the layout breaking quite substantially.Fri, 15 Nov 2024 00:00:00 GMT<dl><dt>Current music:</dt><dd>Daughter — Still</dd><dt>Current drink:</dt><dd>Camomile & Lavender tea</dd></dl><hr /><h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-problem">The Problem</h2>
<p>After I published my <a href="/my-mastodon-starter-pack/">“My Mastodon Starter Pack”</a> post, it got boosted a bunch <a href="https://front-end.social/@kizu/113455328113049542">in Mastodon</a>. This led to more people trying to read it, and some — not successfully.</p>
<p>All because in this not very polished blog I used a lot of a bit too-modern CSS, for example, <a href="https://drafts.csswg.org/css-nesting-1/">native CSS nesting</a>. And — this resulted in the layout breaking quite substantially:</p>
<p><a href="https://blog.kizu.dev/added-lightning-css/">“An “above the fold” screenshot of the “My Mastodon Starter Pack” article, showing the broken and mostly unreadable layout. The elements in the screenshot go into incorrect places in the grid.” (image is not available in RSS, visit the the site to access it.)</a></p>
<p>Yeah. This is what happens when non-frontend people arrive at your experimental site!</p>
<p>Well, I guess it is time to fix it!</p>
<h2 id="lightning-css">Lightning CSS</h2>
<p>First thing I did is I added <a href="https://lightningcss.dev/">Lightning CSS</a> to my blog (following <a href="https://docs.astro.build/en/guides/styling/#lightningcss">these instructions in Astro docs</a>), so now its styles go through it. With the default settings, it does some <a href="https://lightningcss.dev/transpilation.html">transpilation</a>, including unwrapping native CSS nesting, the absence of which led to most of the problems.</p>
<p>After first adding it, I noticed that I don’t want to have <em>all</em> the transpilation that it gives me: I’d better be a control freak in this case, and only add transpilation of native nesting, without, for example, transpiling <code>:is()</code> to <code>:-webkit-any()</code> and <code>:-moz-any()</code>. Here is the full part related to Lightning CSS in <a href="https://github.com/kizu/kizu-blog/blob/main/astro.config.mjs">my <code>astro.config.mjx</code></a>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="js"><code style="tab-size: 2;"><span class="line"><span style="color:#F97583">import</span><span style="color:#E1E4E8"> { Features } </span><span style="color:#F97583">from</span><span style="color:#9ECBFF"> 'lightningcss'</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#6A737D">// …</span></span>
<span class="line"><span style="color:#F97583">export</span><span style="color:#F97583"> default</span><span style="color:#B392F0"> defineConfig</span><span style="color:#E1E4E8">({</span></span>
<span class="line"><span style="color:#6A737D"> // …</span></span>
<span class="line"><span style="color:#E1E4E8"> vite: {</span></span>
<span class="line"><span style="color:#E1E4E8"> css: {</span></span>
<span class="line"><span style="color:#E1E4E8"> transformer: </span><span style="color:#9ECBFF">"lightningcss"</span><span style="color:#E1E4E8">,</span></span>
<span class="line"><span style="color:#E1E4E8"> lightningcss: {</span></span>
<span class="line"><span style="color:#E1E4E8"> targets: {},</span></span>
<span class="line"><span style="color:#E1E4E8"> include: Features.Nesting,</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8"> },</span></span>
<span class="line"><span style="color:#E1E4E8">});</span></span></code></pre>
<p>I already manually add fallbacks for non-oklch colors, and the rest seem to degrade much more gracefully, so, at least for now, this minimal config is all I need.</p>
<h2 id="fixing-calculated-responsiveness">Fixing Calculated Responsiveness</h2>
<p>After testing how things look in Firefox 115, I still found that I need to adjust my responsive side notes and table of contents.</p>
<p>I’m using a bit too complex math for them, which involves many moving parts like <a href="https://drafts.csswg.org/css-values/#funcdef-round"><code>round()</code></a> and <a href="https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule"><code>@property</code></a> (for <a href="https://blog.kizu.dev/captured-custom-properties/">“Captured Custom Properties”</a>).</p>
<p>I added one <code>@supports</code> (targeting <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/round#browser_compatibility"><code>round()</code> support</a>) that sets some binary flags that I’m using for calculations to put these elements always inside the content area:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span>```css</span></span>
<span class="line"><span>@supports not (width: round(1px, 1px)) {</span></span>
<span class="line"><span> --has-no-aside: 1;</span></span>
<span class="line"><span> --has-aside: 0;</span></span>
<span class="line"><span> --has-no-toc: 1;</span></span>
<span class="line"><span> --has-toc: 0;</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span>```</span></span></code></pre>
<p>That’s it. There are probably still places that could be improved, with better fallbacks, but this should be good enough for now.</p>
<h2 id="appreciating-feedback">Appreciating Feedback</h2>
<p>I noticed that people are often reporting typos in my posts, and other issues — like this one.</p>
<p>Multiple people did let me know about it:</p>
<ul>
<li><a href="https://mastodon.nl/@Bahco">@[email protected]</a> (<a href="https://mastodon.nl/@Bahco/113482537398179361">yesterday</a>).</li>
<li><a href="https://circumstances.run/@Szescstopni">@[email protected]</a> (<a href="https://circumstances.run/@Szescstopni/113461468020895552">this Monday</a>).</li>
<li><a href="https://mastodon.online/@octothorpe">@[email protected]</a> (<a href="https://mastodon.online/@octothorpe/112947627858007161">back in August</a>).</li>
</ul>
<p>Thank you!</p>
<p>I always appreciate any feedback and bug reports, so, please, continue sending them my way. Some things could take a bit longer to fix, but, as you can see, repeated reports make it easier to prioritize more important fixes!</p>
<p>Do not be afraid to report something that you think is obvious or could’ve been reported before. Even if it was — you’ll give an additional signal that other people care, and that more people are affected. And if not, you could be the one reporting an awkward bug or typo that I missed.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/113489414589156788">on Mastodon</a>!</p>Box-Decoration-Breakhttps://blog.kizu.dev/box-decoration-break/https://blog.kizu.dev/box-decoration-break/In the last few days, coincidentally, I saw two cases where the obscure `box-decoration-break` CSS property could help. This might be a good sign that it is worth it to remind everyone about its existence!Thu, 06 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>2:54 — Dawn</dd><dt>Current drink:</dt><dd>Green tea with bergamot, kiwi, yellow peach, orange blossom and violet flower</dd></dl><hr /><p>In the last few days, coincidentally, I saw two cases where the obscure <a href="https://drafts.csswg.org/css-break/#break-decoration"><code>box-decoration-break</code> property</a> CSS could help.</p>
<p>This might be a good sign that it is worth it to remind everyone about its existence!</p>
<p>One reason why, I think, this property is not yet well-known is that it is not “baseline”. Its standard version is implemented in Firefox and Chrome, but Safari is still using the older prefixed <code>-webkit-box-decoration-break</code> version.</p>
<p>There is <a href="https://github.com/WebKit/WebKit/pull/17007">a pull request to WebKit</a> from <a href="https://www.la-grange.net/karl/">Karl Dubost</a> about unprefixing it, although it is a bit stale: the last time it was updated was a year ago. Hopefully, one day it will be finished!</p>
<p>I won’t go into details about what <code>box-decoration-break</code> does, as I will link to many different articles and resources about it.</p>
<h2 id="quick-resources">Quick Resources</h2>
<p>If you are keen to learn about the property itself before continuing, read one of these:</p>
<ul>
<li>
<p><a href="https://12daysofweb.dev/2024/css-box-decoration-break/">“CSS box-decoration-break”</a> — an introductory article by <a href="https://kilianvalkhof.com/">Kilian Valkhof</a> from last year’s <a href="https://12daysofweb.dev/">“12 Days of Web”</a> curated by <a href="https://thinkdobecreate.com/">Stephanie Eckles</a>.</p>
</li>
<li>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/box-decoration-break">An MDN reference for <code>box-decoration-break</code></a>.</p>
</li>
<li>
<p><a href="https://drafts.csswg.org/css-break/#break-decoration">The current draft of CSSWG specification about it</a>.</p>
</li>
</ul>
<p>But let’s look at what were the questions that brought me to this topic.</p>
<h2 id="multi-line-padded-text">Multi-line Padded Text</h2>
<p>First case was <a href="https://mastodon.social/@urlyman/115497124207727749">a question</a> from <a href="https://mastodon.social/@urlyman">Jonathan Schofield</a> about a certain cross-browser issue with some text effect. While it could be interesting to investigate the actual interop issue, I noticed that the author was likely pursuing a very specific decorative style, which would be achieved much easier with <code>box-decoration-break</code>.</p>
<p>I took the name for this section from an eleven-years-old <a href="https://css-tricks.com/multi-line-padded-text/">“Multi-Line Padded Text”</a> article by <a href="https://chriscoyier.net/">Chris Coyier</a>. Alongside this property that was “new” at the time, Chris presented a few workarounds that worked then. Can’t wait until this property will become “newly available”.</p>
<p>A newer article that involved <code>box-decoration-break</code> for a similar, although much more elaborated effect, was <a href="https://frontendmasters.com/blog/overlapping-inline-backgrounds/">“A Deep Dive into the Inline Background Overlap Problem”</a> by <a href="https://thebabydino.github.io/">Ana Tudor</a> from this March. Which, of course, involves some SVG filters magic. Just know that the further you’ll go into the article, the more you’ll start to see the matrix, and the slower your browser will render the page. Sadly, browsers neglected SVG for a long time, including working on its performance.</p>
<h2 id="pseudo-random-svg-underlines">Pseudo-Random SVG Underlines</h2>
<p>Second example is something that I forgot to use when I was working on my last long-form article <a href="https://kizu.dev/svg-linked-parameters-workaround/">“Passing Data into SVG: Linked Parameters Workaround”</a> (if you did not read it <em>fully</em> — I highly recommend, it contains many fun details).</p>
<p>That article was, in part, thanks to <a href="https://ivanish.ca/">Ivan Reese</a>, and after some research I proposed to use the method that I later explained in my article instead of the work-in-progress solution that he was working on.</p>
<p>The solution was for a tiny decorative detail of the Ink & Switch’s website — pseudo-randomized underlines for links.</p>
<p>Recenly, I saw one of their projects — <a href="https://automerge.org/">Automerge</a> — <a href="https://front-end.social/@piccalilli/115486132187200932">mentioned on Mastodon</a> by <a href="Piccalilli">https://piccalil.li/</a>, which reminded if Ivan ended up using my weird SVG solution for the underlines’ implementation on <a href="https://www.inkandswitch.com/">Ink & Switch’s website</a>.</p>
<p>It was, with a proper credit inside <a href="https://www.inkandswitch.com/static/inks/ul.svg">the SVG file used for the undelines</a>!</p>
<p>It is fun to see your highly experimental technique used in practice.</p>
<p>When looking at the links on the page, especially on the bottom of its page, I noticed something: while in general links looked nice, when they were wrapping, they had a “hard cut” on the edges:</p>
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/box-decoration-break/)
<figcaption>Links wrap not nicely.</figcaption>
</figure>
<p>When I saw this, I remembered that we have <code>box-decoration-break: clone</code>, and immediately tried it in the dev tools:</p>
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/box-decoration-break/)
<figcaption>Links wrap nicely.</figcaption>
</figure>
<p>It works! Browsers create separate fragments for each part of the wrapped links, and apply the SVG for each of them.</p>
<p>One other difference that we can notice: the wrapping of the last part changed — and this happened only in Firefox. Probably something to report!</p>
<h2 id="conclusion">Conclusion</h2>
<p>I hope <code>box-decoration-break</code> will become standard sooner rather than later. There are some very fun use cases for it that I did omit in this post: maybe one day I’ll write about them as well.</p>
<p>This property <a href="https://github.com/web-platform-tests/interop/issues/486">was proposed</a> to be included in the last year’s Interop initiative by <a href="https://github.com/jsnkuhn">Jason Kuhn</a>, but not included there.</p>
<p>Please — play with it, see if you could use it to enhance your designs, and let browsers know that you want it to be baseline.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/115505180385509544">on Mastodon</a>!</p>Fit-to-Width Discussions & Feedbackhttps://blog.kizu.dev/fit-to-width-discussions-and-feedback/https://blog.kizu.dev/fit-to-width-discussions-and-feedback/A bit less than a year ago, I published my “Fit-to-Width Text: A New Technique” article. Since then, CSSWG resolved to start working on it, and, following this, two things happened: a discussion of its potential accessibility issues, and an intent to prototype it from Google. I have some thoughts, feedback, and ideas about both of these, so here is a post!Thu, 01 May 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>Tom Figgins — A Leaf in the Breeze</dd><dt>Current drink:</dt><dd>Peppermint Tea</dd></dl><hr /><style>{`
h1 {
font-size: 3.125rem;
}
.table-of-contents {
grid-row-end: span calc(10 * var(--has-toc));
}
`}</style>
<h2 id="table-of-contents">Table of Contents</h2>
<h2 id="the-context">The Context</h2>
<p>A bit less than a year ago, I published my <a href="https://kizu.dev/fit-to-width/">“Fit-to-Width Text: A New Technique”</a> article, where I presented a CSS-only way to achieve a responsive fit-to-width text. You might’ve noticed: this article’s header uses it, for example.</p>
<p>Since then, I thought a lot about that technique, refined it, and bumped a few times the <a href="https://github.com/w3c/csswg-drafts/issues/2528">corresponding CSSWG issue</a> by <a href="https://tobireif.com/">Tobi Reif</a>, which is now seven years old.</p>
<p>On April 1st, I presented this issue and my thoughts about it during a CSS Working Group’s face-to-face meeting, where we <a href="https://github.com/w3c/csswg-drafts/issues/2528#issuecomment-2769621512">resolved</a> to start working on it as a part of <a href="https://www.w3.org/TR/css-fonts-5/">CSS Fonts Module Level 5</a>.</p>
<div class="aside-wrapper" style="--span: 4;">
<aside style="position: static;">
<p>I want to thank <a href="https://nerdy.dev">Adam Argyle</a>, who I talked a lot with while <a href="https://nerdy.dev/ex-googler">he was still at Google</a>, and who nudged Chrome engineers to look more into fit-to-width, as well as <a href="https://github.com/b1tr0t">Penelope McLachlan</a> who asked a few questions about fit-to-width in bluesky, and <a href="https://pixelambacht.nl/">Roel Nieskens</a> who promptly answered a few font-related questions that I asked.</p>
</aside>
</div>
<p>Following that, two things happened: a discussion in the issue regarding potential accessibility problems of this feature, <a href="https://github.com/w3c/csswg-drafts/issues/2528#issuecomment-2769947094">started</a> by <a href="https://www.splintered.co.uk/">Patrick H. Lauke</a>, and an <a href="https://groups.google.com/a/chromium.org/g/blink-dev/c/I3aG24t4bwI/m/xLBLyAJKDwAJ">Intent to Prototype</a> for it alongside an <a href="https://github.com/explainers-by-googlers/css-fit-text/blob/main/README.md">Explainer</a> by <a href="https://github.com/tkent-google">Kent Tamura</a>.</p>
<p>I have some thoughts, feedback, and ideas about both of these, so here is a post!</p>
<aside class="warning">
I wrote this post relatively quickly — trying to get it out sooner rather than later, and thus it might be as unpolished as this blog’s byline goes. Please let me know if you’ll spot any typos, mistakes, or anything else!
</aside>
<h2 id="accessibility">Accessibility</h2>
<h3 id="the-problem-dependency-on-viewport">The Problem: Dependency on Viewport</h3>
<p>Long story short, a common problem of fit-to-width (and other responsive typography) approaches is that they can fail <a href="https://www.w3.org/TR/WCAG21/#resize-text">Success Criterion 1.4.4 Resize Text</a> of WCAG 2.1:</p>
<blockquote>
<p>Except for captions and images of text, text can be resized without assistive technology up to 200 percent without loss of content or functionality.</p>
</blockquote>
<p>How could this technique fail this success criterion? Let’s say we have a viewport, in which we have a fit-to-width block that stretches from one side to another:</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a></p>
<div>[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)Hello There!</div>
<p>Now, a user wants to zoom in to increase the text’s size up to 500%:</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>
<a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>Hello There!</p>
<p>Do you see any change in the text’s size? No? The example above has <code>width: 20%; scale: 5; </code> added to it, essentially, replicating the effect that would be there if we were to zoom into a web page without changing the dimensions of its window.</p>
<p>When I measure the computed font-size of both examples, the first example has <code>125.45px</code>, and the second — <code>25.1108px</code>. 500% is the maximum full-page zoom I can achieve in my Firefox, and it did not change the font-size of our text at all.</p>
<h4 id="possible-arguments">Possible Arguments</h4>
<p>While it could be argued that in <em>some</em> cases users could have access to an alternative way to zoom in like a pinch-to-zoom, not all users will have it, so if we were to consider only those methods available in the browsers, neither changing the default page’s font-size, nor full-page zoom allows us to bump the size of our text by 200%.</p>
<p>And so, it fails the success criterion. At least, literally: in some cases, like in an example above, it could be argued that the text is “big enough”. And, here is <a href="https://github.com/w3c/wcag/issues/1671#issuecomment-797178007">a relevant comment</a> by <a href="https://github.com/mitchellevan">Mitchell Evan</a> from a different (but related) WCAG issue by <a href="https://%C5%A1ime.eu/">Šime Vidas</a> <a href="https://github.com/w3c/wcag/issues/1671">“Can large headings be exempt from Success Criterion 1.4.4 Resize text?”</a>:</p>
<blockquote>
<p>[…] I’ll add that today 150% sized heading text could meet the functional performance criteria of US Section 508 as an instance of equivalent facilitation, if it provides “substantially equivalent or greater accessibility and usability by individuals with disabilities than would be provided by conformance”. It’s a similar concept to functional needs in WCAG 3.0.</p>
</blockquote>
<p>I am not a lawyer, and I don’t know if fit-to-width cases could be considered an “equivalent facilitation”. And if WCAG is referenced by legislation in other countries where they don’t have such excemption, from the potential letter of law this could still be a problem.</p>
<p>It is also necessary to say that the “equivalent facilitation” will only take place in certain conditions, where the text that fits the width would need to have some minimum font-size that is larger than the body copy, not overflow when zoomed, and so on.</p>
<p>In practice, when authors implement fit-to-width texts and other responsive typography techniques, it is possible to easily make the experience <em>worse</em> in certain cases.</p>
<p>For example, forgetting to set a minimum font-size, and then trying to fit a very long line of text in just one line could lead to the font-size being too small:</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>
<a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>This a very long line of text that fits the width, but does not wrap, rendering in a tiny font-size as it does not have a lower limit.</p>
<p>Ah, and this is also an example that uses <code>width: 20%; scale: 5</code>, emulating a user trying to use full-page zoom in an attempt to make the text larger. The computed font-size here is <code>2.48483px</code> on a wide screen, and <code>1.10771px</code> on a screen of an iPhone mini.</p>
<p>My other personal pet peve is what happens when you’re not just zooming in, but <em>zooming out</em> — sometimes a text can be too large, and you want to shrink it to read easier… but cannot, as it continues to take all the available space regardless of the full-page zoom level.</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>
<a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>CSS</p>
<p>This example is “zoomed out” by 50% via <code>width: 200%; scale: 0.5</code>, but the text continues to be very big (computed size is <code>779.034px</code> for me).</p>
<h4 id="fixed-exceptions">Fixed Exceptions</h4>
<p>Before talking about solutions, I want to note that this problem won’t appear <em>always</em>. If the fit-to-width <strong>does not</strong> have a dependency on the viewport’s width, it will follow the full-page zoom perfectly.</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a></p>
<div style="width: 200px; outline: 2px solid var(--PINK)">[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)42</div>
<div style="width: 200px; outline: 2px solid var(--PINK)">[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)2025</div>
<div style="width: 200px; outline: 2px solid var(--PINK)">[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)3.1415926</div>
<p>Above is an example with three elements, each of which has a fixed width of 200px. If we were to zoom in, the text’s size will increase as well, as it won’t adapt to the change of the viewport.</p>
<p>However, this is only a subset of all possible cases which authors could have, and sometimes you could think that the element’s width is fixed, apply the technique, only to add <code>max-width: 100%</code> later and find the “stretched” text to be too small on a mobile viewport, where it becomes the limiting factor.</p>
<h3 id="possible-solutions">Possible Solutions</h3>
<p>It is impossible to eliminate <em>all</em> the potential traps an author can fall when using new features, but we can make it harder to break things unintentionally, and build the defaults more cautiously.</p>
<p>If we were to implement the feature with very severe limitations, there is always a chance authors would either use something else (which could be even worse), or work around the limitations by removing them completely with various hacks. We need to find a balance where we could allow authors to express themselves, but in a way they couldn’t unknowlingly make their sites inaccessible.</p>
<p>I will welcome any constructive feedback: please let me know if you think the proposed solutions are enough, and if not — which limitations would you like to see instead? Is there anything I missed? Don’t hesitate to reply either on Mastodon, in the <a href="https://github.com/w3c/csswg-drafts/issues/2528">parent CSSWG issue</a>, write a post on your platform of choice, or email me at <a href="mailto:[email protected]">[email protected]</a>.</p>
<h4 id="limiting-the-size-range">Limiting the Size Range</h4>
<p>My first (and main) idea for a potential solution came from reading the <a href="https://www.w3.org/WAI/WCAG21/Understanding/resize-text.html">“Understanding Resize Text Success Criterion”</a> document, specifically, <a href="https://www.w3.org/WAI/WCAG21/Understanding/resize-text.html#:~:text=for%20some%20users.-,Note,-As%20with%20most">the second note there</a>:</p>
<blockquote>
<p>[…] For example, if at the default browser setting of 100% zoom, text is set at 20px when the window is 1280 CSS pixels wide, at 200% zoom it will visually appear at twice the size. After zooming by 400% the page reflows to fit within the 320 CSS pixel viewport, the author may decide to set the page’s text size to 10px. The text is now half the original size in CSS pixels, but as it has been enlarged to 400%, it is still displayed at twice the size compared to the default browser setting at 100% zoom. […]</p>
</blockquote>
<p>This note describes a case where an author adjusts the font-size based on the available space, but in a way where even though they reduce it from 20px to 10px, an increase in 400% from that point will lead to the text being 200% larger than originally, thus passing the Success Criterion 1.4.4.</p>
<p>What if we were to limit the <em>range</em> in which our fit-to-width can operate?</p>
<p>In my initial proposal, I wanted to use the original <code>font-size</code> as the minimal size in which the text will be rendered during the first pass, and which then would be increased to fit the available space up to an optional maximum font-size. I contemplated having a default value there, and wondered if something like <code>100vb</code> would be enough.</p>
<p>But what if we had the default value to be just <code>200%</code>? With all modern browsers having at least 500% full-page zoom available, a range of any font from <code>1em</code> to <code>2em</code> should pass the Success Criterion 1.4.4 in the same way as described in the above note.</p>
<div class="aside-wrapper" style="--span: 3;">
<aside style="position: static;">
<p>If we were to look at the 500% value as is, we could say that making the limit be <code>250%</code> could still allow us to pass the SC, but it is better to leave some breathing room and limit it a bit more.</p>
</aside>
</div>
<p>Here is an example from before, but with this limit: first without the “fit-to-width” applied, then with it, and finally, zoomed-in:</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>
</p><div>Limited</div><p></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code style="tab-size: 2;"><span class="line"><span>[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)Limited</span></span>
<span class="line"><span></span></span>
<span class="line"><span>[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)Limited</span></span></code></pre>
<p>Of course, you can see that the text in the second line does <em>not</em> fit the full width, as it grows only to be up to 200% larger than originally, but that is what allows it to grow when we “zoom in”.</p>
<p>In practice, this limitation just means you need to care more about the original font-size, and make it not too small if you want your headers to be able to grow. This post’s header is using this limit, and it still looks good:</p>
<p><a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>
</p><h1 style="margin: 0;overflow: hidden; resize: horizontal; max-width: 110cqi;min-width: 7.2em" role="presentation">
<a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>Fit-to-Width
<a href="https://blog.kizu.dev/fit-to-width-discussions-and-feedback/">Component is not available in RSS, visit the the site to access it.</a>Discussions & Feedback
</h1><p></p>
<p>Although, I had to slightly bump the original font-size of the “Fit-to-Width” to grow further, but it was simple to do, and still allows the header to feel responsive when you resize the content area.</p>
<h5 id="relaxed-or-strict">Relaxed or Strict</h5>
<p>There are two versions of this proposed solution: relaxed and strict.</p>
<ol>
<li>
<p><strong>Relaxed:</strong> use <code>200%</code> as the default “max-font-size” value for the fit-to-width feature. Omitting a value will lead to a guaranteed “passing” criterion. But it will be possible for an author to override it to a different value: smaller or larger.</p>
</li>
<li>
<p><strong>Strict:</strong> have <code>200%</code> as the <em>limit</em> of what you could have for the feature. You could set it to be lower, but not higher.</p>
</li>
</ol>
<p>I lean towards the <code>relaxed</code> solution: the strict limit won’t make sense for any case where <a href="#fixed-exceptions">the problem is non-existent</a>, and as I described at the beginning of the <a href="#possible-solutions">“Possible Solutions”</a> section, in CSS it is possible to find hacky way to work around this anyways.</p>
<p>Having a stricter <em>default</em> could be a good start, additional guidance about the potential accessibility implications in the specs and on MDN could go a long way, and user agents’ developer tools could go even further and detect places where the fit-to-width value (or — any responsive typography calculations) can result in a more than 200% range and is dependent on the viewport dimensions.</p>
<p>There might be some in-between version of this solution as well, where we could introduce some friction for removing the 200% limit. An author that knows what they’re doing will be able to do the required simple step to remove it, but the path of the least resistance will be safer.</p>
<p>Finally, there might be other ways to achieve “fitting to width”, like with <code>letter-spacing</code> and other methods. If we will be able to define them well, a strict solution could use these methods to get the “last mile” after stopping at 200% for the font-size. But that is something that requires experimentation and prototyping, and I still tend to think that a more relaxed solution will work well enough.</p>
<h4 id="collapsing-the-container">Collapsing the Container</h4>
<p>Another idea I had, but did not manage to go far with it: what if we could somehow detect that the element is in the context where it <em>can’t</em> adapt to the viewport — or its container’s — width? If the problematic cases only happen due to the zoom & viewport interaction, and we can’t detect the zoom level (there is an <a href="https://github.com/w3c/csswg-drafts/issues/6869">“Browser zoom unit for accessibility”</a> issue by <a href="https://scottkellum.com/">Scott Kellum</a>, but I am not sure if it will be ever resolved), then can we require setting that fixed width for an element that should grow?</p>
<p>I tried thinking how we could approach it — using containers, maybe anonymous boxes around our text, or something else — but couldn’t find a way that wouldn’t introduce too much friction, or won’t be easy to work around by using registered custom properties, viewport units, or something similar.</p>
<p>However, I wanted to mention this as an idea, or a <em>direction</em> in which we could think. Could we have a strict max font-size by default, but somehow make it relaxed when we detect that the container has a fixed width?</p>
<p>Please let me know if you think this direction is worth exploring it further. Or if you have other ideas over how we can alleviate the zooming issue when we’re bounded by the viewport.</p>
<h3 id="built-in-vs-custom-solutions">Built-in vs. Custom Solutions</h3>
<p>I find this case to be similar to many other cases, where there is a tension between the web platform trying to improve certain use cases, when the design behind them is questionable in the first place. Exclusive accordions, carousels, screen-reader-only styles come to mind.</p>
<p>Today, authors implement these in hacky ways, often with heavy JS usage. Disabled scripts, a tiny mistake, or just an author oversight can render the solutions inaccessible or broken. But new sites continue to be created using these patterns regardless.</p>
<p>Should the Web Platform make it <em>easier</em> to implement such designs? Opponents note that this will make those cases even more prevalent. Proponents say that if we approach it thoughtfully, we can build these solutions accessible (as much as they can be) from the box, eliminating the common mistakes, and reducing the room for an author error.</p>
<p>I don’t have a definitive answer to this, but I believe that together we can strive to make things better and improve the Web.</p>
<h2 id="explainer">Explainer</h2>
<p>Now, to the second part of this post: my feedback for Google’s <a href="https://github.com/explainers-by-googlers/css-fit-text/blob/main/README.md">“CSS fit-width text Explainer”</a>.</p>
<p>In general, it is great that Google wants to prototype fit-to-width feature! Having it available in Canary could allow us to test our assumptions and explore possible fixes to the accessibility problems the feature could have. Of course, we should keep it as a <em>prototype</em> until we will come to an acceptable solution for those, and I am strongly against shipping anything without doing so.</p>
<p>The explainer proposes to have two ways of defining the “fit-to-width” behavior as two new CSS properties: <code>text-grow</code> and <code>text-shrink</code>.</p>
<p>My opinion: at least initially, we should have <em>only</em> the <code>text-grow</code> behavior, and I am not sure if we need the <code>text-shrink</code> at all. I want to focus my feedback on this part first, and then I’ll provide some of my thoughts regarding other open questions from the explainer.</p>
<h3 id="problems-of-text-shrink">Problems of <code>text-shrink</code></h3>
<p>While it might seem that there is not a big difference in which way we approach “fit to width” — first rendering the text as small, and then growing it to fit, or first rendering the text as large, and then collapsing it to fit — in practice, there are many ways in which the “shrinking” behavior can be more awkward and less accessible.</p>
<p>I argue that we can do everything <code>text-shrink</code> can do with <code>text-grow</code>, and having both can be problematic.</p>
<h4 id="worse-fallbacks-and-responsive-behavior">Worse Fallbacks and Responsive Behavior</h4>
<p>Today, many workarounds for fit-to-width tend to <em>start</em> from a larger font-size, shrinking it until it fits. If someone tried to reproduce the same behavior with <code>text-shrink</code> by wanting to have a single-line header that fits into the width, they will likely set <code>white-space: nowrap</code> and a large enough font-size, and then add <code>text-shrink</code>.</p>
<p>This <em>will</em> work, but it creates many problems:</p>
<ul>
<li>
<p>In browsers that do not support <code>text-shrink</code>, the text will overflow beyond its container. More often than not, authors will forget to wrap the <code>white-space</code> in an <code>@supports</code>.</p>
</li>
<li>
<p>Similarly, if we’d like to enable/disable this behavior dynamically, instead of toggling a single property, you’ll need to remember to toggle <code>white-space</code> as well.</p>
</li>
</ul>
<p>With <code>text-grow</code>, we start from the small font-size, and then make it grow as a progressive enhancement. We don’t need <code>white-space: nowrap</code>, as we <em>design for the initial state first</em>.</p>
<h4 id="harder-to-set-a-limit">Harder to Set a Limit</h4>
<p>If we decide to go with having a <code>200%</code> limit of how much our text’s size can change, things become <em>very awkward</em> if we have both <code>text-shrink</code> and <code>text-grow</code>, and allow using them at the same time.</p>
<p>Do we make the limit for either smaller, so we will still have a 200% range from the smallest size to the largest when both are present? Do we add some magic that chooses this limit based on the presence of other property?</p>
<p>I don’t think there is a good way to go about it. We either limit the most common cases, or introduce a hard-to-understand behavior.</p>
<h4 id="opaque-edge-cases">Opaque Edge Cases</h4>
<p>If we design for the larger font-size to be shrunk, we will likely only test the cases that have a non-modified font-size, but will rarely check what happens when it reaches the available range.</p>
<p>This can lead to a tiny font-size, or — if we use the <code>white-space: nowrap</code> — content overflowing by reaching the minimum font-size, and not being able to shrink further.</p>
<p>If we involve adjusting other properties alongside or instead of <code>font-size</code> like <code>letter-spacing</code>, negative values of it can result in a completely unreadable text:</p>
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/fit-to-width-discussions-and-feedback/)
<figcaption>Illustration from the [“Combining behaviors” section of the Explainer](https://github.com/explainers-by-googlers/css-fit-text/blob/main/README.md#combining-behaviors)</figcaption>
</figure>
<p>If we implement text-shrinking for something like a pill element, where the count inside fits its width, it is easy to make the font end up being too small to read.</p>
<p>Generally, treating <code>text-grow</code> as a progressive enhancement allows us to design from the extreme case, and allow the browser improve the display of the text.</p>
<h3 id="other-syntax-feedback">Other Syntax Feedback</h3>
<p>Aside from <code>text-shrink</code>, there are two things that, I feel, need to be talked about.</p>
<h4 id="limit-value">Limit Value</h4>
<p>The explainer proposes to use a <code><length></code> for setting the max value of the font, and it mentions values like <code>30px</code> and <code>8px</code>. Setting the font-size in pixels is a common mispractice, and maybe this is a place where we could try not to introduce another potential point of failure for authors. I see two ways to handle this:</p>
<ul>
<li>
<p>Allow only <code><number>|<percentage></code> values, with a <code>200%</code> by default. If the limit will be strict, it will allow a range of values either from <code>1</code> to <code>2</code>, or from <code>100%</code> to <code>200%</code>.</p>
</li>
<li>
<p>Allow setting a <code><length></code> as well, but convert it into a value based on <code>rem</code> automatically. This can be conroversial, as I don’t think we have a precedent for this in CSS yet, but maybe it is worth introducing a mechanism like this?</p>
</li>
</ul>
<p>And, a final option will be to disallow changing the limit at all. Are there actual cases where you’d want to limit upper value to be less than <code>200%</code>? If a strict limit will be enough, then why not simplify the property by removing the ability to override it at all.</p>
<h4 id="syntax-of-fit-method">Syntax of <code><fit-method></code></h4>
<p>The explainer proposes to have the following values: <code>scale</code>, <code>scale-inline</code>, <code>font-size</code>, and <code>letter-spacing</code>.</p>
<p>I am not certain there is any benefit from having a <code>scale</code>/<code>font-size</code> separation: for most fonts there is no effective difference aside from maybe hinting, and for fonts with an optical variable axis you’d likely never want to use <code>scale</code>.</p>
<p>Having <code>scale-inline</code> is interesting, although at least in western typography non-proportional scaling of glyphs is rarely considered to be good. I can see how it can be sometimes better than changing font-size, but it might also be too easy to shrink the glyph too much.</p>
<p>The <code>letter-spacing</code> seems obvious, but I wonder if we also want to have some kind of limitation to how much it can grow: imagine having a two- or three-letter word that stretches using <code>letter-spacing</code>. We’d need to be able to control how much it will stretch, and have some built-in limit as well.</p>
<p>Finally, I saw many authors mention that they’d want to be able to apply <em>both</em> <code>font-size</code> scaling and <code>letter-spacing</code>, and maybe even some other approaches like changing the font’s <code>width</code> optical axis, or something else. In this case, we’d want to be able to <em>mix</em> these, potentially providing a % of each, or defining a <em>sequence</em> in which they should be used (like first only scaling via <code>font-size</code>, and when the limit is reached use <code>letter-spacing</code>).</p>
<p>Handling multiple methods and mixing them is something I want to experiment with, and maybe we could start with a simplistic syntax, but we need to accomodate its future expansion to be more complicated.</p>
<h3 id="thoughts-on-open-questions">Thoughts on Open Questions</h3>
<p>There are a few items and open questions in the <a href="https://github.com/explainers-by-googlers/css-fit-text/blob/main/README.md#detailed-design-discussion">“Detailed design discussion”</a> section of the Explainer that I’d like to give my thoughts about.</p>
<h4 id="scalable-or-static-elements">Scalable or Static Elements</h4>
<blockquote>
<ul>
<li>Items contained in a line box are classified as either “scalable” or “static”, and only “scalable” items are affected by this feature.</li>
</ul>
</blockquote>
<p>I am not sure if it is useful to categorize <em>elements</em> inside a line box. Mostly, because later there is a question:</p>
<blockquote>
<p>What about padding/border/margin of inline boxes?</p>
</blockquote>
<p>And I strongly think that almost anything that depends on the current font-size should scale accordingly (anything with values in <code>em</code>, <code>ch</code>, <code>cap</code>, etc), and anything that does not (<code>px</code>, <code>rem</code>, etc.) should not.</p>
<p>In my proposal, I suggest having an additional render step that allows us to determine the <em>static contribution</em> of any static parts, including paddings, margins, or more complex calculations.</p>
<blockquote>
<ul>
<li>Should we assume text with a fixed font-size as “static”?</li>
</ul>
</blockquote>
<p>Yes, if a nested element has a font-size defined in <code>px</code> or <code>rem</code>, it should not grow proportionally to the parent’s font-size.</p>
<blockquote>
<ul>
<li>Replaced elements such as <code><img></code> and <code><input></code> are static.</li>
<li>Atomic inlines are static</li>
</ul>
</blockquote>
<p>As I mentioned before, I don’t think we should think about specific elements as being static, but rather determine how much they contribute statically, and how much they contribute when depending on the font-size. An image icon that is sized in <code>em</code> should grow with text, an input could also inherit the parent’s font-size, and thus grow with its font-size as well.</p>
<p>This also answers a later question about <code><length></code>:</p>
<blockquote>
<ul>
<li>How does this interact with properties with <code><length></code>.
<ul>
<li>Should the length be scaled or not? Depends on its units (<code>px</code>, <code>em</code>, <code>rem</code>, <code>%</code>, <code>vw</code>, <code>vh</code>, etc.)?</li>
</ul>
</li>
</ul>
</blockquote>
<h4 id="scale-vs-font-size"><code>scale</code> vs <code>font-size</code></h4>
<blockquote>
<ul>
<li>
<p>The methods vaues <code>scale</code> and <code>font-size</code> that can be specified for <code><fit-method></code> can produce similar visual results. Through prototype implementation and discussion, we aim to decide whether to standardize both or remove one of them.</p>
<ul>
<li><code>scale</code> linearly scales up the glyph data obtained at the original font size for rendering. Consequently, the displayed glyph might differ from the ideal glyph intended for that size. However, since the glyph data retrieval process only happens once, it operates significantly faster.</li>
<li><code>font-size</code> renders the ideal glyph for the displayed size. This process can be considerably slower because it necessitates trying out glyphs of various sizes.</li>
</ul>
</li>
</ul>
</blockquote>
<p>I mentioned this in the <a href="#syntax-of-fit-method">“Syntax of <code><fit-method></code>”</a> section. In short, I think we don’t need the <code>scale</code>, as it won’t be a correct representation of the change in font-size, and I can see how the above thoughts about separating elements into static and scalable could make sense if we will do the “scale” method, but I consider this method to not be good enough.</p>
<h4 id="best-fit-font-size-algorithm">Best-fit <code>font-size</code> Algorithm</h4>
<blockquote>
<ul>
<li>How to find the best-fit font-size? There are cases where the line width becomes smaller even if the font-size is increased.</li>
</ul>
</blockquote>
<p>The algorithm that I am using in my workaround could be a good starting point. For edge cases like <code>calc(20px - 1em)</code>, there are two things we could do:</p>
<ul>
<li>
<p>Only use the initial font-size for such calculations, so the <code>1em</code> there won’t inherit the changed value.</p>
</li>
<li>
<p>Or, we could check if our new value that attempts to increase the length of a line results in a shorter line, and keep the original value instead.</p>
</li>
</ul>
<p>Such edge cases are rare, and we should strive to solve the most common cases, and have an accessible fallback for those outside of them.</p>
<h4 id="other-variable-axis">Other Variable Axis</h4>
<blockquote>
<ul>
<li><code>font-weight</code> or <code>font-width</code> for <code><fit-method></code>? They work well only with specific fonts, and they don’t offer the flexibility to fit text to any width. So we don’t apply them in the initial proposal.</li>
</ul>
</blockquote>
<p>I agree that we <em>could</em> postpone this part, but we need to design the syntax in a way where it could be easily expanded to support those.</p>
<p>I have some ideas about how we could do it. One is to treat each additional axis as linear by default, taking the dimensions of the min and max versions, and interpolating between them. Of course, a font could have a non-linear interpolation for any of the axises, in which case we could allow defining a custom easing as well, but for most cases, like with the <code>width</code> axis, having a linear interpolation by default should be good enough.</p>
<h4 id="mentions-of-accessibility">Mentions of Accessibility</h4>
<blockquote>
<ul>
<li>Accessibility If an end-user tries to enlarge font size, UAs should not fit enlarged lines to the container width. Is minimum-font setting enough?</li>
<li>The user’s minimum font size preference should be respected.</li>
</ul>
</blockquote>
<p>These are the only mentions of accessibility, and I don’t think it is possible for the UA to “not fit enlarged lines to the container width”, as this means the UA will treat full-page zoom differently than just a narrow layout, which might be problematic.</p>
<p>I do not remember if we have a notion of a global “minimum font-size” in CSS, but if we have, and regardless of this, we for sure need to consider it. However, I imagine that we only would need to consider it when talking about <code>text-shrink</code>, while if we were to only implement <code>text-grow</code>, it won’t apply (as it will be just its interaction with regular <code>font-size</code>).</p>
<p>Otherwise, I would like the explainer to dive into accessibility deeper, and consider my thoughts from <a href="#accessibility">the first part of this post</a>.</p>
<h4 id="handling-of-last-lines">Handling of last lines</h4>
<blockquote>
<ul>
<li>How to handle last lines if <code>text-grow:per-line</code> is specified. Should we widen them even if auto-wrapped?</li>
</ul>
</blockquote>
<p>A good question! Without a limit, a single short word in the end could get too large. However, if we introduce the limit, I don’t think this becomes a big issue?</p>
<h4 id="floats-and-initial-letters">Floats and Initial Letters</h4>
<blockquote>
<ul>
<li>Line’s available width can depend on its block offset. e.g. <code>float</code> and <code>initial-letter</code>.</li>
</ul>
</blockquote>
<p>I think the <code>float</code> case is more simple: we could exclude it from any scaling (so not change the <code>font-size</code> inside of it), and first lay out the float, then determine the line boxes and only then do the scaling.</p>
<p>The <code>initial-letter</code> is more complex, as it behaves interestingly when it stretches multiple lines, as its size starts to depend on the line-height. If the line-height is only dependent on the font-size, then it is simple enough case, as we can treat the initial-letter’s contribution to each line as scaling accordingly, but when it is static or mixed, then the dependence is not linear, and we’ll need to define how things should work then.</p>
<h3 id="further-recommended-actions">Further Recommended Actions</h3>
<p>It is great that there is this explainer, as it allows us to start a dialogue and discuss the direction in which we want to go with this feature. If I were to give some advice to Google’s engineers implementing a prototype, here is what I would suggest:</p>
<ul>
<li>
<p>Implement a soft 200% max-font-size limit. Having it in a prototype as a soft limit will allow us to test how things behave without it, and also test what happens if we increase it, and if we ever need to do so. We could always make it strict, or remove an ability to override it altogether later.</p>
</li>
<li>
<p>Focus only on <code>text-grow</code> for the start, see the <a href="#problems-of-text-shrink">reasons why above</a>.</p>
</li>
<li>
<p>Focus on trying to do the proper <code>font-size</code> scaling while taking the potential optical sizing axis in consideration as I explained in <a href="https://github.com/w3c/csswg-drafts/issues/2528#issuecomment-2314897420">my original proposal</a>. If the regular scaling is simple, it will be better to try and do the hard part first — we should not discard it without trying. But, in my opinion, even if just scaling in simpler, it will not be enough, and for many typographic designs we’ll have to rely on existings workarounds instead of using the new feature. And, because of the ways different algorithms treat static/scaling contributions, I doubt it will be good to allow them both.</p>
</li>
</ul>
<h2 id="invitation-to-participate">Invitation to Participate</h2>
<p>That’s it for now!</p>
<p>Fit-to-width is a hard problem, but it is worth solving. I invite all designers, typography enthusiasts, and accessibility practioners <a href="#possible-solutions:~:text=Don%E2%80%99t%20hesitate%20to%C2%A0reply">to participate</a> in doing so, and finding a way forward that won’t make things worse.</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu/114433691482828924">on Mastodon</a>!</p>Border: 2px doublehttps://blog.kizu.dev/border-2px-double/https://blog.kizu.dev/border-2px-double/I wanted to write a different post today, but did not have time to finish it, oops. So let me tell you one pretty useless but fun CSS fact.Wed, 26 Nov 2025 00:00:00 GMT<dl><dt>Current music:</dt><dd>toe — all i understand is that i don’t understand</dd><dt>Current drink:</dt><dd>Lemongrass, Ginger & Black Pepper tea</dd></dl><hr /><p>I wanted to write a different post today, but did not have time to finish it, oops.</p>
<p>So let me tell you one pretty useless but fun CSS fact.</p>
<p>Look at this:</p>
<p><a href="https://blog.kizu.dev/border-2px-double/">Component is not available in RSS, visit the the site to access it.</a></p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="html"><code style="tab-size: 2;"><span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">div</span><span style="color:#B392F0"> class</span><span style="color:#E1E4E8">=</span><span style="color:#9ECBFF">"square"</span><span style="color:#E1E4E8">></</span><span style="color:#85E89D">div</span><span style="color:#E1E4E8">></span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="css"><code style="tab-size: 2;"><span class="line"><span style="color:#B392F0">.square</span><span style="color:#E1E4E8"> {</span></span>
<span class="line"><span style="color:#79B8FF"> width</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#F97583">em</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> aspect-ratio</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">1</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#79B8FF"> border</span><span style="color:#E1E4E8">: </span><span style="color:#79B8FF">2</span><span style="color:#F97583">px</span><span style="color:#79B8FF"> double</span><span style="color:#E1E4E8">;</span></span>
<span class="line"><span style="color:#E1E4E8">}</span></span></code></pre>
<p>On screens with good old 1x resolution this will render with a solid <code>2px</code> border.</p>
<p>But on systems with <em>retina</em> screens (or similar), this renders in a fully non-interop way:</p>
<style>{`
.examples {
grid-column: --page;
display: grid;
grid-template: 'c f s';
gap: 1rem;
padding: var(--MIN-CONTENT-PADDING);
margin: 0;
text-align: center;
}
@media (prefers-color-scheme: light) {
img[src*="_light"] {
display: unset;
}
img[src*="_dark"] {
display: none;
}
}
@media (prefers-color-scheme: dark) {
img[src*="_dark"] {
display: unset;
}
img[src*="_light"] {
display: none;
}
}
`}</style>
<div class="examples">
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
<figcaption>Chrome</figcaption>
</figure>
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
<figcaption>Firefox</figcaption>
</figure>
<figure>
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
[Component is not available in RSS, visit the the site to access it.](https://blog.kizu.dev/border-2px-double/)
<figcaption>Safari</figcaption>
</figure>
</div>
<p>Interestingly, there is no guidance (as far as I know) about this <a href="https://www.w3.org/TR/css-backgrounds-3/#valdef-line-style-double">in the specs</a>. They only say for <code>double</code>:</p>
<blockquote>
<p>Two parallel solid lines with some space between them. (The thickness of the lines is not specified, but the sum of the lines and the space must equal <code>border-width</code>.)</p>
</blockquote>
<p>And browsers are free to interpret this as they wish.</p>
<p>Curiously, both Firefox and Chrome also do <code>1.5px double</code> correctly, in which case it will be two <code>0.5px</code>-wide borders with <code>0.5px</code> space between, while <code>2px</code> results in whole <code>1px</code>-wide space between those two <code>0.5px</code> borders.</p>
<p>If only Safari did follow suit… But hey, I mentioned that this is mostly useless fact. But I hope it was at least a bit fun!</p>
<hr>
<p>Let me know what you think about this <a href="https://front-end.social/@kizu">on Mastodon</a>!</p>