Chris’ Corner: Variables

Fotolia Subscription Monthly 4685447 Xl Stock

CSS has a feature called Custom Properties. You know this.

html {
  --brandColor: red;
}

.card {
  border-color: var(--brandColor);
  
  h2 {
    color: var(--brandColor);
  }
}

People also — somewhat interchangeably — refer to these as CSS variables. Somehow, that doesn’t bother me, even though I tend to be a stickler about naming things. For instance, there is no such thing as a frontend developer. There are front-end developers who focus on the front end.

But here, the names feel like they make sense despite me not exactly nailing down how I like to see them being used. Like, Custom Property feels right. When I create --something, that’s used as a property in CSS but I just made up the name myself. It’s a… custom… property. And then I use it later with the var() function, which obviously stands for “variable”, because now this custom properties value has turned into a dynamic variable. So calling what is happening here a “CSS variable” seems entirely fine.

OK moving on I guess we need to talk about CSS variables for an entire issue.


Just the other week I was trying to see if there was a clean way to ask CSS what the value of cos(25deg) was. I feel like I got so close, trying both setting the value to a property that takes a unitless number and typing the variable first, but I couldn’t quite get it. There is a lesson here about never giving up, as Bramus proved by giving it a fresh college try and proving it absolutely can be done.


You totally do need to type variables sometimes, the 99% use case is allowing them to be animated which the browser can (mostly) on do if it knows the type. You could also consider it a form of “type safety” so hardcore TypeScript nerds will probably like it.


Above is about as niche of a situation as you can get.

What are CSS variables actually useful for?

I like thinking of the most common use case for things. The most common use case for grid is to put two things side by side. The most common use case for a <dialog> is an important confirm/cancel question. The most common use case for a popover is a footnote. The most common use case for SVG is a logo. For CSS variables, it’s a brand color.

Even on a fairly simple website, I’d bet there is one particular important color that you end up having to set a number of times. Using a variable for it just keeps things DRY and allows you to tweak it easily. That’s exactly the code I started this post out with. But variables are more and more powerful. Just that --brandColor is tweakable without changing it…

footer {
  background: color-mix(in oklch, var(--brandColor), black 20%);
}

Now if we tweak that brand color, we’re tweaking the tweaks (man).


Even wilder to me is that setting one custom property (see how effortless I can switch the term back and forth?) can have effects all over the place. This is thanks to container style queries.

Consider code like this:

@container style(--darkBackground) {
  > * { color: white; }
}

Now if --darkBackground is set (to any value at all) on any element, all direct children of it have white text. Support for this is pretty limited, so it’ll be a while until any of us have any strong understanding of how this will affect how we write CSS. To me, this is similar to :has() in how a change anywhere on the page can affect changes elsewhere in (I’d argue) unexpected ways. Powerful ways. Maybe useful ways. But unexpected ways. CSS used to be a pretty darn top-down language and that’s changing.


How about a feature with such limited support there… isn’t any. One of those things is the if() statement (woah), which is only useful for testing CSS variables. I’m a fan, but let’s not get all into that here. Another Lea Verou post is Proposal: CSS Variable Groups. Check it:

:root {
  --color-green: {
    100: oklch(95% 13% 135);
    200: oklch(95% 15% 135);
    /* ... */
    900: oklch(25% 20% 135);
  };
}

This turns into variables that are used like var(--color-green-200). Such a chill way to declare a set of variables without so much repetition. It’s just for authors, but that’s fine I think. CSS variables I feel like exist mostly in a post-pre-processing era (heh), so even though we’d probably abstract this with a loop or whatever in the past, we don’t have that anymore, so need syntactical help.

Chris’ Corner: Incremental Adoption

Fotolia Subscription Monthly 4685447 Xl Stock

One of the reasons I can’t stop thinking about native Web Components is how you can use them anywhere. “Incremental adoption” is the fancy phrase, I suppose.

We’ve even started using them on the new editor for CodePen we’re still hard at work on to solve some interesting issues I’m sure we’ll talk about someday. We’re using React/Next there, which isn’t famous for it’s support of Web Components, but it’s mostly been fine. Other JavaScript frameworks are much more friendly, and of course if you aren’t using a JavaScript framework you haven’t a care in the world; Web Components can be part of your world.

Because they are pretty easy to slip in anywhere, they work pretty well on CodePen. I mentioned a list of “stand alone” Web Components the other week here at the ol’ Corner, then I converted them into Pens just to prove that. A lot of web components are published to npm to using a site like esm.sh makes linking up the resources pretty easy.

What’s cool about using web components like I have above is that they just might last forever. I ranted a little about this on Mastodon the other day. The fewer dependencies a web component has, the longer it will last. It will certainly outlive your JavaScript framework, as Jake Lazaroff put it:

If we want our work to be accessible in five or ten or even 20 years, we need to use the web with no layers in between. For all its warts, the web has become the most resilient, portable, future-proof computing platform we’ve ever created — at least, if we build with that in mind.

I think that’s cool.

I makes me think what will break about those demos I posted. Like, what is going to make this Pen stop working someday? If CodePen goes offline, it will. But we’ve just had our 12th birthday are are going strong. You’d have to fight me to the death for that to happen. The web component is linked up from esm.sh so if that went down it would stop working. That’s definitely possible, we’ve seen free CDN-like websites like this come and go. But you could just change to a different one. The code is on npm, so that could die or the author could pull it down. But there doesn’t seem to be a lot of risk of that, and it’s open source so mirrors will exist. Pretty resilient, I’d say! Although different projects have different needs there and you could always get stronger by reducing even those dependencies.

Oh hey speaking of web components and things that are super cool… check out David Darnes new one just for us: <code-pen>.

The idea is that it’s a convienient way to use our Post to Prefill API. So you’d author code like this:

<script type="module" src="code-pen.js"></script>

<code-pen>
  <pre>
    <code>&lt;p&gt;Hello world&lt;/p&gt;</code>
  </pre>
  <pre>
    <code>:root { color: hotpink; }</code>
  </pre>
  <pre>
    <code>document.querySelector(&quot;p&quot;).style.backgroundColor = &quot;orange&quot;;</code>
  </pre>
</code-pen>

(Or you could use Markdown triple backticks and avoid the code escaping, among other options)

Then it builds an “Open in CodePen” button that users can click to open that code in a real Pen. The point is usually stuff like documentation and blog posts where you want to manage all the code yourself, not maintain both the text and the Pens separately. Thanks David, this is super cool.

David also recently published a free eBook called The Case for Web Components you might want to check out if you’re looking to be further convinced or need more learnings on the basic to decide. In it, he mentioned the use case of “design systems”, which seems like an awful big one to me. These days, if you’re creating a design system, doing it in anything other than web components seems weird. Web components will last and be movable between frameworks as your project evolves, with little if any downside.

While we’re on the subject let’s just get a little more into the weeds.

Ultimately a Web Component is a class in JavaScript. It has standard methods, like a constructor that is called when the class is instantiated. It also has a method connectedCallback that runs when on each instance of a web component when it shows up in the DOM. This is a bit of a subtle difference and can be quite a gotcha, as Nolan Lawson says. If your component needs to do stuff that might be unique to each instance, that belongs in connectedCallback. I think it’s a real superpower of web components! For example, it’s kinda like getting event delegation for free.

There is an approach to web components called HTML web components which is essentially:

  1. Take some perfectly acceptable HTML
  2. Wrap it in a <web-component> to extend the functionality

That’s fun and obviously useful (e.g. a blog post with a web component would render fine over RSS). It’s related but not quite the same declarative shadow DOM. Raymond Camden explores something interesting here… how does a web component know if the HTML inside it changes? Unfortunately there is no obvious solution or helper API for this… other than the platform itself. The trick is that you use a MutationObserver on itself internally to watch for changes and then do whatever you gotta do. Interesting stuff. I’d be tempted to rip the whole thing out of the DOM and replace it just so connectedCallback does it’s thing, rather than craft every web component such that it’s watching for it’s own changes.

I hadn’t really thought that much about watching for changes like that before, as it just hasn’t come up for me. Similarly, Ben Nadel points out that the contents of a <template> can be mutated at any time, and new components instantiated off it will use that new content. That makes sense to me, it’s just a twist of how I normally think of components. I think of the template as this static thing which takes data and does what it needs to do. Less so do I think of a template itself that is dynamic based on data.

Chris Corner: Git it

Category Image 080

Julia Evans has released what she’s saying is one of her most popular zines to date: How Git Works.

I don’t think you’d regret reading it. I imagine most of us get by with knowing just enough Git to do our jobs, but are probably using 5% of what it can really do. Being very strong with Git will almost surely benefit you in your career. Imagine helping a superior out of a sticky situation where it might look like code was lost or otherwise screwed up. Being the solution during an emotional time is clutch. Surely this pairs nicely with Oh Shit, Git!, a real classic from Katie-Sylor Miller which I see has been revitalized with Julia here.


Just the other day here at CodePen Headquarters, I saw a co-worker solve an issue with git bisect. Have you even heard of that?! Imagine there is a bug in your code, but you have absolutely no idea when it happened or where in the code it might be. That’s not a good feeling, but it’s exactly where git bisect comes in. As best I understand it, it sets the HEAD of your repo back in time some amount, and there, you test if the bug is present and you can say git bisect good or git bisect bad. Then it moves the HEAD and you keep testing and eventually it gets closer and closer to the exact commit (or at least a range of commits) where the bug happened. Then you can look at the changed files in those commits and figure out where in the code the bug may have came from. So cool!


I certainly know developers who know Git and work with it exclusively at the command line entirely as-provided. But I find it more common among the command line types that they at least have some aliases set up for the most common things they do. Those might be their own aliases, like they’ll make gco do a git checkout, but it’s worth knowing git itself allows you to make aliases within itself, which could be good since they won’t conflict with anything else. (Have I told you how long I had cp aliased to move to our local CodePen project directory? 🤣).


A much more elaborate take on git aliases is called Gut. With it, you don’t git commit anything (with all the params and whatnot you have to also pass), you gut save which launches a little wizard that asks you questions, and then it does the proper git stuff with the information you give it.

I could see that being great for a beginner, but maybe feel a little too slow as you get more comfortable at the command line. Except when it comes to the more advanced stuff and how it looks designed to get you out of binds. The fix and undo commands like awfully helpful and are the kind of things where I can never remember the proper commands.


Paweł Grzybek lays out a classic situation:

Let’s say that we are halfway through the feature, intensely focused on a task, when a critical bug needs to be fixed out of the blue. Happens to us all the time! Should we stash the current changes? Should we quickly smash git add . && git commit -m "wip" and promise that we will sort this mess out later?

His answer is no, it’s using git worktrees. It solves the issue by literally making another copy of your project on disk. And you can open and work on it separately but it all goes to the same repo ultimately. So you can leave your half-done uncommitted work on another worktree while you hop to the other to do work. Me, I’m mostly cool with git stash to tuck stuff away while I go work on something else, or even just the ol “work in progress” or “saving work” commit like Paweł mentioned. It’s not pretty but culturally it’s fine on our project. But I can see how you could get into a groove with worktrees, particularly if your editor supports it nicely.


Phew! We probably talked about Git too much, eh? I know nobody cares. Now let’s go back to just doing the 3-4 commands we know everyday, just with a few more resources in our pocket when we need them.

I gotta leave you with something else. (Digs through bag of hot links.) Ah here we go. This video rules: Flash is dead so I rebuilt it with javascript. Andrew Jakubowicz walks us through building an interface with a pretty modern and lightweight set of tools. Andrew works for Google on Lit, so it’s sort of a big excuse to show off working with Web Components, but it’s a fun ride. At 8 minutes more happens than a typical hour long video.

Chris’ Corner: Let’s Look at Type!

Typography Definitions Cover

Dan Mall has my favorite post on picking a typeface. I’m no master typographer, but I know enough that I don’t want to be talked to like an absolute beginner where you teach me what a serif is. Dan gets into more realistic decision making steps, like intentionally not picking something ultra popular, admitting that you have to be around a lot of type to make good type decisions, and that ultimately choosing is akin to improvising in jazz: it’s just gotta feel right.

If you are a beginner, or really just like type, you’d do well carving out half an hour to watch the 6 parts of Practicing Typography Basics from Tim Brown who sounds like he’s at absolute zen at all times. Each of these videos only has a few thousand views which feels like a damn shame to me as they are super good and hit all the most important stuff about typography.

Now let’s have more fun and just look at some actual typefaces I’ve bookmarked lately.

MD IO

I just love this so much it’s one of those typefaces that make me want to find a project just to use it on.

Jgs

Jgs Font glyphs can be combined from one character to another, from one line to another. Thus from single characters it is possible to draw continuous lines, frames and patterns.

Nudica

The pricing atipo foundry does for their fonts (“pay what you want”) is awfully generous.

mononoki

a font for programming and code review

I’ve got this on my list of potential fonts to add to CodePen when I get to doing another round of that.

F.C. Variable

An exploration by Rob en Robin about using the axes of variable fonts to control illustrations. Wild!


Oh and kinda just for myself, I want to remember two fonts Dan mentioned. He said he doesn’t pick these as they are almost too popular, but I don’t know them well and that popularity kinda intrigues me honestly.

Two of the most popular typefaces on Typewolf are Grilli Type’s GT America and Lineto’s Circular. You can’t go wrong with those. They look great and they won’t offend anyone.

Chris’ Corner: Variations on What Not to Do

Fotolia Subscription Monthly 4685447 Xl Stock

I think the nail is in coffin now: you should never design something for the web with only one (or even a narrow set) of particular viewport sizes in mind. It’s just so darn tempting to think that way. You have a couple of pretty specific screen sizes in front of you right now, you likely design toward those to some degree. Design tools often ask you to draw a rectangle that represent a screen to design for. Testing tools sometimes show you a site at a set of pre-set screen sizes. It can feel normal and fine to design toward, say, three sizes, and hone in on them. Honestly, that might end up working fine, but it might not! It might lead to some awkward in-betweens, especially if you are very rigid in writing CSS that only changes at those specific breakpoints only.

That’s the thing, really. You just don’t have to think in really specific breakpoints anymore. Media query width breakpoints are still a fine tool, but now we’ve got viewport units, container units, container queries, calc/min/max/clamp, and all sorts of other stuff that allow you to design components and pages that work well and look good at the size and under the conditions they are in. It’s just a better way to code. But this stuff has only relatively recently arrived in CSS so it’ll take a minute for it all to settle in.

This isn’t even really new news. Over a decade ago, I was like, yo, there are a ton of different sizes that your site is getting viewed at. Deal with it. Now we can properly.

AND NOW FOR SOMETHING COMPLETELY DIFFERENT

Have websites gone to crap? Browse around popular sites, and I think you’ll land on an easy yes. Especially on mobile, cripes. Just to name a few: they are too slow to load, the ads and popups are too obtrusive, and there is too much usage of fixed-position elements that reduce usable area.

This website User Inyerface satirized it recently, and it’s pretty funny (ya know, if being intentionally frustrated is your thing, gamers should relate).

People have been worried about this for ages, and it never seems to get any better.

This all just makes me sad. Fortunately, most things are fine.

AND NOW FOR SOMETHING COMPLETELY DIFFERENT

Have you seen the popover API? It’s a neat idea, already play-with-able in Chrome. Think styled tooltips. The idea is that you connect some interaction (click of a button) to toggling another element with more information or context. Amazingly, to me, this HTML totally works in Chrome with no CSS or JavaScript at all:

<button popovertarget="my-popover">Open Popover</button>

<div id="my-popover" popover>
  <p>I am a popover with more information.</p>
</div>

You can style stuff with CSS of course, but the basics of the interaction work without. Like a <details> element.

Anytime we get any form of “state management” outside of JavaScript, the people will play! There are countless games made in CSS thanks to the whole idea of the :checked selector in CSS and using the ~ combinator to select other elements.

This time, leave it to Garth Heyes who has made Tic-Tac-Toe entirely in HTML only. That’s gotta be a first.

Wanna see it? Fair warning first. It’s 170 MB (!!) of HTML and “over half a million nodes”. Chrome really struggles with this. It took my machine maybe near a minute to even render the first page, and each click took a while as well. If you’re down try it, see the demo.

AND NOW FOR SOMETHING RELATED BUT DIFFERENT

So now that we’ve looked at something you absolutely shouldn’t do on the web, here’s Heather Buchel with some things you absolutely should do on the web. Heather ain’t even mad that we’re building websites with newfangled tech and trying to share code across platforms and all that, but, just, like, don’t break stuff. Don’t break super duper basic stuff that websites easily do and are good for everyone. I’ll hijack her whole list, but of course go read it for more context:

  • Let me copy text so I can paste it.
  • If something navigates like a link, let me do link things.
  • Let me zoom in on my browser without the website getting all out of whack.
  • Do responsive things.
  • Let me have hover styles.
  • If the UI completely changes when I click on something, as if I’ve navigated to a new page, give me a browser history update and a new URL.
  • Let me see scroll bars.
  • Stop hijacking my typical browser shortcuts for use in your own app.

Reasonable asks, no?

AND NOW FOR SOMETHING ALONG THOSE SAME LINES

Onnnnneeee more thing you should be really careful about doing on the web. Adam Silver: The problem with sticky menus and what to do instead.

One problem is fairly obvious with sticky menus: they overlap stuff! They get in the dang way far too often.

But there are other things that cause problems that you might not see right away. Adam mentions zooming. One little zoom or too might kick a sticky/fixed element right off the page. Also, if something opens a sticky menu, and that menu happens to be taller than the viewport, you’ve got issues. You either need that area to be scrollable (but nested scrolling sucks) or you require users to scroll likely further than they want to just to see more of the menu. Ughghadk.

Adam lists three more that are just as bad or worse, and even less obvious at first glance. I’ll force you over there to see them. But I’ll snag the good ending, featuring the alternatives:

  1. Keep pages short: Sticky menus are a symptom of long pages so fix the root cause.
  2. Just let users scroll: It’s a myth that scrolling is a problem. Even on mobile, the top of the page is a flick or 2 away mostly.
  3. Put relevant links in context: For example, add a subscribe form to the end of a post or add a CTA to a pricing section.
  4. Use a back-to-top link: They’re relatively unobtrusive (but only do this once you exhaust the other options).

Chris’ Corner: Monaspace

Typography Definitions Cover

I’m a sucker for a new coding font. I generally don’t think what coding font you use affects productivity in any significant way (unless it’s distracting) so farting around and switching it up is just a fun little thing to do. Like pushing around the furniture in your room or taking a different bike route to work.

So count me in for playing with GitHub’s new set of monospace coding fonts: Monaspace.

(Before I get too far without mentioning it, you can use them on CodePen just by visiting your editor settings and picking one.)

The fact that there is five different stylized versions alone is pretty note worthy, but there are a variety of other features that are pretty darn cool. Texture Healing feels like a made up term, but what it does is pretty easy to understand and clearly useful.

It basically makes it so wide letters don’t have to scrunch themselves and narrow letters don’t have to exaggerate themselves. They say:

Texture healing works by finding each pair of adjacent characters where one wants more space, and one has too much. Narrow characters are swapped for ones that cede some of their whitespace, and wider characters are swapped for ones that extend to the very edge of their box.

Which is done with the OpenType feature “contextual alternates”. It’s a little bit like a ligature, where certain character combinations flop out into a new glyph that works best with them together, only, ya know, slightly different.

Monaspace has ligatures too. Ligatures are pretty controversial in coding fonts. For instance some people really hate that != might turn into as a ligature as that is like a deviation from the literal syntax of the language you may be writing. They aren’t my favorite but it’s not a firmly held opinion and it’s easy enough just to not use them. (They aren’t enabled on CodePen, as it seems like it might be confusing for some beginners.)

They come as a variable font, which I love because variable fonts rule. And it’s not a phoned in variable font with one measly axis, it’s weight, and width, and slant, which is wonderful.

The download comes both with variable and non-variable versions. If you don’t plan to use the variable-ness, the variable fonts are an order of magnitude larger so probably use the non-variable versions. If it’s not on the web it probably doesn’t matter. Also curious they only shipped .woff and not .woff2?

My very favorite idea they have around this “superfamily” is the idea of mixing and matching them for different reasons in the same UI.

The idea of having an italic monospace is starting to be more and more common. Gotta shout out the OG Operator for breaking that ground. Setting comments in italics is still just a super cool idea to me. Now we could use Radon for that, a different typeface entirely designed for it. In the image above, they suggest JSDoc-style comments using Xenon and GitHub CoPilot using Krypton. I love it. Ship it. (But I don’t think it’s possible in VS Code yet, but considering Microsoft makes both, you’d think it’s coming.)

To make that possible, essentially, you need syntax highlighting tools to provide tokens/classes that make it easy to identify different Aspects of code. It’s certainly possible, and probably not even that hard, but it’s probably a somewhat tricky thing to roll out with so many third-party themes out there.

But anyway, how great is this?


If you’re into playing with different coding fonts, well make sure to explore the fact that we have over 20 of them on CodePen to switch between. But of course there are far more than that out in the wild. A great read about the landscape of “playful and fun” coding fonts is Doug Wilson’s Coding with Character. Doug dug (ha) up this great example of IBM “SELECTRIC” TYPE SAMPLES (literally different typewriter fonts you could swap between by replacing a metal ball in the typewriter):

So cool! I love that this new wave of coding fonts is kind of a callback to what was happening here, whether everyone recognizes it or not. The first one Doug mentions is Operator which I used for years and years after it came out and still love. The second is Comic Code:

My first thought: This has to be a joke, right?! Comic Sans has a bad reputation and was never meant to be used for coding—but what if…? That is what crazy mastermind Toshi Omagari seemed to ask.

He says, “Comic Code is a monospaced adaptation of the most over-hated typeface.” I haven’t asked, but I feel his thought process may have been something like this GIF.

Believe it or not, I think it actually works and certainly brings a smile—or at least a smirk—to your face

Totally agree! It works!


While I was in our code base putting in the Monaspace fonts, of course I couldn’t resist doing general code cleanup. The Monaspace fonts only ship in .woff, so the @font-face in CSS is pretty much as simple as:

@font-face {
  font-family: 'Font Name';
  src: url('./fonts/font.woff') format('woff');
}

You can get away with only shipping in woff2 these days, so some of our fonts that have that format, that’s exactly what I’m doing. The simplicity there just feels great since this used to be such a complex bit of code in the past with loads of formats.

Then I recently learned from an Ollie Williams blog post that you don’t have to put the format as a string anymore, keywords work, so:

@font-face {
  font-family: 'Font Name';
  src: url('./fonts/font.woff2') format(woff2);
}

Gotta appreciate those little things 😍. Check out Ollie’s post for other cleanups with @font-face including how you specify variable fonts, color fonts, other other font “tech”.

Chris’ Corner: People Be Doing Web Components

Fotolia Subscription Monthly 4685447 Xl Stock

Native Web Components are still enjoying something of a moment lately. Lots of chatter, and a good amount of it positive. Other sentiment may be critical, but hopeful. Even more important, we’re seeing people actually use Web Components more and more. Like make them and share them proudly. Here are some recently:

  • David Darnes made a <storage-form> component. Here’s an example that happens to me regularly enough that I really notice it. Have you ever been on GitHub, typing up a PR description or something, but then accidentally navigated away or closed the tab? Then you go back, and everything you typed was still there. Phew! They are using the localStorage API to help there. They save the data you type in the form behind the scenes, and put it back if they need to.
  • Dave Rupert made <wobbly-box>, which draws a border around itself that is every so slightly kittywampus. It uses border-image which is nigh unlearnable so I’d be happy to outsource that. Also interesting that the original implementation was a Houdini paint worklet thing, but since that’ll never be cross-browser compatible, this was the improvement.
  • Ryan Mulligan made a <target-toggler>, which wraps a <button> and helps target some other element (anywhere in DOM) and hides/shows it with the hidden attribute. Plus toggles the aria-expanded attribute properly on the button. Simple, handy, probably catches a few more details that you would crafting it up quick, and is only like 1KB.
  • Hasan Ali made a <cruk-textarea> that implements Stephen’s trick on auto-growing text areas automatically. Probably isn’t needed for too much longer, but we’ll see.
  • Jake Lazaroff made <roving-tabindex> component such that you can put whatever DOM stuff inside to create a focus trap on those things (as it required for things like modal implementations). I think you get this behavior “for free” with <dialog> but that assumes you want to and can use that element. I also thought inert was supposed to make this easier (like inert the entire body and un-inert the part you want a focus trap on), but it doesn’t look like that’s as easily possible as I thought. Just makes this idea all the more valuable. Part of the success story, as it were.

Interesting point here: every single one of these encourages, nay requires, useful HTML inside of them to do what they do. Web Components in that vein have come to be called HTML Web Components. Scott Jehl took a moment to codify it:

They are custom elements that

  1. are not empty, and instead contain functional HTML from the start,
  2. receive some amount of progressive enhancement using the Web Components JavaScript lifecycle, and
  3. do not rely on that JavaScript to run for their basic content or functionality

He was just expanding on Jeremy Keith’s original coining and the excitement that followed.

Speaking of excitement, Austin Crim has a theory that there are two types of Web Components fants:

  1. The source-first fans. As in, close to the metal, nothing can break, lasts forever…
  2. The output-first fans. As in, easy to use, provide a lot of value, works anywhere…

I don’t know if I’m quite feeling that distinction. They feel pretty similar to me, really. At least, I’m a fan for both reasons. We could brainstorm some more fan types maybe! There’s This is the Best Way to Make a Design System group. There’s the This is Progressive Enhancement at its Finest group. There’s the If Chrome Says it’s Good, Then I Say it’s Good group. There’s the Ooooo Something New To Play With group. Your turn.


Let’s end here with two things related to the technology of Web Components you might want to know about.

One of the reasons people reach for JavaScript frameworks is essentially data binding. Like you have some variable that has some string in it (think: a username, for example) and that needs to make it’s way into HTML somewhere. That kind of thing has been done a million times, we tend to think about putting that data in braces, like {username}. But the web platform doesn’t have anything like that yet. Like Rob Eisenberg says:

One of the longest running requests of the Web Platform is the ability to have native templating and data binding features directly in HTML. For at least two decades innovative developers have been building libraries and frameworks to make up for this platform limitation.

The Future of Native HTML Templating and Data Binding

DOM Parts is maybe the closest proposal so far, but read Rob’s article for more in-depth background.

Another thing I’m interested in, forever, is the styling of Web Components. I think it’s obnoxious we can’t reach into the Shadow DOM with outside CSS, even if we know fully what we’re doing. The options for styling within Web Components all suck if you ask me. Who knows if we’ll ever get anything proper (the old /deep/ stuff that had a brief appearance in CSS was removed apparently for good reason). But fortunately Brian Kardell has a very small and cool library that looks entirely usable.

Let’s say you are totally fine with making a request for a stylesheet from within a Web Component though, how does that work? Well there is a such thing as a Constructable StyleSheet, and if you have one of those on hand, you can attach it to a Shadow Root via adoptedStyleSheets. How do you get one of those from requesting a CSS file? The trick there is likely to be import assertions for CSS, which look like:

import sheet from './styles.css' assert {type: 'css'};

Now sheet is a Constructable StyleSheet and usable. I like that. But let’s say you’re bundling your CSS, which is generally a smart thing to do. Does that mean you need to start breaking it apart again, making individual component styles individually importable? Maybe not! There is a proposal that looks solid for declaring individually importable chunks of CSS within a @sheet block. Then, just like non-default exports in JavaScript, you can pluck them off by name.

@sheet sheet1 {
  :host {
    display: block;
    background: red;
  }
}

@sheet sheet2 {
  p {
    color: blue;
  }
}
import {sheet1, sheet2} from './styles1and2.css' assert {type: 'css'};

Pretty solid solution I think. I’d be surprised if it didn’t make it into the platform. If it doesn’t, I promise I’ll go awww sheet.

Chris’ Corner: Tricks With CSS

Fotolia Subscription Monthly 4685447 Xl Stock

There are plenty of very legit reasons you’d want to have a scrolling element start out scrolled to the bottom, and stay scrolled to the bottom (as long as a user hasn’t scrolled back up). As ever, you could do this with JavaScript, as JavaScript can adjust scroll positions of elements. There is a way to do this primarily with CSS now that the anchor-overflow property exists, and I think it’s an extremely great CSS trick.

There is another way though! Kitty Giraudel covers it in CSS-only bottom-anchored scrolling area. The base of the trick is quite simple and requires no additional elements. You just set flex-direction: column-reverse; and then put the HTML inside in reverse order. So the stuff you want pinned at the bottom visually you put at the top of the element. In a way, this makes sense to me, as the thing you want to read first is at the top.

Element with scrolling pinned to bottom (as long as you add the stuff at the visual-bottom to the top of the DOM). Think of a chat interface.

But there is an accessibility concern that Kitty notes. It “creates a disconnect between the visual order and the DOM order, which can be confusing for screen-reader users.” I’d want to verify that with a screen reader user I think (probably applies mostly to people who use a screen reader and have some vision). But it’s a good point and a classic problem that comes up any time you use CSS to position things in such a way they appear visually differently than the source order suggests. I’m sure you can imagine the akwardness of focus states jumping around the screen unpredictably.

The thing that makes all this so news-worthy to me is that CSS is working on a solution for this that I didn’t know about:

reading-order: normal | flex-visual | flex-flow | grid-rows | grid-columns | grid-order

In our case, we could use reading-order: flex-visual to align the way sighted users and screen-reader users consume our feed.

So we’ve reversed the order using flexbox, but we can make the elements still read top-to-bottom (visual order) by forcing it with this property. I might argue, again, that in this case, users might want to read bottom-to-top. But at least you’ve got options now.

And this reader-order stuff is generally interesting. Like if you use flexbox and totally mess with where the flex items are placed with the order property, placing, for instance, the 7th item in the 2nd place, and the 19th item in the 1st place, updating the reading order to flex-visual will be great. I notice there is no grid-visual though, which is curious, since you can mess with the order of grid just the same.


Jonathan Snook has a play with the idea of lenticular cards. Those are those ridged plastic novelty cards that have two different images you can see depending on the angle you look at it from. Or more!

Since Apple released Live Photos, I’ve always felt like they could be used to create a similar effect and yet, no photo app that I’ve seen has implemented it, from what I’ve come across.

I enjoyed playing with the demo on mobile (where the DeviceOrientation API is a thing):

I love the experimentation spirit here. Like thinking of something you think should exist, but doesn’t seem to in an obvious way, then building it anyway.

Yair Even Or had the idea that a box-shadow could be cool if it… wasn’t actually a shadow, but was a blur instead.

The implementation is that perfect tornado of cleverness that appeals to me. It’s not incredibly complicated, but it requires usage of a number of different CSS features that you not think about immediately. In the end, it’s:

  • Place a pseudo element behind the element, a specified amount larger than the original element.
  • Blur the background with that pseudo element using backdrop-filter.
  • This doesn’t “fade out” the effect like a box-shadow would naturally, so instead, two masks are used to fade out the effect (vertical and horizontal).
  • Mask compositing is used to combine the masks.

I think the two masks are needed because of the rectangular nature of the element. I’d be tempted to try it with a single radial-gradient, but I think you’d lose blurring near the corners.


Dan Wilson always does a good job looking at new CSS features and the possibilities they unlock. Particularly the new features that are a bit esoteric, or seem to be at first glance, like math functions.

In The New CSS Math: pow(), sqrt(), and exponential friends, Dan looks at those new CSS functions (and a few more), and point out some somewhat practical things they can do. For example, a typographical system where the header sizes aren’t a straight multiple of one another, but are grown on a curve. Or simulating an easing effect by animating a number linearly, but having the movement distance calculated by a pow() on that number. There is even a function now that makes quick work of the Pythagorean theorem.

If you’re into this stuff, Dan looked at rem() and mod() here, which are similar methods for determining what is left over when you divide a number into another number. Is 9 divisible by 3? Yes, and you can know if the remainder is 0. But in web design, you could do things like figure out how many 125px grid columns could fit into 693px of space, if you needed to.

Dan has looked at trig functions as well, and shortly after that, Hypersphere looked at simulating randomness in CSS with those functions. The sin() function, for example, modulates from -1 to 1. So by farting around with that and incorporating a seed value, you can build pretty darn random looking CSS output:


The can’t-miss link recently is Ahmad Shadeed’s An Interactive Guide to CSS Container Queries. His interactive guides are always outstanding. This one is full of practical examples of where container queries are useful.

Chris’ Corner: Real World CSS

Category Image 035

I enjoyed Lee Robinson’s take on How I’m Writing CSS in 2024. Rather than jump right into tools and syntax, it starts with the user:

What does a great experience look like loading stylesheets when visiting a website?

  1. Stylesheets should load as fast as possible (small file sizes)
  2. Stylesheets should not re-download unless changed (proper caching headers)
  3. The page content should have minimal or no layout shift
  4. Fonts should load as fast as possible and minimize layout shift

Agreed! Number 3, and to some degree 4, are almost more in the JavaScript bucket than CSS, but it’s a good starter list. I’d add “The page styles shouldn’t interfere with default accessibility”.

Then, after those, the developer experience is considered:

How can the DX of the styling tools we use help us create a better UX?

  1. Prune unused styles, minify, and compress CSS for smaller file sizes
  2. Generate hashed file names to enable safe, immutable caching
  3. Bundle CSS files together to make fewer network requests
  4. Prevent naming collisions to avoid visual regressions

What about to help us write more maintainable, enjoyable CSS?

  1. Easy to delete styles when deleting corresponding UI code
  2. Easy to adhere to a design system or set of themes
  3. Editor feedback with TypeScript support, autocompletion, and linting
  4. Receive tooling feedback in-editor to prevent errors (type checking, linting)

I like how the DX concerns are about making things easier that the UX demands. I want all that stuff! Although I admit I still bristle at the idea of dealing with unused styles. It’s very hard to properly detect unused styles and I worry about tools making those decisions.

Lee’s ultimate recommendations are CSS Modules, Tailwind, or StyleX (or just vanilla CSS on simple stuff), and I feel like those feel fair based on his own journey and accomplish the things he laid out. I’m a fan of the CSS Modules approach myself. It’s largely vanilla CSS, but with great scoping built in, it couples to components nicely, and is so well established it’s everywhere you need it.


Speaking of writing CSS in the real world, Ahmad Shadeed did quite a deep dive of looking at the TechCrunch Layout and approaching it with modern techniques.

Sure, it’s just a three column layout, but the different columns have all sorts of different constraints. The first is in a fixed position, the main content has a maximum width but is otherwise fluid as well as contains nested grids. There is a maximum width overall too, with the third column involving absolute positioning. That’s without getting into the (five!) major breakpoints and footer complexities. If you’re into nerding out on CSS layout, Ahmad tackles it literally five different ways, ultimately landing on a nice CSS grid powered technique. He called it easy to implement, but looking at the column declarations I think it only looks easy to someone who was on his fifth iteration. 🤣. And that’s only half the article.


To think that Ahmad’s tackling of a complex layout, in the end, only boiled down to a few lines of CSS is rather incredible. CSS is certainly more powerful. But is it easier? Geoff Graham thinks yeah, it is a little easier to write actually, in some ways.

To name a few, grouping styles is easier, centering is easier, translation needs are easier, and spacing is easier. Geoff names more. And by easier, really truly easier in all ways. Less and more direct code that is easier to reason about and does what it says.


Roman Komarov outlines The Shrinkwrap Problem, which is maybe a little niche but certainly a very interesting layout situation. The deal is that if content wraps, the element essentially takes up all available width. Not that strange, but when you look at how a wrapped title looks with text-wrap: balance;, for example, it looks a little weird. A header might only take up half the space visually, yet still take up all the available space.

Roman goes really deep on this, with solutions that involve even new tech like anchor positioning which is an awfully weird thing to invoke just for this, but hey, needs are needs. Just when you think this is all far too much for such a niche thing, Roman gets to the use-cases which are actually pretty basic and straightforward. Things like chat bubbles where full-width bubbles would look awkward. Or decorations on either side of a header.


David Bushell has a fun and illuminating post about button-specific CSS styles.

Have you ever repeatedly tapped on a button only for the page to zoom in unexpectedly? Rewind and fast-forward buttons in an audio player for example. This unwanted side effect can be removed with touch-action.

There are four others in there that are all in the decent-chance-you-hadn’t-thought-of-it category.

Chris’ Corner: Type

Typography Definitions Cover

I’m in the mood for a typography focused edition. I have some links saved up I’ve been meaning to read. I’m going to start reading now and the links that turn out any good I’ll put below.


Mike Mai put together a Typography Manual (for type on the web). It’s a pretty random spattering of 11 bits of advice. Originally a Pen! I can’t help but read through each of them and raise my Well, Actually finger, but I shall keep my finger down because more and more I like eliminating nuance in this industry. Just do this advice is pretty valuable. If you have no idea where to start, well, just follow the advice, and once you’ve leveled up you can do your own rule breaking.

Like #1 is “Use One Font” but Henry, as a very experienced designer, can do what he wants.


This was mid-last-year, but I still think Stephanie Eckles has the best guide at the moment for modern fluid type. There was this whole period where “fluid type” meant using viewport units (e.g. vw), ideally in a calc(), to set type size (and sometimes line-height). Then things got a little better when we got clamp() because the code got a lot more straightforward (by the way, this is a helpful mind trick). Now things are changing one more time, because we have container units and they change the approach again.

Just as 1vw equals 1% of the viewport width, so does 1cqi equal 1% of a container’s inline size. We’ll be using cqi for purposes of defining fluid typography since we want the size to be associated with the horizontal axis of the writing mode.


Speaking of relatively new units, we now have units that represent the current line height (and “root” line height) in CSS: lh and rlh. Paweł Grzybek writes about how to use them to acheive the idea of “vertical rhythm”:

Vertical rhythm is a design concept that helps to create a harmonious layout by following consistent spacing between elements, typically using the height of a line as a base. I learned it in my design days when printed media was still a thing.

It’s kind of an invisible idea that theoretically makes a page more pleasant to look at.

In the past this was quite a bit harder to pull off, and these units are yet another example of a new CSS technology making an old idea a lot easier.


The why of typography is interesting. There are aesthetics. Making type look good is an art, but it’s an art with everyday consequences. Poor typography can make people feel a product is shoddy, a restaurant doesn’t care, or a service isn’t trustworthy. Great type can be a cheat code in making people choose one thing over another simply through aesthetics. But another Aspect of typography is legibility. If you want people to read text, and you do (and maybe even have them feel a certain way while reading it) then you’re very concerned with legibility.

Mary C. Dyson has a whole new book on this: Legibility. It’s certainly a book-worthy topic, as Mary makes clear in an early chapter:

Within typographic and graphic design, we might consider whether signs are legible (in particular from a distance), whether we can decipher small print (especially later in life), if icons can be easily identified or recognised (without text labels), if a novel or textbook is set in a readable type (encouraging us to read on). These questions emphasise that it is not only the physical characteristics of the text or symbol that need to be considered in determining whether or not the designs are legible, or how legible they are. The purpose for reading, the context of reading, and the characteristics of the reader also determine legibility.

My mind goes: pick fonts that are obviously readable, be generous with line height, don’t make the line length too long, and go big (but not too big). But that’s like legibility 101, and there is a lot more to consider, and a lot more depth to those basics.


Where do you actually go to find fresh fonts? I wish I had a perfect answer for you, but there are hundreds of font foundries with individual websites that all do things differently. My best advice is to bookmark them when you come across them, and when it’s time to pick fonts, make plenty of time to go window shopping.

Here’s one to save for sure though, because although I’m usually quite happy to pay for fonts, not every project has that in the budget, so free is what is needed. Google fonts, as ever, has a lot of potential there, but in the greater world of fonts is more limited than you might think. OK here is is for real: Collletttivo.

Collletttivo is an Open-Source type foundry and a network of people promoting the practice of type design through mutual exchange and collaboration.

It’s a pretty darn nice group of typefaces already.


I bet you know there are some generic keywords for fonts in CSS already, like serif and sans-serif. More recently, we’ve gotten keywords like system-ui which is supposed to pick whatever font that operating system uses primarily (which is awesome). There are more in that vein:

font-family: system-ui;
font-family: ui-serif;
font-family: ui-sans-serif;
font-family: ui-monospace;
font-family: ui-rounded;

There is now discussion in the W3C for more generic font families, a lot of which is centered around fonts for non-Latin languages. I think that’s a fantastic idea. Imagine how disappointing it would be to choose a custom font for a non-Latin language, have there be some problem in loading it, and have the next font down the list not support the language you need.

These new generic font choices have practical consequences and apply in situations where your browser could cause readers problems if it falls back to a random font: either because different fonts are conventionally used to distinguish one part of text from another (eg. headings from body text,), or because the text may become unreadable with the wrong font (eg. non-nastaliq styles in Kashmir). It’s more than just presentational preferences.


Variable fonts: still cool.

Mandy Michael resurrected her site with the perfect URL: https://variablefonts.dev/

I’m tempted to say that variable fonts didn’t hit as hard as I thought they would hit when they were coming out. But… I might be wrong about that. They are supported across the board on the web. There are tons of them. Their support in design tools is pretty darn good. There are lots of good resource sites like Mandy’s. People generally know about them and think they are a good idea. So that’s a pretty darn good. I just feel like I don’t see them in use a ton. The biggest strike against them is how big they tend to be, and I think that scares people off.


How about we end with an actual font: Playpen Sans! It’s like a classy version of Comic Sans. I think it’s both more legible (a feat, as Comic Sans is already super legible) and more fun. I really like how there are a ton of alternate glyphs for each letter that automatically activate, meaning it actually looks like handwriting a lot more than if there is only one like most fonts. Plus it’s FREE so that rules.

Reminds me of Comic Code (which we offer as a code font family on CodePen) and all the variations of the Inkwell family.

Chris’ Corner: More Like Scalable Vector Goodness

Category Image 052

I’m going to do an SVG issue here, because I find that technology persistently interesting. It’s a bit of a superpower for front-end developers who know how it works and can leverage it when needed to pull of interesting effects. For example, this compelling line drawing scroll effect is powered by SVG features.

There have been some really cool SVG tools I’ve only just seen recently, and some great writing about SVG techniques. Warms my little heart to see SVG still being actively explored even as it sits rather dormant from a standards point of view.

Let’s start with some tools and resources, since those are easy to digest and if you really love one of them you’ll be all like thanks CodePen Spark, you’re a good newsletter and ya know that’s what we’re in it for.

Tech Icons

SVG icons tend to be single-color as a trend, but actual logos tend to involve brand colors and can often be multi-color. I like how it’s super easy to use, offering both downloads and quick copy-and-paste.

Durves

I can’t explain it but sometimes you need an SVG of a grid of dots that are waving. This allows you to control all the Aspects of that. Has some tearable cloth vibes.

svghub

Squiggles, scribbles, shapes and… other stuff.

I love this because they are the kind of things that are perfect for vector art, but that you don’t typically find in things like icon sets. One click to copy right to clipboard or download.

SVGMix

Big one! 193 Icon collections. I do like that they are grouped in collections, so in case you need a bunch of assets, there is a good chance they’ll go together aesthetically. I’m a big Noun Project guy, but find it isn’t quite as well organized into collections.

OK I suppose we’d better move on to some techniques and explanations.


SVG Gradients: Solving Curved Challenges

How do you get a color gradient to follow the path of SVG artwork? Michael Sydney Moore solved it by breaking up the art into smaller sections and applying gradients to each section.

This is an interesting contrast to another technique that Ksenia Kondrashova explains.

SVG viewBox

The viewBox on SVG is pretty simple really: it sets up the visible coordinate system where everything else is drawn. Interestingly, you can change it at any time, and it effectively acts as a camera, especially if you animate it.

Brad Woods has perhaps the best explanation of it I’ve ever seen, via an interactive post.

Making noisy SVGs

Turns out <feTurbulence> is up to the job of making a noise effect in SVG, but there is a little more to it to make it nice, as Daniel Immke writes up:

To create noise, I used the <feTurbulence> filter which is explicitly for generating artificial textures but required quite a bit of fiddling to get to my liking. Then, I had to use other filter effects to eliminate color variance and blend naturally with the fill color selected, and finally apply the filter to the circle.

Noise sometimes feels like the perfect way to chill out the mathematical sharpness of vector art.

Also — did you know there is a weird trick to make noise with CSS gradients?

Responsive SVGs

There is a technique in this post from Nils Binder where he stretches just a part of an SVG according to variable content elsewhere and I love it.

Speaking of responsive… did you know the illustration in Ethan’s original article was responsive in itself?

Making SVG Loading Spinners: An Interactive Guide

This is part of what makes SVG so attractive to me: simple primitives that all combine together to do elegant things. Here, to make a specific kind of fun spinner, Sébastien Noël uses

  1. <circle> with a stroke
  2. stroke-dasharray to control exactly how the stroke should be dashed
  3. stroke-linecap to control the nice look of the dashed parts
  4. stroke-dashoffet to control the position of the dashes
  5. @keyframe animation to animate the stroke-dasharray making it feel like a spinner.

Icon transcendence: customizing icons to complement fonts

This one is from the “I hope your client has a lot of money” files. I love the idea but it’s wild. The idea is that SVG icons could swap out to match the vibe of the font they are next to.

But by “swap out”, really, somehow, it’s the same source icon.

Although these icons look quite differently visually, they were actually crafted by using the single source icon you saw above as a reference. For each of the fonts here, we’ve modified that source icon, thus producing a custom icon that better matches the style and mood of each font:

Chris’ Corner: Galleries, Grids, and GreenPrimaryDark6

Featured Imgs 26

Footer.design is a pretty fun gallery site, itself, of course, with a pretty weird/bold footer. I’ve designed my fair share of footers over the years and it’s certainly an area where you just wanna look at like 50 footers before you start in. See what other people are doing. Can you be clever? Should you be clever? What kind of opportunities do you have down there?

I gotta admit I’m a bit torn, though. I love whimsey and weirdness and the footer seems like a fine place for that kind of action, the Ficitive Kin guide I linked to a few weeks ago douses some cold water on that.

The Nav and Footer are two places where best practices rule the day and innovation should be limited.

A visitor doesn’t want to be impressed by your unique navigation design. They want to understand what your company does and they want to get to where they are trying to go.

I do get that perspective too. I suppose it always comes down to what kind of site it is. Some designer’s portfolio website is a lot different than a website for a government agency.


This past weeks’ CodePen Challenge that Marie put together was all about this sorta weird design trend people call Bento Box Design. Like so many design trends, it may have come from Apple who loves this sort of look for presenting dense information in an easily digestible way:

One of the resources she linked up is a design gallery site called bentogrids which has a ton of examples of the style.

I gotta admit I think the style is kind of charming and fun and I’m attracted to it. But I’m sure if I see it three more times I’m gonna be like ok moving on.

And speaking of niche and actually kinda strange design galleries, I find Pattern Club to be… that. It’s kinda like not really patterns, but also not not patterns. Anyway, I like it because it’s not the regular sort of design work I see.


OK well now I’m on a kick of sharing websites that are in the general vicinity of design galleries so I can’t stop now. Bramus Van Damme has been blogging about and following the idea of Scroll-Driven Animations for ages now, and I’m pleased to see he’s now built a website that bundles it all together. And with a cool domain name with dashes in it, which means I love it: scroll-driven-animations.style

I like that there are tons of demos, and they all feel rather practical. They aren’t hyper-specific landing pages or anything, they are more like patterns you could see yourself using one day. Although, of course, I love the extra fancy stuff too.


Are you ever like, you know what I need? A weird pseudo-rectangular blobbo mess. As SVG, please. That’s what this thing does.


Everybody loves a good fresh color palette, right? There are tons of sites for this. They wanna spit at you 5 colors and let your brain ooze with joy. Like Coolors, for example.

LOOK AT ALL THE PRETTY COLORS.

But can you actually make them work? What are you supposed to do with those 5 colors? I’ve always gotten a little lost there. I feel like what you really need is a set of neutral-ish colors that end up being most of your color options. Then a few colors for branding and pop. Probably a bunch of variations.

I dig the site Realtime Colors because of how it maps the colors you’re picking onto a fairly practical-looking website. Plus, then you can share the website with those colors chosen.

Good idea, right?

Chris’ Corner: Complexity

Category Image 052

Have you seen The Grug Brained Developer? It’s an essay with a URL. It’s written like a caveman became a developer and put together a philosophy that is largely a rally against complexity. Cavemen have dumb simple brains, get it? It has good points, and I largely agree with it. The caveman angle is a clever quirk to get to read it and to stick in ol’ brain.

(If you find it hard to read, I have seen a “translation”).

I think it’s fairly easy to relate to what Grug means when it comes to back-end architecture. Sprawling systems with complex requirements, services talking to each other, APIs, third-party dependencies, data manipulation methods, etc. It’s not that front-end development doesn’t have its own complexities, but it’s less obvious to point at a bit of CSS and be like, that, that’s where the complexity got too much.

Is it over, say, 2000 lines of CSS? Is it over three levels of nested DOM per component, or 12 overall? Is selector specificity averages? Is it when browser support requirements go too far back? Is it when there are too many sources of input?

I’ve certainly known organizations that, without perhaps understanding or admitting it, are afraid of their CSS. Nobody wants to touch it because nobody is entirely sure if they are going to kick over a bar stool in another bar, as the meme goes.

Taylor Troesh on a recent Changelog podcast said:

If there is any part of your code base that is starting to scare you, it needs immediate attention. Things will just get worse if there is that one part of your code base that all of your engineers are afraid to touch, because it grows in disgustingness, everyone wants to just get in there and get out and it accumulates. You want to start thinking about how you can throw that away without breaking everything.

I don’t think Taylor was talking about CSS, but to me, it maps perfectly. CSS can get into a situation where developers are afraid to touch it. That’s one reason I’m bullish on CSS that is scoped (despite my hesitation on actual CSS @scope), like CSS modules and Shadow DOM. If you can edit CSS with reasonably high confidence that you’re not touching styles elsewhere unintentionally, that’s good.

I feel CSS nesting, which is now a native feature of CSS, helps this to some degree. Write a unique class, and everything you select in a nested way is scoped to that class without you having to repeat the class name. Plus it’s just kinda ergonomically nice. But there are rather significant gotcha’s, which admittedly I really had no idea about until reading Kilian Valkhof’s The gotchas of CSS Nesting. The order in which rules are applied can get funky, and the specificity can also be unexpected. One example from Killian:

main, #intro {
    & div {
        ...
    }
}

Ends up as:

:is(main, #intro) div { ... }

Which makes it go from 0,0,1 for main div to 1,0,1 making it vastly more specific.

I’m not sure if nesting gotchas is the ultimate example of CSS complexity gone wild, but it’s just one little potential poke. I remember in the Sass heyday that people would point to @extend as a complexity code smell and they weren’t wrong.

Perhaps thanks to the scale and pervasiveness of npm, piles of questionable third-party code is another cause of complexity concern on the front-end. Michelle Barker gets into this in Reducing Complexity in Front End Development where she’s ruminating on Jack Franklin’s recent talk at All Day Hey.

A quick look in our Node modules folder quickly exposes the web of complexity within, which few of us can really fathom. A single point of failure can bring down the entire stack, like the well-worn “house of cards” metaphor.

Reducing dependencies, I’ll go out on a limb and say, is nearly always “worth it” in the sense of saving future-you headaches. Or as grug says:

one day code base understandable and grug can get work done, everything good!

next day impossible: complexity demon spirit has entered code and very dangerous situation!

Chris’ Corner: Subgrid

Category Image 052

Chrome 117 went stable this past week. There is a website where you can see what the plan is for Chrome releases, by the way, which is handy when you care about such things.

Chrome releases a major version about once a month, and I usually don’t feel ultra compelled to write anything about it specifically. Rachel Andrew does a great job covering web platform updates each month on Web.dev, like this past New to the web platform in August.

I’m extra excited about this one, though, because it means subgrid has now shipped across all three major browsers. Chrome was the straggler here:

  • Firefox shipped subgrid on Dec 2, 2019.
  • Safari shipped subgrid on Sep 11, 2022.
  • Chrome shipped subgrid on Sep 12, 2023.

Caniuse is a great site for not only checking support but also seeing when versions shipped that have support.

Lest I type too many words without explaining what subgrid is… it’s a keyword that works with grid-template-columns and grid-template-rows that allow you to suck in the grid lines that pass through the element from the parent grid.

.parent {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
.child {
  grid-column: 2 / 4;
  display: grid;
  grid-template-columns: subgrid;
}

Does your browser support it? Probably, but it’s still good to check and to code around that check. Bramus has a Pen that’s a quicky check. The CSS feature @supports is up for the job:

output::after {
  content: "❌ Your browser does not support subgrid";
}

@supports(grid-template-rows: subgrid) {
  output::after {
    content: "✅ Your browser supports subgrid";
  }
}

Perhaps the most classic example is when you set card elements on the grid, and you want elements with the cards to line up according to “shared” grid lines. Jhey has a demo like that of the basics.

I’ve also played with the cards idea, which is perhaps even more obvious where there are natural lines, like background colors running into each other:

Sometimes my favorite use cases are little itty bitty tiny things that are otherwise annoying or impossible to pull off well. For example! The aligning off CSS counters on list items. See below how in the first example the content in the list items is ragged-left, but in the second example, nicely aligned. That happens in this case by using subgrid to make all those counters essentially share a column line from the parent list item grid.

That example and several more are from a video I did with Dave a little while ago looking at all sorts of uses for subgrid.

Another of my favorites? Lining up web forms that have variable length labels. That exactly the use case that Eric Meyer showcased when he said that subgrid is “considered essential” seven years ago before subgrid shipped. Eric might have been a little wrong as grid has proven to be pretty dang useful even without subgrid, but there is no doubt that it is even moreso now.

MORE VIDEOS, you say? Can do!

  • I think of Rachel Andrew as the One True CSS Layout Master and she’s got a whole talk dedicated to CSS subgrid, which gets deeper into the details. One little one you might want to know: subgrids inherit the parent grid’s gap, but doesn’t have to!
  • Kevin Powell did a series of videos he called “Subgrid Awareness Month” about a year ago. This one about consistent layouts is a good place to start. CSS grid itself has strong “control the layout from the parent” vibes (unlike flexbox), and subgrid really enhances those powers.

Chris’ Corner: More Surprising Powers of CSS

Category Image 052

Kilian Valkhof has a good one this week, You don’t need JavaScript for that, as part of the HTMLHell yearly Advent Calendar (of blog posts). He opens with the rule of least power:

Choose the least powerful language suitable for a given purpose.

That’s fun for us CSS nerds, because CSS is a pretty low language when it comes to building websites. (It doesn’t mean you should try to write an accordion component in Assembly.) It means, as he puts it:

On the web this means preferring HTML over CSS, and then CSS over JS.

If you’re at the JS level already, it means preferring JS over a JS framework or meta language. It’s not that those things aren’t valuable (Heck, one of the purposes of CodePen is making using language abstractions and library easier) it’s that, well, it’s just a better idea to go lower level. There is less to download, less to break, higher chances of the browser optimizing it, higher chances it will be accessible, higher chances it will last over time. That stuff matters.

Killian opens with a custom “toggle” component, and really, component is probably too strong a word. It’s just a styled HTML checkbox. It’s not even all that much CSS, and no JS is used at all, to make this:

While I was reading, where I thought Killian was going was using an <input type="checkbox"> actually turn on and off features on a website. That’s the kind of thing that feels like definite-JavaScript territory, and yet, because of the classic “Checkbox Hack” (e.g. using the :checked selector and selector combinators) we actually can control a lot of a website with just a checkbox.

The ability to do that, control a website with a checkbox, has increased dramatically now that we have :has() in CSS. For instance:

<body>
  ... literally anywhere deep in the bowels of the DOM ...
  <input class="feature" type="checkbox">

We don’t have to worry about where in the DOM this checkbox is anymore, we can style anything there like this now:

body:has([.feature:checked]) .literally-anything {
  /* do styles */
}

We can start the styling choices way up at the body level with :has(), looking for that checkbox (essentially a toggle), and style anything on the page on if it is checked or not. That feels extraordinarily powerful to me.


Speaking of the mental crossover between CSS and JavaScript, Yaphi Berhanu’s Write Better CSS By Borrowing Ideas From JavaScript Functions was interesting. CSS doesn’t actually have functions (but just wait for it!) but that doesn’t mean we can’t consider how our thinking about the code can relate. I liked the bit about considering too many parameters vs not enough parameters. Yaphi connects that idea too too many selectors with too many repeat declarations, and yeah I can get behind that.

But where my mind goes is taking that lesson and trying to apply it to Custom Properties. I have seen (and written!) CSS that just takes Custom Property usage just too far — to the point where the code feels harder to reason about and maintain, not easier.

Like if you were going to make a variable for an animation…

.do-animation {
  animation: 3s ease-in 1s infinite reverse both running slidein;
}

You could decide that the right way to make this controllable and re-suable is something like:

:root {
  --animation-duration: 3s;
  --animation-easing: ease-in;
  --animation-delay: 1s;
  --animation-direction: reverse;
  --animation-fill-mode: both;
  --animation-play-state: running;
  --animation-name: slidein;
}

.do-animation {
  animation: var(--animation-duration) var(--animation-easing) var(--animation-delay) var(--animation-direction) var(--animation-fill-mode) var(--animation-play-state) var(--animation-name);
}

Maybe you love that? But I think it’s already going too far. And it could easily go further, since you could have another whole set of variables that set default fallbacks, for example.

It depends on what you want to do, but if your goal is simply “reusability” then doing like…

:root {
  --brandAnimation: 3s ease-in 1s infinite reverse both running slidein;
}

And then using it when you needed it is closer to baby bear’s porridge.


Little reminder: don’t sleep on View Transitions.

We won’t know what Interop 2024 will do until January, but based on the amount of upvotes from the proposals, I think it stands a good chance.

Jeremy Keith has a well measured take in Add view transitions to your website. It’s got links to good resources and examples on using it, like Tyler’s Gaw’s great post. It ends with an update and warning about how maybe it’s not such a great idea because it may “poison the feature with legacy content”. Meaning if too many people do this, the powers that be will be hesitant to change anything, even for the better. I agree that would suck if such a choice is made, as I do think there is room for improvement (e.g. transition groups). I dunno though, I think because this stuff is literally behind a feature flag, that’s enough of an at your own risk warning. If they want to change something that breaks any code I’ve shipped, I’m cool with that. I know the stakes.

I think we’ll start seeing more interesting examples and experiences soon. And! Gotchas! Like Nic Chan’s View transitions and stacking context: Why does my CSS View Transition ignore z-index? It is confusing. It’s like the elements kinda stop being elements when that are being transitioned. They look like elements, but they are really temporary rasterized ghosts. You can still select them with special pseudo element selectors though, so you should be able to get done what you need.


There is this inherit complexity with doing the whole Dark Mode / Light Mode thing on websites. There is both a system-wide preference that you can choose to honor, and that’s a good idea. And it’s likely that a site implementing this also offers a UI toggle to set the theme. So that’s two separate bits of preference you need to deal with, and the code likely handles them separately.

Christopher Kirk-Nielsen’s A Future of Themes with CSS Container Style Queries gives us a good taste of this. Let’s jump right to code:

/* No theme has been set, or override set to light mode */
html:where(:not([data-theme])),
:root[data-theme=light] {
  --color: black;
  --background: antiquewhite;
  /* … and all your other "variables" */
}

/* Apply dark mode if user preferences call for it, and if the user hasn't selected a theme override */
@media (prefers-color-scheme: dark) {
  html:where(:not([data-theme])) {
    --color: ghostwhite;
    --background: midnightblue;
    /* … and all your other "variables" */
  }
}

/* Explicitly set the properties for the selected theme */
:root[data-theme=dark] {
  --color: ghostwhite;
  --background: midnightblue;
  /* … and all your other "variables" */
}

If you read though that I think you’ll see, you need @media to deal with system preferences, then the HTML attributes to deal with a direct-set preference, and one needs to overlap the other.

Enter Style Queries. What they really are is: “when an element has a certain custom property and value, also do this other stuff.” Christopher’s “future approach” using them is more code, but I’d agree that’s more clean and readable.

/* Optionally, we can define the theme variable */
@property --theme {
  syntax: '<custom-ident>'; /* We could list all the themes separated by a pipe character but this will do! */
  inherits: true;
  initial-value: light;
}

/* Assign the --theme property accordingly */
html:where(:not([data-theme])),
:root[data-theme=light] {
  --theme: light;
}

@media (prefers-color-scheme: dark) {
  html:where(:not([data-theme])) {
    --theme: dark;
  }
}

:root[data-theme=dark] {
  --theme: dark;
}

/* Then assign the custom properties based on the active theme */
@container style(--theme: light) {
  body {
    --color: black;
    --background: antiquewhite;
    /* … and all your other "variables" */
  }
}

@container style(--theme: dark) {
  body {
    --color: ghostwhite;
    --background: midnightblue;
    /* … and all your other "variables" */
  }
}

Check out Christopher’s article though, there is a lot more to go over.


Let’s end with a little good ol’ fashioned CSS enthusiasm.

For many, many years, creating high-quality websites largely meant that designers had to fight what felt like an uphill battle to somehow make their ideas work in browsers. At the same time, sentences like “I’m really sorry, but this solution you designed just can’t be done with CSS” […]

This has now changed to the opposite.

Want to emulate and confidently design a layout that leverages the potential of CSS Grid in any of the major design tools like Figma, Adobe XD, or Sketch? Not possible. 

Matthias Ott, The New CSS

And:

I still keep Sass around, as well as PostCSS, for things that CSS just wont ever be able to do (nor should it), but they’re fading into the background, rather than being at the forefront of my mind when writing styles. And for small, simple projects, I don’t use them at all. Just pure CSS. I haven’t found it lacking.

Jeff Sandberg, CSS is fun again

Chris’ Corner: Little Useful Websites

Category Image 052

I came across Alexey Ardov’s work the other day. Looks like the color bug hit him pretty hard. I first saw this playground:

It’s awfully cool. I like seeing color palettes presented in the context of UI like that. Sometimes it’s hard to picture how it all might come together if colors are looked at too abstractly. It doesn’t exactly have an export tool, but a bunch of CSS custom properties are barfed out into a style attribute on the <body> if you were so inclined to use them for something.

Of course I thought: HSL is nicely used here, but what about the HDR color formats?! Seems like a good opportunity to set up P3 colors and non-P3 color fallbacks. I don’t think this fact is lost on Alexey, as they have lots more color experiments they have built. For example, this visualizer for looking at color models, which then it looks like got an upgrade to visualize more models (and gamuts).

I like looking at those things as they are a reminder of just how designed these color spaces are and how deep the rabbit hole can go. Before you know it, you’re designing extremely sophisticated accessible color palette generation tools.


Looking at these one-off single-purpose websites always puts me in the mood to share more. Aren’t you lucky that I save links to new ones that I see just for times like this.

CSS-Pattern

Temani Afif’s pattern site has some pretty sophisticated backgrounds that are done just with CSS backgrounds. Reminds me of Lea’s take on this from years ago. A grand tradition of CSS wizards.

Very easy to paste on into a Pen.

SpaceBadgers

Those little badge graphics that are super common at the top of GitHub repos, created with a super clean URL format.

Oh and hey they look great small but you can make them as big as you want and because they are SVG they scale up nicely.


Theme Toggles

Need a neat little animated toggle for Light Mode / Dark Mode? This site has a whole bunch of them:

Wasn’t much to pluck one over to a Pen, in case you need a reference there. I saw a little controversy on this as one of the usage options is as a <div>, which of course is not an interactive element. I’m not sure that’s fair, as you might use this as a visual adornment next to an interactive button, for example. And the React exports use <button> nicely.


Tree

I’m sorry I can’t explain it, but sometimes you have to update intended text to have a bunch of extra special ASCII characters that better represent a file tree.


Custom Shape Dividers

In the rectangular world of web design, sometimes just what you need is something… not rectangular.

The site provides SVG, HTML, and CSS for you to copy out, which, I’m sure you’re aware, plunking over to CodePen to play with is a snap. Gosh, isn’t CodePen useful? You should go PRO.

Chris’ Corner: Baseline

Category Image 052

At this latest Google I/O, Rachel Andrew introduced a new concept they are spearheading called Baseline. It’s a visual thing to help developers understand browser support for features better. Here’s one:

It’s not a Google-owned-website only thing, as you can see here on an MDN page.

It’s essentially a simplified browser support chart, featuring only Chrome, Edge, Firefox, and Safari. I’d argue Edge is just taking up space there as it’s-just-Chrome when it comes to web platform feature support, but Edge is still contributing to web platform stuff at a high enough level I think it’s probably a fair shoulder rub.

How do they get away with just a green-checkmark-or-not for browsers? They say it’s because we’ve reached the point where all the major browsers are now evergreen, as in, users don’t even have to update themselves, updates just arrive, so nobody has to think about versions much anymore. Sorta true, sorta not.

Presumably, it can also tell users when cross-browser support isn’t there yet, but I cannot find a single example of this. Presumably there is some red-ness and ❌ stuff happening. It’s tricky though isn’t it? I love the new View Transitions stuff (examples), but the main blog post on it doesn’t have a Baseline thingy. If it did, it would show that only Chrome has this feature, which would, I suppose, inform developers that the feature isn’t really ready to use. But is that true? Not really. If we avoid as much nuance as we possibly can with browser support, it should still be at least a three-answer game:

  1. You can use it.
  2. You can use it (but only with polyfills or progressive enhancement).
  3. You can not use it.

Baseline feels more YES or NO to me, avoiding that really useful middle answer which is perfect for even cutting-edge stuff like View Transitions.

It’s also tricky to know you’re looking at the correct thing. Take Una’s blog post about Style Queries in CSS, a brand new thing. The Baseline at the top is all green good-to-go. But Style Queries are definitely not all-green good-to-go. That Baseline is talking about container queries not style queries, and that is entirely not obvious at a glance. Gonna be tricky to get all this right.

I am pretty stoked about this though:

We’ll be providing widgets that you can use on your own articles or libraries, indicating support for the Baseline feature set.

The Can I Use site is used now by tons of developers (and also gets much of it’s data set from MDN, just like Baseline does). I always thought it was weird they didn’t offer their own lightweight embeds for any site to use. Way back when, Ire Aderinokun created The CanIUse Embed which was awesome but I don’t think it was ever updated for the MDN-data-only charts. Maybe Baseline can be a good and official version of embeddable browser support charts. I would have used them at CSS-Tricks (probably) if they existed.

What they should do is make a Web Component! Wouldn’t it be cool to see like:

<baseline-support feature="grid"></baseline-support>

And that would spit out what web.dev and MDN are essentially showing? Ship it. Then everybody benefits. Here’s another great article on Style Queries. Sure would be nice to see right at the top what kind of support we’re looking at.

Chris’ Corner: Esoteric Stuff in CSS

Category Image 052

Listen I ain’t trying to scare you, but this CSS stuff can get complicated. It doesn’t have to be. CSS is just selectors with key value pairs in the end. The vast majority of CSS I write is pretty darn straightforward, especially once you have a general system (what files go where? how do we generally name things? how do we do variables?). But fair is fair, CSS can get wildly complex. It doesn’t help the complexity situation that anything new added increases that complexity, because, well, everything in CSS affects everything else. Selectors can get confusing and nesting can exacerbate that. Variables can get changed at any time and it’s not always clear from where. The situation on the page (sizing, events, settings) can effect what’s happening in CSS in increasingly bigger ways (querying containers, querying user preferences). If you want to push the edges of what CSS can do, now is the time.

I often save links of other people’s explorations of these edges of CSS. They are fascinating to me, naturally, as one of the proprietors of a front-end coding tool and ex-owner of CSS-Tricks. But sometimes I struggle to find a way to share them and contextualize them because of the complexity. In fact I think it’s fair to not use techniques based on complexity alone, after all, you write it you maintain it.

But let’s remove the limiter and look at CSS stuff regardless of how complex it might be.


I’ll start with one that has broken my brain for a few years now. @James0x57 calls this technique “Space Toggles” (who credits Ana Tudor for the discovery). Lea Verou calls it The -​-var: ; hack. Just to lock in my own understanding, I called it The CSS Custom Property Toggle Trick.

The idea is that CSS custom properties can be valid and invalid, a valid value even just being " " (a single space). You can concatenate that custom property with others to produce either-valid-or-invalid other custom properties. If it’s valid, you can do one thing, if it’s invalid, you can use the fallback for the custom property to do another thing. So it’s essentially if/then logic for custom properties.

The closest I ever came to simplifying it is this. And I admit it’s not exactly straightforward.

The good news is that CSS just decided that if() would be a thing, so now we wait for browser implementations. It should be quite a bit more straightforward, although the ease-of-use will lead to more exotic usage of it and, I’m afraid to admit, more complex CSS.


Have you ever prepped for needing to do a sorting algorithm in a job interview? Can you explain what a Bubble Sort is? It’s the one where you loop through a list comparing the two things next to each other, and swap them if they need to be swapped. You keep running through the list until you don’t do any more swaps. I think, anyway, I’m not some computer genius over here. GrahamTheDev is though! Their article Bubble Sort…in PURE CSS? is bonkers.

It literally works.

This is the complexity that comes through the ability to compare variables (e.g. we have min() and max() in CSS now) and set new variables based on other variables. Write enough of that with delays and animations and you got yourself a bubble sort. Good luck grokking all that though.

And speaking of the edges of CSS:

warning: on mobile the last few animations might not play and just go blank. On PC your fan may spin up!

This is a limitation of using so many calculations that rely on previous calculations…I am not sure if it runs out of memory or what, but I defo pushed the limits of CSS here!


What’s the value of cos(25deg) in CSS? Tyler Gaw wanted to figure it out exactly.

I know that will return a number between -1 and 1. But what number?

You can’t even set any property to exactly that, because just the number it produces is invalid for most properties.

You can do something like width: calc(1px * cos(25deg)) then check the width value in the devtools computed styles panel and get close, but not exact. Also, width: cos(25deg) is invalid CSS and using a custom prop like --v: cos(25deg) doesn’t really work either because the custom prop value is stored as cos(25deg).

But obviously cos(25deg) produces a number?! Tyler found a way to extract the CSS-generated number in JavaScript. I felt like having a poke at it too, but I didn’t get much further. I did discover that the output is a unitless number, so it’s valid for CSS properties that take unitless numbers, like line-height. So you can set line-height directly with it and then read the computed value. The problem is the computed value isn’t the direct output of the cos() function it’s the final px value so… blech, hard.


There is some CSS trickery that involves @keyframe animations. For example, styles applied during an animation apply extra strongly, so a style applied with a animation that runs for, say, a year is a way to do style overrides. Not recommended, heh. Setting animations to a particular place and pausing them is another weird trick for managing state in CSS.

Those, at least, I feel like I can get my brain around quickly. Animations have some extra power (and complexity) lately via Scroll-Driven Animations. Roman Komarov is the master recently of extremely exotic and complex CSS trickery, and his Scroll-Driven State Transfer is the pièce de résistance.

… an ability to mirror a particular state of some element — for example, hovered or focused — to an element in a different place on the page without a common or unique ancestral element that could have been used to deliver that state

You might think of :has() as the new hotness for being able to access state anywhere in CSS from anywhere else, and you’d be right, but apparently this trick is a bit more adaptable, not requiring us to write more CSS later:

… we could implement this with the :has() selector, but for any new values we’d have to modify the stylesheet afterwards

It looks like the trick involves those Space Toggles too, meaning I think this is one of the most complicated CSS tricks I’ve ever seen. Apart from the super math-y stuff that always blows my mind, that is.


We’ve established that animations can be one of the vehicles for CSS complexity, which is true when using them just to animate, not strong-arm them into some wild state machine.

One way animations can get complicated is combining them. It was just the other day I reminded myself that nesting elements and then animating them both essentially doubles the speed of the inside animation. That’s just shooting a cannon from an airplane though, no fancy tech there. CSS actually allows us to manually combine animations, with tools like animation-composition. It can be confusing though! Bramus wrote up The mysterious case of using CSS animation-composition: accumulate on a scale transform outlining just how weird it can get even in relatively simple situations. Maybe you’ll scratch your head too:

Accumulating a scale(0.5) with scale(2) does not give scale(2.5) but scale(1.5)

After scratching my own head about this long enough, it did sort of start to make sense. Even though blur(2) and blur(3) certainly make blur(5) when accumulated, those are both “blur something more”. In the case of scale, 0.5 makes something smaller. So adding 2.0 + 0.5 isn’t 2.5 because they aren’t both “do something more”, one is “make smaller” and one is “make bigger”, hence the spec having to step in and explain.