<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/feed.xsl" type="text/xsl" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en" xml:base="https://chrisburnell.com">
	<title>Chris Burnell · CSS</title>
	<subtitle>All of my posts tagged “css”.</subtitle>
	<id>https://chrisburnell.com/tag/css/</id>
	<link href="https://chrisburnell.com/tag/css.xml" rel="self" />
	<link href="https://chrisburnell.com/tag/css/" rel="alternate" />
	<author>
		<name>Chris Burnell</name>
		<uri>https://chrisburnell.com/</uri>
		<email>me@chrisburnell.com</email>
	</author>
	<logo>https://chrisburnell.com/images/raven.svg</logo>
	<image>https://chrisburnell.com/images/avatar@4x.jpeg</image>
	<updated>2026-05-09T12:49:02+00:00</updated>
	<generator>Eleventy v3.1.0</generator>
	<entry>
		<id>https://chrisburnell.com/article/fresh-pixels/</id>
		<link href="https://chrisburnell.com/article/fresh-pixels/" />
		<title>Fresh pixels</title>
		<published>2026-05-09T09:49:02-03:00</published>
		<publishedFriendly>9 May 2026</publishedFriendly>
		<updated>2026-05-09T09:49:02-03:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Status updates and enforcing the crispiest-possible 88x31 badges across the web</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Status updates and enforcing the crispiest-possible 88x31 badges across the web&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Yesterday afternoon, I spent some time creating a new &lt;a href=&quot;/88x31/&quot;&gt;88x31 badge&lt;/a&gt; for my website footer.&lt;/p&gt;
&lt;p&gt;In case you missed &lt;a href=&quot;/article/new-year-new-server-2/&quot;&gt;my last post&lt;/a&gt;, I’m in the midst of migrating servers, and one of the things I migrated was &lt;a href=&quot;https://status.chrisburnell.com&quot;&gt;my status page&lt;/a&gt;, which pings each of my websites once per minute and reports whether the request was successful, and if so, how long the request took. Each website is represented on the front end by a graph of response times across the last hour as well as 60 red or green-coloured &lt;em&gt;bloops&lt;/em&gt;, which represent the successes of the last hour’s pings.&lt;/p&gt;
&lt;p&gt;So the idea was to create a dynamic 88x31 badge that relayed information from my status page by displaying some number of the most recent &lt;em&gt;bloops&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I set out achieving this by first creating the 88x31 image with some blank areas that I could fill in later with green or red, depending on the status of each &lt;em&gt;bloop&lt;/em&gt;, and the next step was to create a short PHP script to consume this image, fill in the colours of the &lt;em&gt;bloops&lt;/em&gt;, and spit out the result.&lt;/p&gt;
&lt;p&gt;Fortunately, generating images with PHP is one of the first things I ever learned how to do outside of HTML and CSS early on in my web development journey, nearly 20 years ago, so this was a familiar task!&lt;/p&gt;
&lt;p&gt;And the result (blown up for clarity):&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://chrisburnell.com/images/uptime.gif&quot; alt=&quot;Server uptime badge&quot; width=&quot;352&quot; height=&quot;124&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/figure&gt;
&lt;details&gt;
    &lt;summary&gt;Backend code, if you’re interested&lt;/summary&gt;
&lt;p&gt;Here’s what the JSON file of minute-by-minute data looks like:&lt;/p&gt;
&lt;pre data-language=&quot;json&quot; data-language-friendly=&quot;JSON&quot; data-filename=&quot;uptime.json&quot;&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260261&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.406&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260321&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.446&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260381&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.807&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here’s the gist of the PHP that generates the dynamic image:&lt;/p&gt;
&lt;pre data-language=&quot;php&quot; data-language-friendly=&quot;PHP&quot; data-filename=&quot;uptime.php&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?php&lt;/span&gt;
&lt;p&gt;&lt;span&gt;$image&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecreatefromgif&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;uptime.gif&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$green&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecolorallocate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;102&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;204&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;51&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$red&lt;/span&gt;   &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecolorallocate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;153&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;51&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cacheFile&lt;/span&gt;  &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;cache.json&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$uptimeFile&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;uptime.json&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$numBloops&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;9&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;file_exists&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;||&lt;/span&gt; &lt;span&gt;filemtime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;time&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&lt;/span&gt; &lt;span&gt;60&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$uptimeData&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;json_decode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;file_get_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;usort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeData&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;fn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$b&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&lt;/span&gt; &lt;span&gt;$a&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$recent&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;array_slice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeData&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$numBloops&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cache&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$recent&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&quot;bloops&quot;&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;array_map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;br&gt;
&lt;span&gt;fn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$item&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;0&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;gt;=&lt;/span&gt; &lt;span&gt;200&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;299&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$recent&lt;/span&gt;&lt;br&gt;
&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;]&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;file_put_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;json_encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cache&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cache&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;json_decode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;file_get_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;$bloops&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;array_reverse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cache&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;bloops&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;foreach&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;$bloops&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; &lt;span&gt;$i&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$ok&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$color&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;$ok&lt;/span&gt; &lt;span&gt;?&lt;/span&gt; &lt;span&gt;$green&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;$red&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;imagefilledrectangle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;4&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$color&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Content-type: image/gif&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Cache-Control: public, max-age=60&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;imagegif&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And while we’re at it, here’s how I’m serving my PHP file as if it’s a GIF in &lt;em&gt;nginx&lt;/em&gt;:&lt;/p&gt;
&lt;pre data-language=&quot;nginx&quot; data-language-friendly=&quot;nginx&quot; data-filename=&quot;/etc/nginx/sites-available/example.com&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;location&lt;/span&gt; = /images/uptime.gif&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;include&lt;/span&gt; fastcgi_params&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;fastcgi_param&lt;/span&gt; SCRIPT_FILENAME /absolute/path/to/uptime.php&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;fastcgi_pass&lt;/span&gt; unix:/run/php/php8.4-fpm.sock&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;In building this new 88x31, I was struck with another idea.&lt;/p&gt;
&lt;p&gt;Because I so fiercely believe that (most) 88x31 badges look best on the web when they have &lt;code&gt;image-rendering: pixelated;&lt;/code&gt; applied to them, why not enforce my belief across (almost) the entire web?&lt;/p&gt;
&lt;p id=&quot;using-css&quot;&gt;Using CSS&lt;/p&gt;
&lt;p&gt;I use the &lt;a href=&quot;https://add0n.com/stylus.html&quot;&gt;Stylus&lt;/a&gt; extension in my browser (&lt;a href=&quot;https://github.com/openstyles/stylus#releases&quot;&gt;get it here&lt;/a&gt;) to apply my own CSS to websites and pages. My custom styles are mostly to fix bugs, improve shaky layouts, or to add little quality-of-life stuff, and this seems like an ideal place for me to throw a small chunk of CSS and have my browser apply it across every page that I visit.&lt;/p&gt;
&lt;p&gt;The CSS I came up with is pretty minimal, and although it relies on the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes being present, many websites that I visit that &lt;em&gt;do&lt;/em&gt; have 88x31 badges at least have the attributes present, if not the desired CSS property applied as well:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:where(img[width=&quot;88&quot;][height=&quot;31&quot;])&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;image-rendering&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; pixelated&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here’s how it looks in &lt;em&gt;Stylus&lt;/em&gt;. Note that I’m applying this CSS to &lt;q&gt;Everything&lt;/q&gt;, which means &lt;em&gt;every&lt;/em&gt; webpage that you visit:&lt;/p&gt;
&lt;figure&gt;
    &lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.avif 500w, /images/built/stylus-pixelate-88x31s-800.avif 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.webp 500w, /images/built/stylus-pixelate-88x31s-800.webp 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;img alt=&quot;Stylus UI when adding styles for all websites to pixelate 88x31 badges&quot; title=&quot;Stylus UI when adding styles for all websites to pixelate 88x31 badges&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;/images/built/stylus-pixelate-88x31s-500.png&quot; width=&quot;800&quot; height=&quot;128&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.png 500w, /images/built/stylus-pixelate-88x31s-800.png 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;/picture&gt;
&lt;/figure&gt;
&lt;p id=&quot;using-js&quot;&gt;Using JavaScript&lt;/p&gt;
&lt;p&gt;Alternatively, if you want to achieve this for &lt;em&gt;all&lt;/em&gt; 88x31 images, whether they have the correct attributes or not, there’s the &lt;a href=&quot;https://www.tampermonkey.net/&quot;&gt;Tampermonkey&lt;/a&gt; extension (&lt;a href=&quot;https://www.tampermonkey.net/#download&quot;&gt;get it here&lt;/a&gt;) that works much like Stylus but with JavaScript instead of CSS. Here’s my script that checks the width and height of images &lt;em&gt;whether their attributes are set or not&lt;/em&gt; and appropriately applies the pixelated effect to 88x31 images:&lt;/p&gt;
&lt;pre data-language=&quot;javascript&quot; data-language-friendly=&quot;JavaScript&quot;&gt;&lt;code&gt;&lt;span&gt;// ==UserScript==&lt;/span&gt;
&lt;span&gt;// @name         Pixelate 88x31s&lt;/span&gt;
&lt;span&gt;// @match        *://*/*&lt;/span&gt;
&lt;span&gt;// @run-at       document-idle&lt;/span&gt;
&lt;span&gt;// ==/UserScript==&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;document&lt;span&gt;.&lt;/span&gt;&lt;span&gt;querySelectorAll&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;img&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;img&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;const&lt;/span&gt; &lt;span&gt;pixelate&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;img&lt;span&gt;.&lt;/span&gt;naturalWidth &lt;span&gt;===&lt;/span&gt; &lt;span&gt;88&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; img&lt;span&gt;.&lt;/span&gt;naturalHeight &lt;span&gt;===&lt;/span&gt; &lt;span&gt;31&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
img&lt;span&gt;.&lt;/span&gt;style&lt;span&gt;.&lt;/span&gt;imageRendering &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;pixelated&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
img&lt;span&gt;.&lt;/span&gt;complete &lt;span&gt;?&lt;/span&gt; &lt;span&gt;pixelate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; img&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;load&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; pixelate&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now properly-attributed 88x31 images will always appear nice and sharp, everywhere on the web, including but not limited to the ones in the footer of my website (though they already have the &lt;em&gt;correct&lt;/em&gt; &lt;code&gt;image-rendering&lt;/code&gt;)!&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/fresh-pixels/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/color-scheming/</id>
		<link href="https://chrisburnell.com/article/color-scheming/" />
		<title>Color Scheming</title>
		<published>2025-10-24T12:01:00-03:00</published>
		<publishedFriendly>24 October 2025</publishedFriendly>
		<updated>2025-10-24T12:01:00-03:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>It’s been about a year and a half since I changed how colour schemes (i.e., light and dark themes) work on my website, and after reviewing and refactoring things again recently, I thought I would share how everything ties together and allows for different levels of control over colour schemes.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;It’s been about a year and a half since I changed how colour schemes (i.e., light and dark themes) work on my website, and after reviewing and refactoring things again recently, I thought I would share how everything ties together and allows for different levels of control over colour schemes.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;In this article, I’ll cover &lt;em&gt;how&lt;/em&gt; to implement a colour-scheming system, gain some understanding of how to control the colour scheme in different ways, and write some CSS that leverages the strengths of the language to build a hierarchy of colour scheme controls.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: We’re going to build this hierarchy of controls out of order, but we’ll wrap everything back around to honour its order by the end.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;&lt;abbr title=&quot;Operating System&quot;&gt;OS&lt;/abbr&gt;/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr&gt;
&lt;h2 id=&quot;build&quot;&gt;Let’s build&lt;/h2&gt;
&lt;h3 id=&quot;part-1&quot;&gt;4. &lt;abbr title=&quot;Operating System&quot;&gt;OS&lt;/abbr&gt;/Browser-level Preference&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;OS/Browser-level Preference&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To begin with, we should make sure to include this &lt;code&gt;meta&lt;/code&gt; tag in the &lt;code&gt;head&lt;/code&gt; of our page(s). This &lt;q&gt;indicates a suggested [colour] scheme that user agents should use for a page&lt;/q&gt; (&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/color-scheme&quot;&gt;MDN&lt;/a&gt;).&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;content&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to indicate in our CSS what colour schemes we want to have available, and we can apply this to the document root (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; in &lt;em&gt;most&lt;/em&gt; cases) and the cascade will apply the appropriate colour scheme to the entire document:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This, alone, allows us to write CSS that responds dynamically to the &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; for a light or dark colour scheme. Where colours are concerned in our CSS, we can use the &lt;code&gt;light-dark()&lt;/code&gt; function to hook into which of the two colour schemes is active and provide an appropriate colour for both conditions.&lt;/p&gt;
&lt;p&gt;Also, because we’ve written &lt;code&gt;light dark&lt;/code&gt;, we have indicated that where an &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; does not exist, we should default to the first value. This means that in the absense of all preferences and overrides, the default colour scheme will be the &lt;code&gt;light&lt;/code&gt; one. If we had instead written &lt;code&gt;dark light&lt;/code&gt;, the &lt;code&gt;dark&lt;/code&gt; colour scheme would be the default.&lt;/p&gt;
&lt;h3 id=&quot;part-2&quot;&gt;1 &amp;amp; 2. Element-level &amp;amp; Page-level Overrides&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;Element-level Override&lt;/li&gt;
    &lt;li&gt;Page-level Override&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Next, let’s take care of Page-level and Element-level colour scheme overrides. The way I’ve chosen to do this is by creating classes for each colour scheme that can be appled to any element and use a specific colour scheme for itself and its children:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can apply these classes to the &lt;code&gt;html&lt;/code&gt; element to force an entire page to use a specific colour scheme:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, we might want a particular section of a page to always use a specific colour scheme, so we can apply the class to a wrapper element and allow the &lt;code&gt;color-scheme&lt;/code&gt; value to cascade to its children:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	...
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;part-3&quot;&gt;3. Site-level Preference&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Site-level Preference&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The last part is unfortunately the most complex, so let’s dive in and flesh out how we can allow website visitors to override their &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; &lt;em&gt;without&lt;/em&gt; stepping on top of our &lt;em&gt;Page-level/Element-level Overrides&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To start with, I’m using &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes’&lt;/a&gt; web component, &lt;a href=&quot;https://github.com/daviddarnes/storage-form/&quot;&gt;&lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt;&lt;/a&gt;, to capture the &lt;em&gt;Site-level Preference&lt;/em&gt;. This works by wrapping a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; that contains a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;. The &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component listens for selection changes on the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and saves those changes to local storage.&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span&gt;autocomplete&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;off&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;select&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;optgroup&lt;/span&gt; &lt;span&gt;label&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;Select a colour scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;selected&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;OS Default&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Light&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Dark&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;optgroup&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From then on, whenever the web component’s JavaScript finds the same &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; (matched by &lt;code&gt;name&lt;/code&gt; attribute) on subsequent page loads or on other pages, it will modify the selected &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; in the DOM to match the local storage value.&lt;/p&gt;
&lt;p&gt;This takes care of persistence of &lt;em&gt;Site-level Preferences&lt;/em&gt;. I cannot overstate how amazingly powerful this little web component is! I use it every time I need to manage some sort of &lt;q&gt;state&lt;/q&gt; on my website.&lt;/p&gt;
&lt;p&gt;What’s great about this approach is that we can leave &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; alone from here and continue using CSS to control and manage how we respond to different colour schemes. We can build selectors that match when a particular &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; is selected (i.e., &lt;code&gt;checked&lt;/code&gt;), and using the &lt;code&gt;:has()&lt;/code&gt; selector, we can then apply a specific colour scheme based on that selection:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So when the &lt;code&gt;light&lt;/code&gt; option has been selected, we are applying the light colour scheme to the document root, and vice versa for the &lt;code&gt;dark&lt;/code&gt; option.&lt;/p&gt;
&lt;h3 id=&quot;part-4&quot;&gt;A nod to performance&lt;/h3&gt;
&lt;p&gt;Before we can put everything together, there are some problems we need to address.&lt;/p&gt;
&lt;p&gt;Firstly, we need to think about &lt;em&gt;how&lt;/em&gt; we initiate the JavaScript that defines the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component because until it is loaded, the &lt;em&gt;Site-level Preference&lt;/em&gt; that exists in local storage won’t have been mirrored onto the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; on the page. At present, we’re &lt;em&gt;relying&lt;/em&gt; on the value of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; to apply a &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This gives us some options and a choice to make.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; instantiate the web component in the &lt;code&gt;head&lt;/code&gt; of our page(s) and be sure that by the time the HTML parser reaches our &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;, the browser will know what to do with it, and the correct colour scheme will be applied; however, this will block the parsing of HTML while the entirety of the web component’s JavaScript is being processed.&lt;/p&gt;
&lt;p&gt;We might think to defer the script or run it asynchronously, but no matter how we slice it—loading the JavaScript before the HTML or vice versa—we’re going to run into an unsightly problem. The effect will be more pronounced on slower devices and/or slower connections, but there &lt;em&gt;will&lt;/em&gt; be a period of time where some portion of HTML has been parsed and rendered &lt;em&gt;before&lt;/em&gt; the locally-stored colour scheme value has been applied to the HTML. Depending on how different in brightness the light and dark colour schemes are, this can result in an intense shift from light to dark or dark to light before and after the locally-stored colour scheme value is applied.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;I’ve&lt;/em&gt; done to solve this is to defer the loading of the JavaScript that initiates the web component and instead include a small snippet of (minified) JavaScript in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; that &lt;em&gt;is technically&lt;/em&gt; parser-blocking, but will reliably run (or fail) very quickly.&lt;/p&gt;
&lt;pre data-language=&quot;javascript&quot; data-language-friendly=&quot;JavaScript&quot;&gt;&lt;code&gt;&lt;span&gt;const&lt;/span&gt; &lt;span&gt;COLOR_SCHEME&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; localStorage&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;COLOR_SCHEME&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	document&lt;span&gt;.&lt;/span&gt;documentElement&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;data-color-scheme&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;COLOR_SCHEME&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;window&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;load&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
document&lt;span&gt;.&lt;/span&gt;documentElement&lt;span&gt;.&lt;/span&gt;&lt;span&gt;removeAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;data-color-scheme&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;What this does is independently check the browser’s local storage for the same value that gets set by the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; in the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component. &lt;em&gt;If&lt;/em&gt; a value is found, then it sets a data attribute on the document root. When the window has finished loading, this means that the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; JavaScript has completed, so the data attribute on the document root gets removed, allowing the CSS selector based on the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value (which is now in parity with local storage) to once again take control.&lt;/p&gt;
&lt;p&gt;We can apply some further CSS that will apply the correct colour scheme during this &lt;q&gt;in-between&lt;/q&gt; state when the data attribute is present on the document root:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;[data-color-scheme=&quot;light&quot;]&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;[data-color-scheme=&quot;dark&quot;]&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;part-5&quot;&gt;Review and Refactor&lt;/h3&gt;
&lt;p&gt;Let’s put all of our CSS together. We’ll combine our initial &lt;code&gt;:root&lt;/code&gt; declaration alongside two other declarations, one for each of two groups, selectors that should apply the light colour scheme and selectors that should apply the dark colour scheme.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;Warning!&lt;/span&gt; The CSS below is not the full solution! Keep reading below to learn about what we need to do to fix its problems.&lt;/em&gt;&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked),&lt;br&gt;
[data-color-scheme=&quot;light&quot;],&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked),&lt;br&gt;
[data-color-scheme=&quot;dark&quot;],&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, while this CSS does target the different parts of the DOM that we need, there are a few last considerations to make before this will preserve the order of preferences and overrides that we want. We’re going to use two important features of CSS to help us tailor things to do that.&lt;/p&gt;
&lt;p&gt;First of all, we can amend our first declaration with the &lt;code&gt;:where()&lt;/code&gt; selector. This selector &lt;em&gt;nullifies&lt;/em&gt; the specifity of all selectors inside it, so when our &lt;code&gt;:root&lt;/code&gt; selector becomes &lt;code&gt;:where(:root)&lt;/code&gt;, it has a specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;. This makes it very easy to &lt;em&gt;out-specify&lt;/em&gt; later on.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
&lt;/span&gt;	color-scheme: light dark;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we’ll consider the three methods of control (&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value, data attribute, class) and which should be more specific.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value selector and data attribute selector can be treated as one—that is to say that their specificity in this hierarchy should be identical, as they both &lt;em&gt;actually&lt;/em&gt; represent the same thing, the value of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Based on the hierarchy that we want, the specificity of the class-based controls should be higher than the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and data attribute controls.&lt;/p&gt;
&lt;p&gt;Let’s consider the specificity of the three selectors in each group:&lt;/p&gt;
&lt;table&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;:root:has([name=color-scheme] [value=light]:checked)&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,4,0)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;[data-color-scheme=light]&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,1,0)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;.light&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,1,0)&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Given that their specificities don’t align with what we want, we can leverage a second important feature of CSS, source order.&lt;/p&gt;
&lt;p&gt;Let’s use the &lt;code&gt;:where()&lt;/code&gt; selector again to nullify the specificity of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value selector and data attribute selector:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;-&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;.light {
	color-scheme: light;
}
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;-&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;.dark {
	color-scheme: dark;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But why do this? Won’t they have the same specificity as the &lt;code&gt;:where(:root)&lt;/code&gt; declaration?&lt;/p&gt;
&lt;p&gt;They &lt;strong&gt;do&lt;/strong&gt; have the same specificity &lt;code&gt;(0,0,0)&lt;/code&gt;, but, &lt;strong&gt;critically&lt;/strong&gt;, they come &lt;em&gt;after&lt;/em&gt; the &lt;code&gt;:where(:root)&lt;/code&gt; declaration in source order. This means that our new &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and data attribute selectors take precedence over &lt;code&gt;:where(:root)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’ve inlined the specificity of each selector to demonstrate this below:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;/**
 * (0,0,0) — 1st in source order
 */&lt;/span&gt;
&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/p&gt;
&lt;/code&gt;&lt;ul&gt;&lt;code&gt;
&lt;li&gt;Order of selector specificities below:&lt;/li&gt;
&lt;li&gt;(0,0,0) – 2nd in source order&lt;/li&gt;
&lt;li&gt;(0,0,0) – 2nd in source order&lt;/li&gt;
&lt;/code&gt;&lt;li&gt;&lt;code&gt;(0,1,0)&lt;br&gt;
*/&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id=&quot;part-6&quot;&gt;Fin.&lt;/h2&gt;
&lt;p&gt;At this point, the build is complete! For the most part, the code involved in this solution &lt;em&gt;rarely&lt;/em&gt; needs amending or changing, so I tend to put it wherever you might find things like resets in my CSS.&lt;/p&gt;
&lt;p&gt;We can make powerful use of the &lt;code&gt;light-dark()&lt;/code&gt; function to toggle between colour values depending on the active colour scheme, e.g.:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;main&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;background-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;light-dark&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;#e1e1e1&lt;span&gt;,&lt;/span&gt; #1e1e1e&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;light-dark&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;#1e1e1e&lt;span&gt;,&lt;/span&gt; #e1e1e1&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Furthermore, because we’ve set up a hierarchy for the controls that we’ve made available to us, we’ve instructed our styles to hook into visitors’ &lt;em&gt;OS/Browser-level Preference&lt;/em&gt;. If they’d rather not let their OS/Browser dictate their preference, they can use the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; to choose a &lt;em&gt;Site-level Preference&lt;/em&gt; that will persist across tabs, windows, and even sessions, thanks to the power of local storage.&lt;/p&gt;
&lt;p&gt;We’ve also thought about user experience and poor-performance situations by introducing a light sprinkling of JavaScript. Despite incurring a small performance impact itself, this gives us the tremendous benefit of applying a chosen colour scheme to the page as &lt;em&gt;early&lt;/em&gt; as possible to prevent the &lt;em&gt;wrong&lt;/em&gt; colour scheme from being shown &lt;em&gt;before&lt;/em&gt; the heftier parts of this solution have had a chance to make their impact.&lt;/p&gt;
&lt;p&gt;On top of that, we, as website authors, can override the user’s &lt;em&gt;Site-level Preference&lt;/em&gt; to be able to say that certain pages or parts of pages should &lt;em&gt;always&lt;/em&gt; be rendered with a specific colour scheme.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Full CSS Solution&lt;/summary&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;br&gt;
&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;Bonus!&lt;/h4&gt;
&lt;p&gt;Although it isn’t stable across browsers yet, the &lt;a href=&quot;/feature-watch/#css-if&quot;&gt;&lt;code&gt;if()&lt;/code&gt; selector&lt;/a&gt; will allow us to toggle non-colour property values based on the resolved colour scheme. This is great for things like changing a &lt;code&gt;background-image&lt;/code&gt; based on the colour scheme. That would look something like this:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;light&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/light.png&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/dark.png&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;part-7&quot;&gt;Fin. Part 2:&amp;nbsp;Electric Boogaloo&lt;/h2&gt;
&lt;p&gt;We can actually take this one step further without &lt;em&gt;much&lt;/em&gt; extra CSS, and this gives us the ability to set a Page-level or Element-level colour scheme that is more of a &lt;em&gt;suggestion&lt;/em&gt; than a &lt;em&gt;rule&lt;/em&gt;, and can be overridden by a &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This gives us two new ways to apply colour schemes to our pages and an amended hierarchy of how colour schemes can be applied:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Element-level Suggestion&lt;/li&gt;
    &lt;li&gt;Page-level Suggestion&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;:where(:root) {
	color-scheme: light dark;
}
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked):not([data-color-scheme], .light, .dark))&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;&amp;amp;:where(.suggested-light),&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&amp;amp; :where(.suggested-light)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;		&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;&amp;amp;:where(.suggested-dark),&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&amp;amp; :where(.suggested-dark)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;		&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light {&lt;br&gt;
color-scheme: light;&lt;br&gt;
}&lt;br&gt;
:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark {&lt;br&gt;
color-scheme: dark;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;div&gt;
    &lt;p&gt;This introduces a rather unwieldy selector, &lt;code&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked):not([data-color-scheme], .light, .dark))&lt;/code&gt;, so let’s break down what it does:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;code&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked)&lt;/code&gt; checks if the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; on the page has its default value but targets the document root when applying styles. When this is the case, it means that the user has selected neither &lt;code&gt;light&lt;/code&gt; nor &lt;code&gt;dark&lt;/code&gt; as their &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;:not([data-color-scheme], .light, .dark)&lt;/code&gt; ensures that the document root has neither a &lt;code&gt;data-color-scheme&lt;/code&gt; attribute nor the classes &lt;code&gt;light&lt;/code&gt; or &lt;code&gt;dark&lt;/code&gt; applied to it.&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;:where(...)&lt;/code&gt; makes sure that this complex selector has a specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;. This ensures that it doesn’t compete in specificity with other important parts of this solution, but rather takes a specific place in the source order to help define its place in the hierarchy (see below).&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;The two extra classes that this introduces, &lt;code&gt;.suggested-light&lt;/code&gt; and &lt;code&gt;.suggested-dark&lt;/code&gt;, can be applied to our HTML in the same way as our previous classes (&lt;code&gt;.light&lt;/code&gt; and &lt;code&gt;.dark&lt;/code&gt;), but the important thing to note here again is the source order.&lt;/p&gt;
&lt;p&gt;By placing these declarations &lt;em&gt;between&lt;/em&gt; the two parts of our previous solution (and matching the specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;), they receive &lt;em&gt;higher&lt;/em&gt; precendence than the &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; but &lt;em&gt;lower&lt;/em&gt; precedence than the &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This can be useful in situations where, for artistic reasons, you&#39;d like a particular page or section to be a specific colour scheme, but if the user has set a &lt;em&gt;Site-level Preference&lt;/em&gt;—maybe for reasons relating to eyesight or otherwise—then that choice should be respected and the particular page/section should be rendered as they’ve chosen, &lt;em&gt;not&lt;/em&gt; from your &lt;q&gt;suggested&lt;/q&gt; colour scheme.&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS. This post is part of &lt;a href=&quot;https://chrisburnell.com/rss-club/&quot;&gt;RSS Club&lt;/a&gt;, which means it appears &lt;em&gt;only&lt;/em&gt; in my RSS feeds for 3 days (until &lt;time datetime=&quot;2025-10-27T12:01:00-03:00&quot;&gt;Monday, 27 October 2025&lt;/time&gt;), rewarding folks who subscribe to my RSS feeds with knowing about this post early!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/color-scheming/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/note/1723796014/</id>
		<link href="https://chrisburnell.com/note/1723796014/" />
		<title>Reply to What&#39;s Your Style?</title>
		<published>2024-08-16T16:13:34+08:00</published>
		<publishedFriendly>16 August 2024</publishedFriendly>
		<updated>2024-08-16T16:13:34+08:00</updated>
		<category term="note" scheme="https://chrisburnell.com/note/" label="Note" />
		<summary>If I go back and look at the first version of my website from 2008, it looks like I was a style.css guy. I resent so much about that decision. 😂 I mean, I guess they are called Cascading Style...</summary>
		<content xml:lang="en" type="html">
			
			
			
			&lt;p&gt;If I go back and look at &lt;a href=&quot;https://v1.chrisburnell.com/&quot;&gt;the first version of my website from 2008&lt;/a&gt;, it looks like I was a &lt;code&gt;style.css&lt;/code&gt; guy.&lt;/p&gt;
&lt;p&gt;I resent &lt;em&gt;so much&lt;/em&gt; about that decision. 😂&lt;/p&gt;
&lt;p&gt;I mean, I guess they &lt;em&gt;are&lt;/em&gt; called Cascading Style Sheets, not Cascading Style&lt;strong&gt;s&lt;/strong&gt; Sheets, so maybe there’s an argument to be made there for using &lt;code&gt;style.css&lt;/code&gt;, but I won’t be the one defending that position!&lt;/p&gt;
&lt;p&gt;Recently, though, I tend not to use either &lt;code&gt;style.css&lt;/code&gt; or &lt;code&gt;styles.css&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ever since the notion of &lt;strong&gt;Critical CSS&lt;/strong&gt; entered the scene, I’ve named things a bit differently. Because the idea here is to split a website’s styles into two sets—one that is required for &lt;q&gt;above the fold&lt;/q&gt; content, or many/all pages; and another that is needed to style the rest of the website—I’ve started naming the two stylesheets &lt;code&gt;critical.css&lt;/code&gt; and &lt;code&gt;defer.css&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;actually&lt;/em&gt; happens on my website these days is that I use the 11ty plugin, &lt;a href=&quot;https://github.com/11ty/eleventy-plugin-bundle&quot;&gt;eleventy-plugin-bundle&lt;/a&gt;, to combine various SCSS partials into two buckets (also named &lt;code&gt;critical&lt;/code&gt; and &lt;code&gt;defer&lt;/code&gt;), and the plugin generates a chunk of CSS that gets inlined in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and another chunk that gets spat out into a content-hashed file location and gets referenced by a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;p&gt;So, in short, I’ve still got a fondness in my heart for ol’ faithful, &lt;code&gt;/css/styles.css&lt;/code&gt;, but what I actually do in practice differs. That being said, I think there’s a future where, like native Web Components for example, CSS comes bundled with the HTML that it’s associated with as a best practice. And with that being a possibility, I think it’s reasonable to assume that I’ll be naming my CSS files &lt;code&gt;styles.css&lt;/code&gt; once again!&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/note/1723796014/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		<link rel="related" type="reply" href="https://flamedfury.com/posts/whats-your-style/" />
	</entry>
	<entry>
		<id>https://chrisburnell.com/note/layout-update-may-2024/</id>
		<link href="https://chrisburnell.com/note/layout-update-may-2024/" />
		<title>Layout Update</title>
		<published>2024-05-29T23:19:17+08:00</published>
		<publishedFriendly>29 May 2024</publishedFriendly>
		<updated>2024-05-29T23:19:17+08:00</updated>
		<category term="note" scheme="https://chrisburnell.com/note/" label="Note" />
		<summary>A short update on my website’s layout.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;A short update on my website’s layout.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Over the last few days, I’ve been working on some minor redesign of my website’s overall layout that I mentioned &lt;a href=&quot;/note/indent-outdent/&quot;&gt;in yesterday’s post, &lt;q&gt;Indent Outdent&lt;/q&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After some thinking, I’ve decided to do away with the sidebar that’s been part of my website’s layout for many, many years. This puts the &lt;em&gt;content&lt;/em&gt; of my page and posts in a much more prominent and distinct location within the viewport at wide enough screen sizes. I was starting to feel like the sidebar was pushing a lot of dense information right up alongside the start of each page, which made things a little cluttered and fought for attention and focus with the content of each page.&lt;/p&gt;
&lt;p&gt;That’s not to say that the information in the sidebar is gone, I’ve just done a little refactoring of the grid layout to move that stuff underneath the main content, which fills horizontally across the page (given enough space in the viewport) instead of vertically. I’ve been eagerly reading a lot of articles and thoughts in the front end community regarding &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Masonry_layout&quot;&gt;masonry layout&lt;/a&gt;, and I’m eager to see the technology mature and a solid standard come out of it. It would certainly help tidy up the meta information at the bottom of pages.&lt;/p&gt;
&lt;p&gt;There are still some things I’d like to take another look at to see what improvements I can make, but I think it’s in a good enough state now that I’m happy to push it live, and not have to juggle two branches of code anymore.&lt;/p&gt;
&lt;p&gt;As a result of the sidebar going away, I also took the opportunity to bump up some of the font sizes across my site to make use of the reclaimed real estate, and I think it makes for an easier reading experience across viewport sizes. Another thing I’ll likely be tinkering with as time goes on. This also means that it will be easier for me to re-explore the idea of having aside text within the content of my pages and posts because I won’t have to contend with convoluted styles to take into account the unknown size of the sidebar when positioning them.&lt;/p&gt;
&lt;p&gt;I hope you enjoy it! &lt;a href=&quot;/about/#contact&quot;&gt;Let me know&lt;/a&gt; if you encounter any issues or if you have any ideas or suggestions. I’m all ears!&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #29 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/note/layout-update-may-2024/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/note/indent-outdent/</id>
		<link href="https://chrisburnell.com/note/indent-outdent/" />
		<title>Indent Outdent</title>
		<published>2024-05-28T18:07:40+08:00</published>
		<publishedFriendly>28 May 2024</publishedFriendly>
		<updated>2024-05-28T18:07:40+08:00</updated>
		<category term="note" scheme="https://chrisburnell.com/note/" label="Note" />
		<summary>In the last few days, I’ve been working on a small redesign of my website, and thought I’d share a handy little implementation of CSS Grid I’ve been using to lay out the contents of my pages.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;In the last few days, I’ve been working on a small redesign of my website, and thought I’d share a handy little implementation of CSS Grid I’ve been using to lay out the contents of my pages.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;What this implementation does is set up a containment context around my main grid. This grid is set up with a series of named rows that I can slot children elements into, but the part that I really like about this grid are the columns, where the grid defines three named columns. Depending on the &lt;code&gt;width&lt;/code&gt; / &lt;code&gt;inline-size&lt;/code&gt; of the container, the size of these columns changes.&lt;/p&gt;
&lt;p&gt;First things first, let’s look at the HTML we’re working with.&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;grid&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;title&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Title&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;description&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Description&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;content&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum suscipit id nulla vitae maximus. In bibendum risus in commodo fermentum.&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;meta&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;published &lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;time&lt;/span&gt; &lt;span&gt;datetime&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;2024-05-28T18:07:40+08:00&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;28 May 2024&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;time&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;tagged &lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span&gt;href&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;/tag/css/&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;css&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;,  &lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span&gt;href&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;/tag/css-variables/&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;css-variables&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;, &lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span&gt;href&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;/tag/weblogpomo2024/&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;weblogpomo2024&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the rough HTML for an example blog post, which contains a title, description, content, and meta information about the post.&lt;/p&gt;
&lt;p&gt;The first step in building out this implementation is to define a containment context on the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element, which wraps the grid.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;main&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;container&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; main / inline-size&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we’ll set up the grid and its rows and columns.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;.grid&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; grid&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;align-items&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; start&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;grid-template-rows&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
		[title-start]
		auto
		[title-end description-start]
		auto
		[description-end content-start]
		auto
		[content-end meta-start]
		auto
		[meta-end]&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;grid-template-columns&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
		[indent-start]
		&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--indent-size&lt;span&gt;,&lt;/span&gt; 0&lt;span&gt;)&lt;/span&gt;
		[indent-end]
		&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--indent-gap&lt;span&gt;,&lt;/span&gt; 0&lt;span&gt;)&lt;/span&gt;
		[content-start]
		&lt;span&gt;repeat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;6&lt;span&gt;,&lt;/span&gt; 1fr&lt;span&gt;)&lt;/span&gt;
		[content-end]
		&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--outdent-gap&lt;span&gt;,&lt;/span&gt; 0&lt;span&gt;)&lt;/span&gt;
		[outdent-start]
		&lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--outdent-size&lt;span&gt;,&lt;/span&gt; 0&lt;span&gt;)&lt;/span&gt;
		[outdent-end]&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’ve got our grid in place, complete with named rows and columns. In particular, note that the two outer named columns, &lt;code&gt;indent&lt;/code&gt; and &lt;code&gt;outdent&lt;/code&gt; (as well as the gaps between them), have a size of &lt;code&gt;0&lt;/code&gt;. This is because the four respective CSS Variables (&lt;code&gt;--indent-size&lt;/code&gt;, &lt;code&gt;--indent-gap&lt;/code&gt;, &lt;code&gt;--outdent-gap&lt;/code&gt;, and &lt;code&gt;--outdent-size&lt;/code&gt;) have not been defined, so the fallback value of &lt;code&gt;0&lt;/code&gt; is used instead.&lt;/p&gt;
&lt;p&gt;We can now use a container query to assign some values to these CSS Variables when the &lt;code&gt;inline-size&lt;/code&gt; of the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element is greater than &lt;code&gt;500px&lt;/code&gt;.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@container&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;inline-size &amp;gt; 500px&lt;span&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;.grid&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;--indent-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 1fr&lt;span&gt;;&lt;/span&gt;
		&lt;span&gt;--indent-gap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 1rem&lt;span&gt;;&lt;/span&gt;
		&lt;span&gt;--outdent-gap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 1rem&lt;span&gt;;&lt;/span&gt;
		&lt;span&gt;--outdent-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 1fr&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last step is to slot the four content areas into the named rows and columns.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;.title,
.description,
.meta&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;grid-column&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; indent / outdent&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span&gt;.title&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;grid-row&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; title&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;.description&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;grid-row&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; description&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;.content&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;grid-row&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; content&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;grid-column&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; content&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;.meta&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;grid-row&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; meta&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now we’ve got a layout where three of the four grid items span the full width of the grid, and the content spans only the width of the &lt;code&gt;content&lt;/code&gt; column.&lt;/p&gt;
&lt;p&gt;When the container size is greater than &lt;code&gt;500px&lt;/code&gt;, the &lt;code&gt;indent&lt;/code&gt; and &lt;code&gt;outdent&lt;/code&gt; columns will have a size of &lt;code&gt;1fr&lt;/code&gt;, so the title, description, and meta information areas will be wider than the content.&lt;/p&gt;
&lt;p&gt;At or below &lt;code&gt;500px&lt;/code&gt;, the &lt;code&gt;indent&lt;/code&gt; and &lt;code&gt;outdent&lt;/code&gt; columns will have a size of &lt;code&gt;0&lt;/code&gt;, so all four grid items will have equal widths.&lt;/p&gt;
&lt;p&gt;And that’s all there is to it!&lt;/p&gt;
&lt;p&gt;I built a &lt;a href=&quot;https://codepen.io/chrisburnell/pen/bGyBvyK&quot;&gt;demo on CodePen&lt;/a&gt; so you can play with the container to see how the indent and outdent appear at different sizes. Use the handle on the bottom-right of the grid to resize the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element to see the indent and outdent appear and disappear.&lt;/p&gt;
&lt;p&gt;&lt;c-codepen slug=&quot;bGyBvyK&quot; height=&quot;450px&quot;&gt;&lt;/c-codepen&gt;&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #28 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/note/indent-outdent/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/interpolating-colours/</id>
		<link href="https://chrisburnell.com/article/interpolating-colours/" />
		<title>Interpolating Colours</title>
		<published>2024-05-27T21:39:56+08:00</published>
		<publishedFriendly>27 May 2024</publishedFriendly>
		<updated>2024-05-27T21:39:56+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Today I’ll be talking about how we can use some relatively new data types in CSS for finer control over how we use colour spaces in mixing and creating gradients from colours.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Today I’ll be talking about how we can use some relatively new data types in CSS for finer control over how we use colour spaces in mixing and creating gradients from colours.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Although not completely stable across all modern browsers, there are two data types that we can apply to colour-related CSS functions like &lt;code&gt;color-mix()&lt;/code&gt; and &lt;code&gt;linear-gradient()&lt;/code&gt; and give us the ability to traverse through different colour spaces in new ways. I’m going to work through these two data types by using them with some linear gradients and seeing how they affect the outcome.&lt;/p&gt;
&lt;h2&gt;Color Interpolation Method&lt;/h2&gt;
&lt;p&gt;The first data type I’m going to look at is called the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color-interpolation-method&quot;&gt;color interpolation method&lt;/a&gt;.&lt;/p&gt;
&lt;details&gt;
    &lt;summary&gt;What’s &lt;q&gt;interpolation&lt;/q&gt;?&lt;/summary&gt;
    &lt;p&gt;Interpolation, in this context, is a method for finding new data points based on a range of discrete data points. When it comes to interpolation in colour gradients, this refers to the method by which new colours are found between some known set of colours.&lt;/p&gt;
    &lt;p&gt;If we imagine a gradient between the colour red and green, interpolation is how the browser figures out what colours come between the red and green on opposite ends of the gradient.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;A few months ago, I published a code snippet, &lt;a href=&quot;/code/mixing-colours-different-spaces/&quot;&gt;Mixing Colours in Different Colour Spaces&lt;/a&gt;, where I showed how different colour interpolation methods will mix two given colours in different ways. The reason why using different colour interpolation methods produce such different results boils down to the shapes of the colour spaces.&lt;/p&gt;
&lt;p&gt;When mixing two colours, the browser will do some calculations to determine the nearest possible midpoint between the two, and the shape and journey taken inside that colour space to find that midpoint is what affects the output.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://hueplot.ardov.me/&quot;&gt;Hueplot&lt;/a&gt; by &lt;a href=&quot;https://ardov.me/&quot;&gt;Alexey Ardov&lt;/a&gt; for an &lt;em&gt;incredible&lt;/em&gt; visualiser of different colour spaces.&lt;/p&gt;
&lt;p&gt;The article, &lt;a href=&quot;https://developer.chrome.com/docs/css-ui/high-definition-css-color-guide&quot;&gt;High definition CSS color guide&lt;/a&gt;, by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; is also a fantastic resource for learning more about colour spaces and how the browser draws a path between different types of colour spaces (rectangular and polar) to mix them or create gradients between them.&lt;/p&gt;
&lt;p&gt;Similarly to mixing colours with &lt;code&gt;color-mix()&lt;/code&gt;, we can use different colour spaces when defining gradients with &lt;code&gt;linear-gradient()&lt;/code&gt;. As a rudimentary example, let’s look at how we might define a gradient between the colours red and green:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		green
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/srgb-gradient.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;128&quot; height=&quot;128&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;Most browsers will use the sRGB gamut by default, which means the in-between points of colour between red and green are derived from traversing the path between red (&lt;code&gt;rgb(255, 0, 0)&lt;/code&gt;) and green (&lt;code&gt;rgb(0, 128, 0)&lt;/code&gt;) in the rectangular sRGB colour space.&lt;/p&gt;
&lt;p&gt;We can instruct the browser to traverse between these two colours in a &lt;em&gt;different&lt;/em&gt; colour space by using the &lt;code&gt;in *&lt;/code&gt; syntax. For example, to traverse between the equivalent of the same two colours in the HSL colour space, we can add &lt;code&gt;in hsl&lt;/code&gt; after the angle of direction in the gradient’s definition:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom in hsl&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		green
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/hsl-gradient.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;128&quot; height=&quot;128&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;This produces a different gradient because the path between red (&lt;code&gt;hsl(360, 100%, 50%)&lt;/code&gt;) and green (&lt;code&gt;hsl(120, 100%, 25%)&lt;/code&gt;) passes through different colours in the polar HSL colour space than it does in the sRGB colour space.&lt;/p&gt;
&lt;p&gt;What’s also great about this method is that we can define our colours however we choose, and the browser will interpret them in our chosen colour space for us. No conversion needed!&lt;/p&gt;
&lt;h2&gt;Hue Interpolation Method&lt;/h2&gt;
&lt;p&gt;The second data type I’ll discuss is called the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/hue-interpolation-method&quot;&gt;hue interpolation method&lt;/a&gt;. This provides us with a way to specify how the browser should calculate the midpoint between the hues of different colours when in a polar colour space like HSL, LCH, or OKLCH.&lt;/p&gt;
&lt;p&gt;I think the power of this data type can be most-easily visualised by taking a look at a colour wheel (this one is using HSL):&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/hsl-colour-wheel.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;190&quot; height=&quot;190&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;Let’s say we wanted to create a gradient that traverses through all the hues of a colour space to produce a full rainbow of colours across the gradient.&lt;/p&gt;
&lt;p&gt;Ideally, it would be nice to be able to define a starting colour and have the gradient traverse through all the hues in the colour space and arrive back at the starting point. Something like this:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom in hsl&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		red
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly, this doesn’t work, and what is produced is a solid red colour across the entire gradient. This is because the browser will travel through a colour space by taking the shortest path that it can. In our case, because we’re going from &lt;code&gt;red&lt;/code&gt; to &lt;code&gt;red&lt;/code&gt;, the shortest path is to not travel at all, which means that the hues in between the start and end of the gradient will not change.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/hsl-colour-wheel-example-1.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;190&quot; height=&quot;190&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;Traditionally, creating a rainbow gradient like the one we want would involve defining a series of colour stops for the browser to interpolate between.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom in hsl&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		orange&lt;span&gt;,&lt;/span&gt;
		yellow&lt;span&gt;,&lt;/span&gt;
		green&lt;span&gt;,&lt;/span&gt;
		blue&lt;span&gt;,&lt;/span&gt;
		indigo&lt;span&gt;,&lt;/span&gt;
		violet&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is certainly far from perfect. The problem is that the spread of colours in a colour space is usually not very even, so the visual difference between each of the colour stops can vary quite dramatically.&lt;/p&gt;
&lt;p&gt;However, by defining a hue interpolation method alongside a polar colour interpolation method, we can tell the browser to take the longer way around the colour space. This means we can instruct the browser to traverse from &lt;code&gt;red&lt;/code&gt; to &lt;code&gt;red&lt;/code&gt; again, but instead by taking the longer route around the colour space to get from beginning to end:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom in hsl longer hue&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		red
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells the browser to take a path through the HSL colour space that looks something like this:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/hsl-colour-wheel-example-2.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;190&quot; height=&quot;190&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;And the result is our rainbow gradient!&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/hsl-rainbow-gradient-longer.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;190&quot; height=&quot;190&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;We can also use other colour spaces to get different colours in the gradient, produced by the shapes of those colour spaces instead, e.g. &lt;code&gt;in oklch&lt;/code&gt;:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
	&lt;span&gt;linear-gradient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;
		to bottom in oklch longer hue&lt;span&gt;,&lt;/span&gt;
		red&lt;span&gt;,&lt;/span&gt;
		red
	&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/content/oklch-rainbow-gradient-longer.png&quot; alt=&quot;&quot; role=&quot;presentation&quot; width=&quot;190&quot; height=&quot;190&quot;&gt;
&lt;/figure&gt;
&lt;p&gt;The other values (&lt;code&gt;shorter hue&lt;/code&gt;, &lt;code&gt;decreasing hue&lt;/code&gt;, and &lt;code&gt;increasing hue&lt;/code&gt;) are other ways we can dictate that the browser should traverse through a given colour space. This allows us to do things like change the direction around the colour space that is taken, force the browser to use the &lt;em&gt;shorter&lt;/em&gt; route, and so on. Playing with these values can lead to some really interesting mixes and gradients that were previously quite cumbersome to achieve!&lt;/p&gt;
&lt;h2&gt;Demo&lt;/h2&gt;
&lt;p&gt;Check out this post &lt;a href=&quot;/article/interpolating-colours/#demo&quot;&gt;on my website&lt;/a&gt; to play with the demo.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #27 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/interpolating-colours/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/website-settings/</id>
		<link href="https://chrisburnell.com/article/website-settings/" />
		<title>Website Settings</title>
		<published>2024-05-10T11:04:55+08:00</published>
		<publishedFriendly>10 May 2024</publishedFriendly>
		<updated>2024-05-10T11:04:55+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>In this post, I’m going to run through how I’m using some exciting new browser features to power the settings/preferences on my website.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;In this post, I’m going to run through how I’m using some exciting &lt;q&gt;new&lt;/q&gt; browser features to power the settings/preferences on my website.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;While still riding the high of the fantastic &lt;a href=&quot;https://conf.11ty.dev/&quot;&gt;11ty Conference&lt;/a&gt; yesterday (which ended at &lt;time datetime=&quot;2024-05-10T05:00:00+08:00&quot;&gt;5 in the morning&lt;/time&gt; here in Singapore…), I was inspired to write this post off the back of two talks in particular: &lt;a href=&quot;https://conf.11ty.dev/2024/dont-fear-the-cascade/&quot;&gt;Don&#39;t Fear the Cascade&lt;/a&gt; by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; and &lt;a href=&quot;https://conf.11ty.dev/2024/light-mode-versus-dark-mode/&quot;&gt;&lt;/a&gt; by &lt;a href=&quot;https://conf.11ty.dev/2024/light-mode-versus-dark-mode/&quot;&gt;Light mode versus Dark mode&lt;/a&gt; by &lt;a href=&quot;https://sarajoy.dev/&quot;&gt;Sara Joy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While there’s certainly a lot to look forward to in the &lt;a href=&quot;https://wicg.github.io/web-preferences-api/&quot;&gt;Web Preferences API&lt;/a&gt;, it hasn’t yet become a fully-fledged web standard and become available in browsers. Until that time comes, I’m using a combination of relatively-modern but stable browser features to serve up a series of settings/preferences that website visitors can use to control and modify their browsing experience.&lt;/p&gt;
&lt;aside&gt;&lt;p&gt;If you’re not familiar, the settings window can be opened from the top-right corner of any of my pages&lt;span&gt;; although, you’ll have to visit my website to see it in action: &lt;a href=&quot;https://chrisburnell.com/article/website-settings/&quot;&gt;https://chrisburnell.com/article/website-settings/&lt;/a&gt;&lt;/span&gt;!&lt;/p&gt;&lt;/aside&gt;
&lt;h2&gt;Popovers&lt;/h2&gt;
&lt;p&gt;Historically, attaching functionality to buttons has, for the most part, required JavaScript, save for some bits and pieces like submit buttons in forms. The &lt;q&gt;new&lt;/q&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Popover_API&quot;&gt;Popover API&lt;/a&gt; provides a method for displaying popover content on top other page content, like a modal window, and wonderfully does &lt;em&gt;not&lt;/em&gt; require JavaScript, as it’s baked right into the browser.&lt;/p&gt;
&lt;p&gt;At its simplest, turning an element into a popover element is done by applying a &lt;code&gt;popover&lt;/code&gt; attribute; likewise, attaching a button to that popover element (to open and close it) is done by adding a &lt;code&gt;popovertarget&lt;/code&gt; attribute whose values is the &lt;code&gt;id&lt;/code&gt; of the popover element:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;wibble&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;popover&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Popover content here&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span&gt;popovertarget&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;wibble&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Toggle Popover&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;
    &lt;div id=&quot;wibble&quot; popover=&quot;&quot;&gt;Popover content here&lt;/div&gt;
    &lt;button popovertarget=&quot;wibble&quot;&gt;Toggle Popover&lt;/button&gt;
&lt;/figure&gt;
&lt;p&gt;Included with popover elements is a new pseudo-element, &lt;code&gt;::backdrop&lt;/code&gt;, that covers the entire viewport, can be styled with CSS, and can even intercept clicks to hide/close the popover.&lt;/p&gt;
&lt;p&gt;There are a tonne of other features that I won’t go into detail about today, but includes other quality-of-life things like the &lt;kbd&gt;Escape&lt;/kbd&gt; key closing popovers, being able to control whether buttons should open, close, or toggle its respective popover element, etc.&lt;/p&gt;
&lt;p&gt;I’m using this great new browser feature to hold my website’s settings, which tucks them away neatly when not in use and saves me from having to write and maintain some JavaScript to control the interactions!&lt;/p&gt;
&lt;p&gt;If you want to learn more about Popovers, &lt;a href=&quot;https://hidde.blog/blog/&quot;&gt;Hidde de Vries&lt;/a&gt; has written extensively on their intricate details, how to use them effectively, and accessibility related to their use. I can’t recommend Hidde’s work enough. It’s absolutely worth the read!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;has-selector&quot;&gt;The :has() selector&lt;/h2&gt;
&lt;p&gt;I spent &lt;em&gt;many&lt;/em&gt; years as a developer wishing, hoping, and deeply-lamenting the non-existence of &lt;q&gt;the parent selector&lt;/q&gt;. I cannot count the number of times that I’d be working on something and mourned how much more readable and easy life would have been had there been a way to style a &lt;em&gt;parent element&lt;/em&gt; based on &lt;em&gt;its children element(s)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So with the introduction of the indomitable &lt;code&gt;:has()&lt;/code&gt; selector, my hopes and dreams were finally realised.&lt;/p&gt;
&lt;p&gt;For example, in the past, if I wanted to style my &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; elements in a particular way when it contains an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element, I’d have to do something like create a specific class that I would &lt;em&gt;also&lt;/em&gt; need to remember to include in my HTML:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;This is a heading&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;has-anchor&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span&gt;href&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;#_&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;This is also a heading&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;h2.has-anchor&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;/* apply specific styles */&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the &lt;code&gt;:has()&lt;/code&gt; selector, a lot of the mental overhead involved with that solution just floats away:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;This is a heading&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span&gt;href&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;#_&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;This is also a heading&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;h2:has(a)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;/* apply specific styles */&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When it comes to applying the settings on my website, I’m providing a series of &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements that visitors can use to control things like the colour scheme, theme, and smooth scroll. I’m applying a set of styles based on the selected &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; inside those &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements and their associated values in conjunction with the &lt;code&gt;:has()&lt;/code&gt; selector.&lt;/p&gt;
&lt;p&gt;Let’s look at the HTML for the colour scheme setting controls:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span&gt;for&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme-selector&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Light/Dark:&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;select&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme-selector&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;optgroup&lt;/span&gt; &lt;span&gt;label&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;Select a colour scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;selected&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;OS Default&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Light&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Dark&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;optgroup&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, I’m leaving it up to the browser / operating system to define whether a visitor prefers a light or dark colour scheme. When this setting is left alone, I can use a media query to match whatever this preference may be, e.g.:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@media&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;prefers-color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;html&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;/* apply dark colour scheme styles */&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if the visitor were to select either the &lt;q&gt;Light&lt;/q&gt; or &lt;q&gt;Dark&lt;/q&gt; options, I can use the &lt;code&gt;:has()&lt;/code&gt; selector to match their selection and apply those same styles:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;html:has([name=&quot;color-scheme&quot;] [value*=&quot;dark&quot;]:checked)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;/* apply dark colour scheme styles */&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Although this selector might look a little unwieldy, what it’s doing is checking the DOM to see if the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element contains an element that has a &lt;code&gt;name&lt;/code&gt; attribute whose values is &lt;code&gt;color-scheme&lt;/code&gt;, which matches the &lt;code&gt;&amp;lt;select name=&quot;color-scheme&quot;&amp;gt;&lt;/code&gt; element. And if the child element &lt;code&gt;&amp;lt;option value=&quot;dark&quot;&amp;gt;&lt;/code&gt; is selected, then apply my dark colour scheme styles.&lt;/p&gt;
&lt;p&gt;I’m using this same pattern for all of my website’s settings, and I couldn’t be more thankful that the fabled parent selector is finally a reality!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;storage-form&quot;&gt;&amp;lt;storage-form&amp;gt;&lt;/h2&gt;
&lt;p&gt;The last piece of the puzzle here is a critical one. Being able to open and close the settings popover and make some choices to control how to experience my website is one thing, but if those choices don’t persist when navigating between pages, then the settings could be more of a headache than the lovely feature that I’d like them to be!&lt;/p&gt;
&lt;p&gt;That’s where &lt;a href=&quot;https://darn.es/storage-form-web-component/&quot;&gt;&lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt;&lt;/a&gt;, a Web Component by &lt;a href=&quot;https://darn.es&quot;&gt;David Darnes&lt;/a&gt; that allows form elements to persist and be saved, comes in. It uses the browser’s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage&quot;&gt;Local Storage&lt;/a&gt; to save what the visitor has typed/checked/selected in form elements, and reads those saved values from Local Storage so they can be reapplied whenever the visitor navigates between pages and even when completely leaving the site and returning later.&lt;/p&gt;
&lt;p&gt;Usage is very straightforward and done by wrapping &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; elements with the Web Component:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&amp;lt;!-- settings form inputs here --&amp;gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, this &lt;em&gt;does&lt;/em&gt; mean that persisting visitor choices of settings between pages requires JavaScript, but I cannot overstate how useful this Web Component is. I feel so lucky that great folks like David are contributing to the ecosystem of Web Components!&lt;/p&gt;
&lt;p&gt;If you’re interested in exploring the wealth of amazing Web Components that you can just about drag-and-drop into your own projects and start using, I’ve got &lt;a href=&quot;https://github.com/stars/chrisburnell/lists/web-components&quot;&gt;a list of Web Components on GitHub&lt;/a&gt; that you might want to browse through.&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #10 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/website-settings/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/cluster-composition/</id>
		<link href="https://chrisburnell.com/article/cluster-composition/" />
		<title>The Cluster Composition</title>
		<published>2024-05-07T18:39:29+08:00</published>
		<publishedFriendly>7 May 2024</publishedFriendly>
		<updated>2024-05-09T17:34:01+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>In this post, I’m going to cover how I use a snippet of CSS for laying out list items that called the Cluster.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;In this post, I’m going to cover how I use a snippet of CSS for laying out list items that called the &lt;q&gt;Cluster&lt;/q&gt;.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;&lt;em&gt;The contents of this post require my website’s CSS to appear properly.&lt;br&gt;See the web version: &lt;a href=&quot;https://chrisburnell.com/article/cluster-composition/&quot;&gt;https://chrisburnell.com/article/cluster-composition/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://cube.fyi&quot;&gt;&lt;em&gt;CUBE CSS&lt;/em&gt; methodology&lt;/a&gt;, there is the concept of a &lt;q&gt;composition&lt;/q&gt;. In short, a composition is a piece of CSS that creates &lt;q&gt;flexible, component-agnostic layout systems that support as many variants of content as possible&lt;/q&gt;&lt;sup&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;While there &lt;em&gt;is&lt;/em&gt; a layout in &lt;a href=&quot;https://every-layout.dev&quot;&gt;Every Layout&lt;/a&gt; &lt;em&gt;also&lt;/em&gt; called &lt;a href=&quot;https://every-layout.dev/layouts/cluster/&quot;&gt;The Cluster&lt;/a&gt;, I’ve built my own version that serves a very similar purpose but achieves it with slightly-different CSS. I’m using my version of the &lt;q&gt;Cluster&lt;/q&gt; composition for a number of lists around my website: breadcrumbs, the category/tag lists on post pages, links in the footer, and &lt;a href=&quot;https://chrisburnell.com/note/slash-interests/#responses&quot;&gt;response types&lt;/a&gt;, to name a few.&lt;/p&gt;
&lt;p&gt;This composition uses CSS variables with fallback values as a means of creating variants. This means that when the composition’s CSS variables are &lt;em&gt;not&lt;/em&gt; set, the fallback value is applied, creating the &lt;q&gt;default&lt;/q&gt; version of the composition, so by &lt;em&gt;setting&lt;/em&gt; the CSS variables, we can modify the behaviour of the composition.&lt;/p&gt;
&lt;p&gt;Without further ado, here’s the code for my Cluster composition:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;.cluster &amp;gt; *&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; inline-block&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;.cluster &amp;gt; *:not(:last-child)::after&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--delineator&lt;span&gt;,&lt;/span&gt; &lt;span&gt;&quot;·&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;padding-inline&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;var&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;--padding-inline&lt;span&gt;,&lt;/span&gt; 1em&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;line-height&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 0&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;usage&quot;&gt;Using the Cluster&lt;/h2&gt;
&lt;p&gt;Using the cluster is done by applying the &lt;q&gt;cluster&lt;/q&gt; class to some HTML:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt; [ cluster ] &lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;One&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Two&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Three&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
    &lt;ul&gt;
        &lt;li&gt;One&lt;/li&gt;&lt;li&gt;Two&lt;/li&gt;&lt;li&gt;Three&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Styling my website’s breadcrumbs is done by setting the &lt;code&gt;--delineator&lt;/code&gt; variable to a desired value using a class or with inline styles:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt; [ cluster ] &lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;--delineator&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&#39;→&#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;One&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Two&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Three&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
    &lt;ul&gt;
        &lt;li&gt;One&lt;/li&gt;&lt;li&gt;Two&lt;/li&gt;&lt;li&gt;Three&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;And for cases where I want greater spacing between list items, I can set the &lt;code&gt;--padding-inline&lt;/code&gt; variable to a desired value:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt; [ cluster ] &lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span&gt;style&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;--padding-inline&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 2em&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;One&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Two&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Three&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
    &lt;ul&gt;
        &lt;li&gt;One&lt;/li&gt;&lt;li&gt;Two&lt;/li&gt;&lt;li&gt;Three&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Compositions are a seriously powerful concept that I’ve enjoyed using ever since learning about them from the indomitable &lt;a href=&quot;https://piccalil.li/&quot;&gt;Andy Bell&lt;/a&gt;, and it’s given me a really strong sense of control over the styles that I write.&lt;/p&gt;
&lt;p&gt;What methodologies do &lt;em&gt;you&lt;/em&gt; use when authoring CSS? Do you have any compositions that you find yourself using all over the place? I’d love to learn more about what gives &lt;em&gt;you&lt;/em&gt; a sense of control over your styles too!&lt;/p&gt;
&lt;hr&gt;
&lt;nav aria-label=&quot;Footnotes&quot;&gt;
	&lt;ol&gt;
		&lt;li id=&quot;fn1&quot;&gt;
			&lt;p&gt;&lt;a href=&quot;https://cube.fyi/composition.html&quot; rel=&quot;external noopener&quot;&gt;Composition | CUBE CSS&lt;/a&gt; &lt;a href=&quot;#fnref1&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
		&lt;/li&gt;
	&lt;/ol&gt;
&lt;/nav&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #7 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/cluster-composition/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/code/mixing-colours-different-spaces/</id>
		<link href="https://chrisburnell.com/code/mixing-colours-different-spaces/" />
		<title>Mixing Colours in Different Colour Spaces</title>
		<published>2024-03-05T04:58:00+08:00</published>
		<publishedFriendly>5 March 2024</publishedFriendly>
		<updated>2024-03-05T04:58:00+08:00</updated>
		<category term="code" scheme="https://chrisburnell.com/code/" label="Code Demo" />
		<summary>Visualise how different colour spaces will mix two given colours.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Visualise how different colour spaces will mix two given colours.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;&lt;c-codepen slug=&quot;PogqpMN&quot; height=&quot;800&quot;&gt;&lt;/c-codepen&gt;&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/code/mixing-colours-different-spaces/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/bookmark/some-use-cases-for-revert-layer/</id>
		<link href="https://chrisburnell.com/bookmark/some-use-cases-for-revert-layer/" />
		<title>Some use cases for revert-layer</title>
		<published>2024-02-14T10:27:37+00:00</published>
		<publishedFriendly>14 February 2024</publishedFriendly>
		<updated>2024-02-14T10:27:37+00:00</updated>
		<category term="bookmark" scheme="https://chrisburnell.com/bookmark/" label="Bookmark" />
		<summary>CSS Layers has been such a boon to wrangling specificity, and it’s really helped me get a better understanding of the CSS I write from a bird’s eye view. So I’m surprised that I’m just learning about revert-layer now, but super glad that this fabulously-comprehensive article by Mayank is what introduced me to it!</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;CSS Layers has been such a boon to wrangling specificity, and it’s really helped me get a better understanding of the CSS I write from a bird’s eye view. So I’m surprised that I’m just learning about &lt;code&gt;revert-layer&lt;/code&gt; now, but super glad that this fabulously-comprehensive article by Mayank is what introduced me to it!&lt;/p&gt;
				&lt;hr&gt;
			
			
			
			
			&lt;p&gt;Reference: &lt;a href=&quot;https://www.mayank.co/blog/revert-layer&quot;&gt;https://www.mayank.co/blog/revert-layer&lt;/a&gt;&lt;/p&gt;
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/bookmark/some-use-cases-for-revert-layer/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		<link rel="related" href="https://www.mayank.co/blog/revert-layer" />
		
	</entry>
	
</feed>
