Chris’ Corner: Buttons, Modes, and a Couple of Layout Situations That Are Still a Bit Tricky

Category Image 052

If you ever need some inspiration for buttons, definitely check out Lucas Bonomi’s buttons.cool. This is a better-than-it-needs-to-be one-off site just for beautiful buttons:

But it’s not just a design gallery, it’s made for front-end developers in that you can see the code, see them being live-rendered right on the page, and of course, the best part is you can pop right over to CodePen for a look.

Looks like it’s taking submissions.


How hard is a Dark Mode to pull off? Or perhaps more accurately, how hard is it to pull off a second color mode? Some of us have dark-mode-first websites, ya know.

I thought Wes Bos phrased the question well:

Question for those who have implemented light/dark mode: how much is just swapping out variables, and how much is custom code, and tending to edge cases?

I answered: fiddy fiddy.

In the new version of CodePen we’re working on, we will have a site-wide theme setting (which is separated from what syntax highlighting theme you choose). CodePen being a pretty complex site, it involved quite a bit of CSS custom property setting. So in a sense, it was mostly just “swapping out variables”, but quite a few of those variables exist just because of different color modes, most of which I might even call an “edge case”. For us: north of 100 south of 200. I found this to be challenging but ultimately a fair approach.

Sometimes you see ideas going around of how simple it could be. For instance, he’s Akhil Arjun saying it can be done in one line:

html[theme='dark-mode'] {
    filter: invert(1) hue-rotate(180deg);
}

And here’s Mads Stoumann with a totally different 3-line approach:

body {
  background-color: Canvas;
  color: CanvasText;
  color-scheme: light dark;
}

While I appreciate a good CSS trick and these are good things to know about, I’m going to go ahead and say these super minimal approaches probably aren’t going to get you very far. You’re going to want better control than this and you’re going to need to deal with those edge cases.


Now that we have such powerful layout tools in CSS (keep ’em coming, CSS!) — it’s fun to see little layout situations that look fairly simple but are still a little challenging. Tyler Sticka ran across one he calls Tricky Floating Image Alignment. The idea is to have some text that is center aligned with an image, but if the text grows larger than the image, use the behavior of float.

I liked the solution in the end. It’s a throwback to the way we used to be able to vertically center stuff with top: 50%; transform: translateY(-50%). This will do the centering nicely, but when the text is bigger than the container, they essentially cancel out and so essentially do nothing.


Here’s another tricky layout situation, this time involving newfangled HTML and CSS features, namely anchor positioning. (Think of it as positioning an element based on another arbitrary element’s position.) Eric Meyer blogged it as Nuclear Anchored Sidenotes.

Imagine a footnote, except on a large enough screen, it’s more like a sidenote. That is, the note goes into empty sidebar space at the exact line that the footnote marker appears on. But to really pull this off, you’re using anchor positions of multiple elements:

Yes, I’m anchoring the sidenotes with respect to two completely different anchors, one of which is a descendant of the other.  That’s okay!  You can do that!

I did not know you could do that, but I like it.

top: anchor(top); /* implicit anchor */
left: anchor(--main right); /* named anchor e.g. anchor-name: --main; */

I only just heard of the CSS round() function the other day. It takes a value and rounds it. Ha.

line-height: round(2.2, 1); /* 2 */

I was blogging it with a number of other CSS functions I’d never heard of. Try this demo in Firefox to see a pretty clear example of why it could be cool. Of course Dan Wilson is all over it with a much more comprehensive look in The New CSS Math: round(). Dan looks closely at the syntax, sharing how you pass in not just a value, but the interval by which you want to do the rounding. Then optionally, even a “rounding strategy” if it’s important to you how that is done.

I feel like this falls into the category of “interesting layout related thing that would have been hard or impossible before but now isn’t.” Or at least “we’d probably have to do this in JavaScript before but it actually makes more sense in CSS.”


Looks like we’re going to get scrollbar-color and scrollbar-width across all browsers for real now. That’s the “real spec version” of doing this, instead of the more-capable (get gone-wild) WebKit styles of old. I wish it was more capable, but I’ll take standards over that any day.


While I’m still on this kick of “difficult CSS layout things”, you gotta see this Pen from Alex Riviere that handles this curved grid.

What’s striking to me about this is how… not weird it looks. It’s like if you were standing in a glass elevator going down and looking at these blocks, that’s just how they would look. But in order to pull that off while scrolling, some relatively exotic transform action needs to happen on them, which even involves new trigonometric functions in CSS (along with a scroll-timeline, which you can see has a fairly simply polyfill in this case).

Go take a peek at that CSS. The transforms are just a few lines, but wow that’s fancy.

Chris’ Corner: Swinging For It

Category Image 052

New year, new local code editor? It’s maybe worth a peak at Zed, at least. They do a good job in the one-sentence pitch:

Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.

All tech things have to be fast, so check. No shade either, speed is vital in all things tech, especially something you use heavily all day. Their main competition is clearly VS Code, which already gets some flack for slowness (feels fast to me 🤷), so leaning into a comparison that shows them some 4x faster on startup is sensible marketing.

“Multiplayer”… eh. I’m skepitcal about how much teams really care about this. VS Code did a whole “live share” thing a while back and I don’t think it struck much of a chord. I’m not against it as a feature, it’s just more like table stakes these days rather than a killer feature.

The last one… “from the creates of Atom and Tree-sitter” is a great pitch. People loved Atom. People are not happy Atom went away, so you get those people right out of the gate. Even if you didn’t use it, I think a lot of people respected it. Then Tree-sitter is this best-of-breed code parsing tool that all sorts of stuff uses (the new version of CodePen that will be out this year uses it heavily).

Will I actually switch? No idea. I’m always down to try new things. But I’ve written about this before, and I have my own criteria on switching code editors. For me, the new one needs to be able to behave essentially like the old one. If anything is too obnoxious, I’ll just switch back. If I can switch without terrible annoyances, then I’m happy to explore changes and different features and such.

And to keep me (and I think this is generally true, not just for me) it needs killer features. Maybe that is speed, but I don’t think the competition in this area is slow enough for that to be the big thing.

Maybe the AI stuff will be one of the killer features. AI is such a big thing these days, but VS Code has Github Copilot, which is great and a huge competitive advantage. Except… Zed supports GitHub Copilot! Nice move. And check out the video where they’ve integrated GPT-4 into the editor, and you invoke it by highlighting a block of text and typing a prompt. Very classy, I think.

It appears as if they are really making a swing for it with Zed and that’s good for everyone. Making a business out of it is going to be tricky too. Looks like they already have a team of 10. I can tell you that 10 world-class developers aren’t cheap. It doesn’t look like Zed is open source yet, so best guess is the plan is to make it paid. That’s tough in a world where VS Code is free (although Copilot is not). Panic makes it work with Nova though, so it’s not uncharted territory. I think developers are happy to throw bucks at tools that are even a little bit better, so I would bet on Zed doing pretty decently, myself. The good design of their landing page makes me feel like they have their heads screwed on straight.

Gotta love companies making a big swing on things. I feel like that’s what Arc has been doing since the beginning with their new web browser. They are constantly shipping and taking risks on big features. And it has all the hallmarks of big swings: some big hits, some big misses. I think Arc has massive potential as being the best web browser out there, but it seems like that’s not where they are headed. In a vague end-of-year where-we’re-headed video, they say they actually want to build a whole new computer. That seems like a wildly different task and set of skills needed, but hey, a big swing is a big swing. They are kind of “pre-money” so I guess it’s more of a pivot.

I feel like another company that is trying to make a swing for it in a crowded market this year is Bun. A brand new JavaScript runtime in a totally different language is a big endeavor. Competition in this space feels warranted and good for everyone. And also like the business model is just as nebulous as all the other companies mentioned here. There was some pretty pointed pushback about Bun, which both feels fair and like that’s exactly what you’d expect when you’re doing something new and bold.

Chris’ Corner: More Like CSBest

Typography Definitions Cover

We gotta talk about CSS! That’s my favorite thing! It’s always on the table for a good Chris’ Corner edition, but sometimes focusing on it entirely is best.

Klint Finley called it “The modern web’s underrated powerhouse” for GitHub’s publication The ReadME Project back in February, and I’m inclined to agree. Although the days of CSS being considered underrated are waning. I get the sense that plenty of people find it complicated or generally just don’t like it, but those same people still respect its power. There is also one big undeniable fact: every website uses it. All of ’em. And it controls nearly every Aspect of how a website looks, which, ya know, if you care at all about how successfully your website does what it sets out to do, matters a whole heck of a lot.

Anyway, rather than listen to me prattle on about how good CSS is, let’s look at some interesting ideas pulled off in CSS, new things coming to CSS, dealing with browser support, and future ideas.


It used to be that if you used CSS to set the width and height of an image and the Aspect ratio that those two numbers formed didn’t match the Aspect ratio of the image, it would squish the image awkwardly. Almost certainly not the effect you want. But now we’ve got the object-fit property in CSS, and specifically the cover and contain values, which prevent the squishing. With cover, the image might crop, so you’re sending more image data than you needed to, perhaps, but you’ll be achieving the design you’re after.

With that as a foundation, let me let Henry Desroches take over in Using Focal Points, Aspect Ratio & Object-Fit To Crop Images Correctly. In conjunction with object-fit there is object-position which allows you to set an XY coordinate from where the image scales.

Try clicking different positions on the source image and see how the sized images change which part of the image they show. This is just good to know. If you’re ultimately cropping images, you don’t have to settle for the defaults.


You’d think “position this element over by this other element” would be easy peasy for CSS, but you’d be wrong. There has been no mechanism for that up until now. The new thing is called anchor positioning, and Jhey Tompkins has the scoop in Tether elements to each other with CSS anchor positioning.

The big obvious use case to all this for me is basically: tooltips powered by footnotes. Essentially I want bits of UI (a phrase, link, or [?] button) that can be hovered or otherwise interacted with to reveal a bit more information. But that information is elsewhere in the DOM. Wherever I want in the DOM that makes sense for my project. Finally, I’ll be able to do that (once is supported across all browsers or if I use the polyfill).

I had a little play with this myself, thanks to Jhey’s guidance in this post.

I didn’t get into all the scrolling stuff you have to think about or the @try style positioning, but I do think all that is very cool. Edge detection stuff is another thing that we’d have to lean on JavaScript to do normally, but never love having to do so.


As good as CSS has been lately with new features working across browsers, it’s still a thing we have to think about. Fortunately, CSS saw this coming long ago and has @supports rules that can help us conditionally apply CSS in supporting (or not) situations.

Stephanie Eckles has the most up-to-date information on all this in Testing Feature Support for Modern CSS.

An example I can think of is the kick-ass :has() selector. As I write, :has() isn’t supported in Firefox yet. So if we wanted to know that in CSS before we use it, we could do:

@supports selector(:has(a)) {
  /* styles when :has() is supported */
}

It is useful to think about what your plan is for detection, though. Like does it matter if Firefox doesn’t support :has() for what you are trying to do? Are you prepared to do it some other way if it’s not? As an example, I was talking to Eric Meyer the other day, and somehow table row/column highlighting came up, and he made a demo with :has().

Now you’d have to decide: how important is that effect? As written, in Firefox, just the cell you hover over highlights, so you could decide that’s fine, and then you don’t need any feature detection at all; you just let it fail. Alternatively, you could decide to use a @supports query in CSS and highlight the entire row if :has() isn’t supported, which is a similar effect (if not quite as cool).

Another decision you could make is to do the test in JavaScript and use a JavaScript-powered fallback if necessary. Good news, Stephanie has a JavaScript testing tool just for this. It uses a number of different techniques to report if a feature is supported or not. Ultimately you could use it for our :has() test like:

<script type="module">
  import * as SupportsCSS from "https://cdn.skypack.dev/supports-css@0.1.5";
  const tests = ["has"];
  SupportsCSS.init({ tests });

  if (!SupportsCSSTests.results.has) {
    document.head.insertAdjacentHTML(
      "beforeend",
      "<style>tr:hover { background: rgba(255,0,0,0.33); }</style>"
    );
  }
</script>

Ya know, just while we’re talking about feature detection in CSS, a typography-specific feature tester crossed my desk the other day, font-tech and font-format:

@supports font-tech(palettes) {
  .palette {
    display: block;
  }
}

@supports font-format(woff2) {
  div {
    display: block;
  }
}

Just interesting to me; I’ve never seen those specific functions before.


Wait, wait, I gotta do one more about feature detection. There are some things that you cannot detect in CSS, and is kind of a pain in the butt to detect in JavaScript also. Ahmad Shadeed made this point in Do we need CSS flex-wrap detection? The point has been made again and again that we need certain state detections like a :stuck selector for position: sticky; elements, and it sounds likely we’ll get that. But “is wrapped or not” is another form of state, I’d say. Ahmad’s use case was like… if a line in a flexbox layout wraps, it’s saying: “there isn’t room for these on one line”. But where that is is totally arbitrary based on content and element size. But if we knew exactly when that break was, we could, for example, use that exact moment to break a line of navigation into a hamburger rather than guessing at some magic number size. Strong point, I think.


I have an unnatural affinity for the “yellow fade technique”. It’s this idea that works with the :target selector in CSS and on-page anchor links. Imagine a table of contents where you click a link, and it jumps the page down (or scrolls, I suppose if you use scroll-behavior: smooth). How do you know exactly where the page is trying to take you to and draw your attention toward? The element is probably at the top of the page, but it might not be if the page is too short. The yellow fade technique just makes it way more clear. When that jump happens, that element becomes the :target, and you apply a background-color animation to it (light yellow!) that draws attention to it. It’s just nice, I think. There are some classic examples on CodePen, naturally.

The idea can also be applied to an element being added to the DOM, drawing attention to the fact that it just appeared. That’s what Bramus Van Damme does in The Yellow Fade Technique with Modern CSS using @starting-style.

Erm… @starting-style, what’s that? It’s basically built for the yellow fade technique. 😍.

div {
  transition: background-color 0.5s;
  background-color: transparent;

  @starting-style {
    background-color: yellow;
  }
}

With that, you don’t need a once-running @keyframes which ends up being more verbose and harder to understand. This way the transition essentially runs once on <div>s being added to the DOM. So I guess it’s not as perfect for the table of contents use-case, but it’s still pretty cool. Now I’m thinking about other DOM-entrance animations, like list items that slide in, or modals that fade in.


Sometimes we get new CSS stuff, and it’s just great right on the surface. Oh, the oklch() color function? Neat, it can do vibrant P3 colors. Neat, it has perceptually uniform lightness. Neat, the gradient interpolation is arguably nicer for some color pairings.

But then, over time, it turns out it’s how the new CSS feature is combined and interacts with other features that makes that feature shine even more. Aww, that was sweet, wasn’t it? We’re all better with a little help from our friends.

That’s what I was thinking about reading Adam Argyle’s A color-contrast() strategy for complimentary translucent backgrounds. If you haven’t seen color-contrast() yet, it’s a function that will pick the most visually contrasting color from a list of colors against a given color. That given color is probably a --custom-property meaning it can change and thus you don’t know ahead of time what the most contrasting color is. That’s awesome! But Adam takes it a little bit further. He wants to kick up the contrast even more by putting a slightly transparent black or white color behind the text.

html {
  --bg: hsl(var(--hue) 50% 50%);
}
  
h1 {
  --text: color-contrast(var(--bg) vs black, white);
  color: var(--text);
  background: hsl(0 0% 0% / 40%);
}
  
@supports (background: hsl(from red h s l)) {
  h1 {
    background: oklch(from color-contrast(var(--text) vs black,white) l c h / 40%);
  }
}

So cool. So individually, color-contrast() is neat, OKLCH is neat, @supports is neat, and the relative color syntax is neat, but combined, they really shine.

Chris’ Corner: Design Shrinking

Category Image 052

While I don’t think you should publish to Medium (at least not as the only place you publish something, you should write on your own site that you control), I get why other people do. You quickly sign up, write some words, hit publish, and the result is a pretty clean-looking presentation of your writing. Not to mention familiar to the general public. Medium is big and popular enough that people have seen it and are comfortable with it. I mean Barack Obama writes there so goes a long way in terms of endorsement.

It’s that clean comfortable design that I think it’s especially notable (when it’s not being covered up by a mysteriously activated paywall). So it’s interesting to see their designers write about the effort that goes into that look. Breana Jones says they re-focused on the single-column look:

We’re bringing back the single-column page layout and removing the two-column layout across all stories on desktop.

You can still find recommended stories from Medium and author bios, but these sections will now be below the story, instead of right next it. This allows readers to focus on the story without any distractions on the side.

I applaud that, really. The single column look really works great on the web for primarily written content and it’s harder than it looks to pull off, especially at a huge company with lots of business objectives fighting for space on that screen.

Design does tend to be associated with cleanliness. Like a “clean” design is a “good” design, generally, especially when we’re talking product design for wide varied audiences. I like how Matt Birchler says:

If you are sitting next to someone at a computer and you know how to use the thing and they don’t, it’s very easy for you to say, click here, do this. When you click this, this is what’s going to happen. It’s very easy to do that. The goal of a good user interface is to give someone that experience without you having to be in the room with them.

That’s as good of an explanation for digital product design as I’ve heard. I caveated it with “digital product” because design is a pretty broad discipline. Designing a wooden bookshelf is a pretty different endeavor with different constraints and goals. Wood has a grain that the designers will work with. The web, too, has a grain. Amelia Wattenberger says:

In the digital world, especially on the web, we’re used to things being stacked vertically. Scrolling, scrolling, through boxes of content, one… on top… of another.

Things are always arranged linearly — top-to-bottom. Or, if we’re feeling spicy, left-to-right.

This is all great for neat, orderly content. But what about when thoughts are complex, unsorted, exploratory?

This is her introduction to thinking about infinite canvases, which is a little against the grain on the web, but absolutely doable and sometimes quite useful. Consider how you can drag and zoom a Figma canvas anywhere without any constrained edges at all. But this approach isn’t just for design, it can be useful for things like thinking through problems with teams, doing organizing and grouping.

I love me some good “general rules” for design concepts. There is so much nuance and it depends situations in design and development, when there is some just do this advice I appreciate it. I think of things like how headers always have less line-height than body text, things should align with other things, and you should probably double the white space.

CodePen’s own Rachel Smith has some excellent general advice in this vein that I didn’t really understand until now:

If you’re moving an object from out of the frame/stage in to the frame/stage, use an ease-out variation.

If you’re moving an object from inside the frame to outside the frame, use an ease-in variation.

If you’re moving an object from one place to another in the frame, use an ease-in-out variation.

I can remember that!


Lemme leave you with a little one: Magick.css. It’s one of those “just link it up and your semantic basic classless HTML will look nice. It’s got a pretty fancy look to it with some unusual font choices, but it might be your bag. My favorite in this genre is still new.css.

Chris Corner: Unusual Ideas with Great Results

Category Image 052

SVG Short Circuiting

SVG is normally a pretty efficient file format. If an image is vector in nature, leaving it as vector is normally a good plan as it will like scale well and look pretty darn crips. But of course, It Depends. Super complex vector graphics can get huge, and a raster (i.e. JPG, PNG, etc) version can actually be smaller. This can happen with little tiny images too where the straight up low amount of pixels is just pretty efficient.

This should be the kind of thing computers are good at, right? You’re in luck if you’re using Eleventy. Zach wrote about a thing the Image component can do for Eleventy called SVG Short Circuiting. The idea is, if your source image is SVG, it can make raster versions to help with efficiency. But if the SVG version ends up smaller than any of the other produced versions, it will discard the raster versions.

A nice looking font that helps dyslexia

Worth knowing:

According to the International Dyslexia Association, as much as 15 to 20 percent of the U.S. population may have symptoms of dyslexia. Those include slow or inaccurate reading, weak spelling, and poor writing.

Jill Stakke

Also worth knowing: these people, and really probably anybody can be helped along with better typefaces. That is, typefaces designed in such a way that the are less confusing and less problematic for people with dyslexia.

I’ve seen Dyslexie before, which is pretty neat. But to be frank, it does look a smidge childish which might make it a tough choice when a brand voice needs to be more serious looking. A crappy trade-off, but such is life.

I’ve just seen Oliva King’s Inclusive Sans which, to my eyes, it extremely nice looking and covers the general criteria laied out by Sophie Beier in Designing for Legibility.

  1. Clear distinction between I, l and 1
  2. Non-mirroring of letters d, b, q and p
  3. Distinction between O and 0
  4. Wider, more open counter forms on c, o, a and e
  5. A higher x-height for easier readability at small sizes
  6. Wider default letter-spacing
  7. Clear difference between capital height and ascender height

Just look at how #2 is handled:

Super classy if you ask me. I wanna use it for something. I’m stoked at how good it looks at body copy sizes.

An HTML element as a mask

The vast majority of masks are either shapes in black/white such that they hide or reveal what is behind them in that shape exactly. Or a gradient, such that they fade out what is behind them little by little.

Artur Bień has another idea of what a mask can be: any HTML element. You can set up a simple-but-clever SVG filter to filter out all black.

I gave it a quick shot myself just to have a play and it worked great.


Now that you’re primed into thinking of layering things on top of each other and doing exotic filtering to get weird and cool results, you’re ready for this next one.

Javier Bórquez: Motion extraction with mostly CSS.

Say you wanted to look at a video where only the things that are moving are visible, and the rest is essentially blacked out. Why? I don’t know don’t think about that part too hard. Maybe it’s a way to spot changes in security video easier. Or more likely it’s just a really cool final effect.

You’d think getting that done would involve sophisticated video processing technology. But nope: CSS. The trick is so perfect:

One video is placed on top of the other, playing slightly ahead. Then, by styling the top video with mix-blend-mode: difference in CSS, we make is so only the pixels that have changed between the two frames are shown.

So cool. That’s my favorite trick I’ve seen in a while.

Single Element Gradient Borders

Actually I have another trick that is right in the zone with the last two that is also just extremely cool. You gotta admit the gradient border look is pretty hot right now.

There are number of ways to pull that off, but they typically involve multiple stacked elements and decently involved trickery or limitations. The above is just one element, and it’s showcasing how you also aren’t limited with what you want to do in the body of the element (there using a backdrop-blur).

Ben Frain documents a trick he found in the freeCodeCamp forums. You slap a pseudo element on the main element to create the border, and then essentially knock out a hole in the middle.

Here is the clever bit I have never seen before; we then use a mask, and a mask composite. This allows us to create a ‘shape’, that our gradient border will inhabit. To create this shape, we need to composite two images together and find the difference. That might sound like a lot of work but we can make those two images with CSS using a linear-gradient. It doesn’t matter that the linear-gradient is actually just a flat white colour, the fact that it is defined as a linear-gradient means that the browser renders the outcome of that notation as an image and the image can be composited. So the first mask is a linear gradient set to the padding-box, which then crucially does not include the border, and the second gradient is the full size, and the difference between them is the border shape. Genius!!!!

Genius indeed.

Chris’ Corner: Things I Like

Category Image 052

I like Melanie Sumner’s coining of the phrase Continuous Accessibility. To me, it’s like a play on the term Continuous Integration (CI) that is very pervasive. We build CI pipelines to lint our code, test our code, and test our code primarily, but all sorts of things can be done. We can test new code for performance regressions for example. So too could and should we be testing our new code for accessibility issues. Continuously, as it were. I’m very guilty of failing at the continuous part. I care about and act on accessibility issues, but I tend to do it in waves or sprints rather than all the time.


I like the career value that Ben Nadel assigns to learning RegEx. He says not a day goes by he doesn’t use them in some form (!). I wouldn’t say that’s true for me, but certainly every week or two I need to think about them, and over the years, my fear-factor in using them has scaled down to zero. They really aren’t that bad, it’s just a long steady learning curve to the point where eventually you feel like even if I’m slow I can ultimately reason this out. Either figuring out an existing one or writing a new one. Ben doesn’t just talk about it abstractly, he lists loads of practical examples.

Before I move on, allow me to show you Hillel Wayne agreeing with Regexes are Cool and Good (that’s my kind of title). Hillel mentions some valid reasons why people have a distaste for them, but then brings up a super good point: RegExes are particularly good when you’ve got some muscle memory for them and use them in little one-off use cases.

… where regex really shines is in interactive use. When you’re trying to substitute in a single file you have open, or grep a folder, things like that. Readability doesn’t matter because you’re writing a one-off throwaway, and fragility is fine because you’re a human-in-the-loop. If anything goes wrong you will see that and tweak the regex.

Heck yeah. If you get good at it, using them for Find/Replace reasons in your code editor can make you look like damn superhero.

Oh and thank heavens for RegEx101 and sites like it. So good.


I really like the CSS only “scroll-to-top” trick that David Darnes created and Stefan Judis wrote up. It’s just so deliciously clever. A scroll-to-top link is just a UX convenience and accessibility feature, as it not only scrolls to the top but moves focus back up there as well. It’s like…

<a href="#top" class="back-to-top-link">Back to Top</a>

But where and when do you show it? It could just be down in the footer of a site. But a classy way to do it is to show it on long-scrolling pages pretty much all the time — just not when the page is already scrolled to the top. Say you want to wait until the user has scrolled down at least 200px or something like that. Feels like JavaScript territory, but no, that’s where David’s trick shines: this can all be done in CSS.

The bare-bones part of the trick:

.back-to-top-link {
  margin-block-start: calc(100vh + 200px);
  position: sticky;
  bottom: 1rem;
  left: 1rem;
}

Here’s a demo.


I like the relative color syntax. Support for it is coming along and it’s in Interop 2024 so “actually using it” isn’t terribly far away. What I like is that it allows you to manipulate a color on the fly in a way that will actually work well without needing anything other than native CSS.

Thought process:

  • I’ve got this orange color
  • I wish I had a version of it that was a bit darker
  • … and is a bit alpha transparent.

So I’ve got the color:

body {
  --color: #f06d06;
}

Then I can use it, and I can use my modified version easily.

.box {
  background: var(--color);
  border: 20px solid oklch(from var(--color) calc(l - 0.5) c h / 0.5);
}

I’m using OKLCH there because it has “perceptually uniform lightness” so if I manipulate all my colors the same amount, they will feel the same amount manipulated. I don’t have to use that function, I could use rgb() or hsl() or even the generic color(). That’s the thing with the relative color syntax, it’s not any particular function, it’s largely that from keyword.


I like the idea of things challenging the dominance of npm. Much like Deno is challenging Node, and is literally from the same creator, now vlt is challenging npm and is from the same creator. Well, he’s on the team anyway. I remember listening to Darcy Clarke on Syntax saying some smart stuff about this new package manager possibility. Like, I’m the user, right? It’s my computer, and I’m asking this tool to go get a package for me. Why can’t I say “don’t get the README though, I don’t need it, and definitely skip the 1.5 MB JPG in that README, I just need the JavaScript file.” Makes a lot of sense to me. Give me a pre-built version! Don’t give me the types, I’m not using TypeScript. That kind of thing. I’m sure that like 1% of what this thing will be able to do, I just like the fresh thinking. I’m sure it’s more about the security. We’ve got JSR in there shaking stuff up now too, which I like because it isn’t friggin lowecase.

Chris’ Corner: Hard Things

Category Image 052

Julia Evans has an extremely relatable and extremely charming talk in Making Hard Things Easy. Julia has a way of putting her finger on technology concepts that are notoriously difficult and making them easier to understand. She does this both by sharing her own tactics, like learning a reduced set of options or commands, as well as by producing very approachable guides.

I like her formula: infrequent use + lots of gotchas = disaster.

(As a CSS guy who regularly hears people complain about CSS, this tracks.)

Another trick to avoiding that disaster is… using computers! Tools like linters can help you fix (or avoid) the very mistakes that can make a technology frustrating or error prone. She uses the tool ShellCheck, which I’d never heard of, as an example to avoiding problems in Bash scripts. Then, sharing when you find tools like this that actually help you. I found that last bit especially interesting. It’s good to be “intellectually honest” about sharing tools that really have helped you, not tools that seem like they could help you, because they look nice or whatever.


Speaking of hard things… you know what can be hard? Refactoring. I’ve probably over-repeated this, but David Khorshid one said “It should be called legendary code not legacy code”, referring to the idea that code that is in production doing work, even if you think it might be sloppy, inefficient, inelegant, is literally doing the job it needs to do. Whereas some theoretically rewritten wonderful code has yet to prove itself.

Miroslav Nikolov writes:

Code refactoring may cost a fortune if not done right. A dysfunctional revamped system or new features coupled with incorrect rewrite is, with no doubt, damaging. One can argue to what extent.

Refactoring code can be very dangerous, so it’s worth being very considerate about what you’re doing. A few of Miroslav’s points:

✅ Isolate improvements from features. Do not apply them simultaneously.

❌ Do not mix expensive cleanups with other changes. But do that for small improvements.


This makes me think about TypeScript.

TypeScript is (uh, obviously) newer than JavaScript, so there is a good amount of code out there that has been refatored into TypeScript. Whether than was worth it or not is up for debate. People that love it might say that a refactor like this actually makes the code safer, and they probably aren’t wrong to some degree, although it wouldn’t be hard to argue that any refactored code has risks.

There is also cost to the TypeScript itself. Build tooling and whatnot of course, but also the syntax itself. Remy Sharp has made the call that his own personal code isn’t in TypeScript, partially for this reason:

A “well crafted” definition, type or interface (still no idea when I should use each), is often a huge cognitive load on me.

Being presented with lots of double colons, <T> when I’m not sure what T refers to, a wall of interfaces and more is an upfront cost on me, the reader.

Often the types will be tucked away in other files (probably good) but working out the argument required to a function call often leaves me distracted in the task of understanding what’s required rather than making my function call.

I feel that. I’m slowly getting better at TypeScript myself, because at CodePen we’ve decided to take advantage of it when we can. I can see the value in it fairly regularly, but I’m also fairly regularly frustrated by it and question the hours lost. I’ve felt this way for years, and I’m still not quite sure what to make of that.


One of the reasons you might be refactoring something is because you’ve decided on some new abstractions. A classic, in my experience, is that you’re adding, dropping, or changing a framework. The old one just isn’t doing it anymore, times have changed, and you either want to go vanilla or move to something more modern. There is probably some kind of axiom where any sufficiently large codebase is always undergoing at least one refactoring per hundred thousand lines of code or the like.

Have you read the Hammer Factories thing? It’s a pretty satisfying read, save for a few dated stabs at comedy that read pretty misogynisticly. Sometimes you just need a hammer, is the thing, it’s clearly the right tool for the job, but the industry wants you to you some all-in-one hammer, wait, no, a hammer factory, wait, no, a factory for building hammer factories, wait, no…


It feels true to me that front-end specific work has always been treated as lower-value than back-end work. Don’t hate me, but part of me feels like that’s fair. I’m a front-end guy myself and actually think it’s extremely valuable, but ultimately most products real value lies in some kind of unique back-end magic. The problems on the back-end, on the whole, are harder and riskier and scarier, and that translates to higher paying roles. Of course there is tons of nuance here. A product with a very decent back end and total garbage front end is likely to have problems catching and may outright fail because of a poor experience for the people actually using the thing, and making an experience people love is weighted toward the front end. Or as Josh Collinsworth recently wrote:

In many ways, CSS has greater impact than any other language on a user’s experience, which often directly influences success. Why, then, is its role so belittled?

There used to be a time where if you knew both front end and back end you were a unicorn and it was considered very rare and you were a powerful force in this industry. Now unicorns are dead. We call that “full stack” now and it’s all but expected that you are one. Especially if you’re skilled in the front end, you can’t just say that, you have to say “full stack” or your job prospects ain’t looking great. Then the actual expectations of full stack mean that you’re good at the JavaScript stuff, you’re fine with the work that connects that JavaScript client work with JavaScript on the server, and you know enough front end to use a design system, library, or hack some workable things together.

It’s just a thought, anyway. It solidified in my mind reading Andrew Walpole:

The full-stack developer was borneth!

It looks great on paper, especially to the payroll department: One person to fill traditionally two roles. But in reality, we know it doesn’t work that way. It may be a role for a technology generalist to thrive in, but one person’s effort is finite, and consistent, quality development across the entire product development spectrum requires focus and expertise. Nevertheless, start-ups soaked up the efficiency, and in a tumultuous churn of web tech it was a decent defense.


There is a new Node.js website and it’s always fun to read a little behind-the-scenes. That would be a hard job but it looks like they did a great job.

Chris’ Corner: Some AdviCSS

Category Image 052

Get it?! Like “advice”, but for CSS.

When should you nest CSS?

Scott Vandehey says:

There’s a simple answer and a slightly more complicated answer. The simple answer is “avoid nesting.” The more practical, but also more complex answer is “nest pseudo-selectors, parent modifiers, media queries, and selectors that don’t work without nesting.”

The big idea behind avoiding nesting (which is a native CSS feature now, if you hadn’t heard) is that it can lead to specificity increases that just aren’t necessary. Like:

.card {
  .content {
    .byline {

    }
  }
}

That .byline selector probably doesn’t gain anything by being nested like that. Break it out of there and it’ll be more re-usable and easier to override if you need to.

But this:

.card {
  @container (width > 60ch) {

  }
}

Is probably good! It just saves you from having to re-write the .card selector again. Scott gets more in-depth though with more examples and I largely agree.

How do you adjust an existing color light and darker?

I’m a biiiig fan of the relative color syntax, which is great at this job, but before I go on a tangent about that, it’s not well supported yet so let’s not. It’s on the Interop 2024 list though!

Better supported is color-mix(), and Cory LaViska has the story on using it for this job:

Using color-mix(), we can adjust the tint/shade based on the background color, meaning we don’t need to manually select lighter/darker colors for those states. And because we’re using OKLCH, the variations will be perceptually uniform, unlike HSL.

By mixing white and black into colors, and doing it in the OKLCH color space, we can essentially tint and shade the colors and know that we’re doing it evenly across any color we have. This is as opposed to the days when a lot of us tried to use darken() and such in Sass only to find extremely different results across colors.

How are the final values of Custom Properties calculated?

Stephanie Eckles:

Custom properties – aka “CSS variables” – seem fairly straightforward. However, there are some behaviors to be aware of regarding how the browser computes the final values. A misunderstanding of this process may lead to an unexpected or missing value and difficulty troubleshooting and resolving the issue.

Custom Properties follow the cascade and are computed at runtime, for one thing, which is the whole reason that they cannot be preprocessed ahead of time. But it’s more complex than that. What if the value is valid for a custom property (most anything is), but not valid for the way you are trying to use it?

This is a real head scratcher:

html { color: red; }

p { color: blue; }

.card { --color: #notacolor; }

.card p { color: var(--color); }

Turns out .card p will actually be red (I would have guessed blue), but Stephanie explains:

The .card p will be the inherited color value of red as provided by the body. It is unable to use the cascaded value of blue due to the browser discarding that as a possible value candidate at “parse time” when it is only evaluating syntax.

How do you accommodate people who struggle with transparent interfaces?

Adam Argyle explains it can be like this, using this media query you may or may not have heard of:

.example {
  --opacity: .5;

  background: hsl(200 100% 50% / var(--opacity));

  @media (prefers-reduced-transparency: reduce) {
    --opacity: .95;
  }
}

Adam had lots of practical examples in the post, and does consider that word reduced, and how it doesn’t mean absolutely none ever.

What units should you use for spacing properties?

Me, I just use rem usually as that’s what I use for nearly everything else. But Ashlee M Boyer argues that while stuff like text makes good sense to use relative units, spacing need not scale at that same rate:

When a user is customizing their viewing experience, they thing that’s most important to them and their task at hand is the content. Spacing isn’t often vital for a user to perform their task, so it doesn’t need to grow or scale at the same rate as the content itself.

When spacing between content grows, it eats up vital real estate and becomes harder to manage.

Ashlee proves it with a before video and an after video, after being moving relative units to absolute units for spacing.

How do you make every Sass file automatically include common imports?

This one hits home for me, as someone with a codebase with easily hundreds of Sass files that all start with something like @import "@codepen/variables"; Wouldn’t it be cool if Sass could just assume we wanted to do that for every file?

Austin Gil covered this a while back on doing it with Vite. When you define your Vite config, you can like:

  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/assets/_shared.scss";`
      }
    }
  }

I see webpack can do it too, but I’m not sure if Sass alone can be configured to do it, although I wish it could.

Chris’ Corner: Scroll Driven Delight

Category Image 052

I’m pretty hot on Scroll-Driven Animations! What a wonderful idea that we can tie @keyframe animations timelines to scroll positions. And I’m sure the creators of it thought long and hard, because the API makes a ton of things possible. It’s not just “how far the entire page has scrolled”, although that’s possible. The progress through the animation can be tethered either to the scroll position of any element or to the position of an element within a scrollable container. Those are referred to as the Scroll Progress timeline or the View Progress timeline respectively. Slow clap, people.

Bramus Van Damme makes that nicely clear in this overview article. Bramus has been following, working on, creating demos, and writing about this stuff for a long time, and it was a smart move to wrap all that stuff up in a dedicated website for it.

I’m also a big fan of his co-worker Adam’s approach to an intro article here. Adam makes demos that are a smidge more designery and those tend to land with me. And speaking of designery demos, Ryan Mulligan’s beginning explorations are wonderful. He’s got some Polaroid photo style images that “blur in” when they scroll into view and a pair of photos that shuffle themselves as you scroll. I share Ryan’s sentiment that the tools Bramus has built are nearly crucial in understanding this stuff, since all the different keywords and values have such big effects.

These scroll-driven animations tend to be things that are just fun and could easily be thought of as progressive enhancement. So the fact that this is Chrome-only for now isn’t terribly bothersome to me, although it is polyfillable. We also didn’t get scroll-driven animations on the Interop 2024 list, but that doesn’t mean we won’t get Safari or Firefox support this year. Still could happen, just not really a guarantee.

Why do I think this is so cool? It’s not like we absolutely couldn’t do this before. Greensock has a ScrollTrigger plugin that is widely loved and has a pretty sweet API. (Here’s a great Collection.) I don’t think it’s terribly egregious to use JavaScript for these kind of effects, particularly if it makes them more maintainable, performant, or do things impossible any other way. But that’s the thing — when these abilities come back to native web technology like CSS, chances are the performance is going to be great and arguably more maintainable thinking long term as the people familiar with the technology will grow.

Yuriko Hirota did a great job of proving how much more performant using CSS for these types of animations are. The single-threaded nature of DOM interactive JavaScript means that if JavaScript is busy doing anything else, a JavaScript-powered animation is going to suffer from jankiness, that is, jerky and non-smooth animation. Even when JavaScript is quite busy, a CSS powered animation is fine. Those “scroll progress animations” are the classic demo of this web tech. Michelle Barker went deep on those this past year, starting with the basics and getting lovably weird as the article goes on.

Let’s end with a little tip! Bramus mentioned that if you’re setting up a scroll-driven animation that involves a target element and different scrolling element, if it’s not working, there is a good chance…

The culprit: an overflow: hidden sitting somewhere in between the target and the scroller.

It’s always the overflow, isn’t it? I find overflow is usually the culprit in figuring out why a sticky positioned item isn’t working as well. The solution, if you do actually need to deal with hiding overflow, is to use overflow: clip; instead, a relatively new ability. Kevin Powell covered a couple other scenarios where overflow: clip; saves the day, so it’s definitely worth knowing about!

I’ve been playing with Scroll-Driven Animations myself a bit. I wrote one bit about highlighting a bit of text as you scroll down a blog post, something I was inspired by from Lene Saile’s blog. As a response to a reader question, I also figured out how to zoom in images when they come into the viewport as well. Both of those ultimately use the scroll position to control the point in the animation to be at, which I think is usually nice, but I also enjoyed the idea that you can un-tether those things (say, run a 3s animation once an element becomes fully visible) by flipping a --custom-property in a keyframe which triggers a different keyframe, like Ryan Mulligan digs into.

It’s still early days for Scroll-Driven Animations and there are sure to be extremely clever ideas people will find for years. My jaw was already dropped by using them to fit text exactly to a container and to write conditional logic detecting if an element can scroll or not.

Chris’ Corner: More Like Celebrating Style Skills

Category Image 052

It’s January and we’re seeing a little round of CSS wishlists make the rounds.

  • Tyler Sticka is mostly hoping for better support on stuff that already is starting to cook, like View Transitions, anchor positioning, balanced text, and scroll-driven animations. But he’s got his own new wishes and has done the leg-work to properly propose them, like more useful vertical alignment (without extra work).
  • Christopher Kirk-Nielsen also has some wishes for better support for thing that ought to be doing that naturally, like Style Queries, but also has some really interesting ideas of his own like using transform to force an element of an unknown size into a specific size, which he also wrote up properly.
  • Manuel Matuzović has more love for Style (and State) Queries (agreed there is some real potential here to reduce CSS size and complexity) and @scope. On the doesn’t-exist-yet side, a vote for mixins to which I’ll echo: Yes, please!
  • Elly Loel weighted in last year using the same distinctions: stuff that is already cooking (e.g. Custom Media) and stuff that doesn’t exist yet (e.g. detecting flex-wrap). Good news for Elly, some stuff from the list got done, like subgrid.
  • Nathan Knowler joins the choir with strong votes for Style Queries, Scroll-Driven Animations, and @scope, among others.
  • Sarah Gebauer has a great one on her wishlist about borders and controlling the offset. Hey, SVG can do it and it’s super cool. Plus a shout out to a personal favorite: more useful attributes and the attr() function.

Phew! That’s a lot of people taking the time to be pumped about CSS and make clear what they want. The way CSS is going lately I would not be surprised to see massive progress again in 2024.


Stephanie Eckles points out 12 one-liners in CSS that are all tremendously useful and powerful.

One liners.

Stuff like p { text-wrap: pretty; } that just makes web type all the nicer. Five years ago our gapping mouths would have been on the floor if they knew what was coming.


Brecht De Ruyte took two brand new CSS and HTML things and smashed them together:

  • The new <selectmenu> element, which is exactly like <select> except fully CSS styleable.
  • The Anchor Position API

It’s a cool interaction that is supposed to end up like this:

But this was actually published mid-last-year, and the demo is already broken even. It only ever worked in Chrome Canary with the Experimental Web Platform Features flag turned on, so that just goes to show you how fast this experimental stuff moves.

It’s not <selectmenu> any more, it’s <selectlist>, but even after forking the demo and trying to fix it, I couldn’t get it. I suspect it’s changes to the Anchor Positioning API that I’m not up to snuff on. I do suspect this interaction is possible today, but you’d either be using cutting edge APIs that may or may not be polyfillable, and/or recreating a ton of interaction and accessibility stuff that you’d get for free with Brecht’s implementation.


Ben Frain has a very clever idea for drawing angled lines in CSS (like a line chart). Which, weirdly, isn’t a particularly easy thing to do in CSS. You can make lines various ways and rotate them and stuff, but it’s harder to be like: draw a line from here to here. SVG is typically the path for that.

In Ben’s technique, you take advantage of the polygon() function and clip-path. You “draw” points in the clip path at certain coordinates, then go back over the exact same coordinates with a 1px difference, leaving that little gap where a new color can “shine through”.

Like:

clip-path: polygon(
  0% 60%,
  20% 90%,
  40% 43.33%,
  60% 61.67%,
  80% 23.33%,
  100% 18.33%,
  100% calc(18.33% - 1px),
  80% calc(23.33% - 1px),
  60% calc(61.67% - 1px),
  40% calc(43.33% - 1px),
  20% calc(90% - 1px),
  0% calc(60% - 1px)
);
Demo

Robin Rendle once made a bunch of different chart types in CSS only, but I don’t think I’ve seen a CSS “sparkline” like this until now.

Chris’ Corner: Switch

Category Image 052

The “switch” is a pretty common design pattern on the web. It’s pretty much a checkbox. In fact, under the HTML hood, it really ought to be an <input type="checkbox"> or perhaps a <select> with just two <option>s (or a third if there is an indeterminate state).

But unfortunately, the web doesn’t give us any primitive that looks particularly switch-like, as in, some kind of knob that is flipped one way or the other. So we use CSS. For example, we hide the checkbox one way or another, making sure there is still a discoverable clickable area, then with the :checked selector, style something that looks switch-like.

Here’s a very classic example.

Marcus Burnette nicely re-creating the iOS toggle look

I’m sure you could imagine using that for, say, toggling email notification settings on an off for some sort of app. We use them here on CodePen quite a bit, for stuff like toggling the privacy of a Pen. Or you might use a toggle to switch a site between dark mode and light mode.

Speaking of that, Aleksandr Hovhannisyan has a solid article about the struggles of a dark mode toggle. You’d think it would be pretty straightforward, but it really isn’t. Consider that users have system-level preferences in addition to your site-level preference, and you have to honor them in the proper order. Plus you have to set the controls properly as well as actually style the site accordingly, ideally without temporarily flashing the wrong colors. (FART). Aleksandr does a good job of it and links to other posts that have done a similarly good job. It’s always way more code than you want it to be, leading me to think browsers and standards could and should get more involved, but I also admit I don’t have a perfect idea on what they should do. Chrome has played with Auto Dark Mode, but it’s not clear how that trial went. (And speaking of Dark Mode, this gallery is pretty nicely done.)

Anyway, I was trying to talk about switches!

I saw Jen Simmons note that Safari is playing with a native switch. Here’s the HTML:

<input type="checkbox" switch>

Nice.

And here’s what it looks like by default:

No big surprise there! It’s the native iOS toggle come to life. It respects accent-color in CSS like other form controls, which is great. But better, it has really sensible pseudo elements you can grab and style. You get ::thumb and ::track elements (nice clear naming) plus ::before and ::after work on the element itself, so there are a lot of possibilities.

.custom-switch { }
.custom-switch::thumb { }
.custom-switch::track { }

.custom-switch:checked::thumb { }
.custom-switch:checked::track { }

.custom-switch::checked::after { }
.custom-switch::checked::before { }

Tim Nguyen has demos that do a good job of showing off the possibilities with clean readable CSS.

The best part of browsers providing this kind of thing for us, to me, is that now you don’t have to worry about dinking up the accessibility. Now, as long as you follow the normal HTML structure of a labelled checkbox in a form, you’re good. No worries about the way you hid the original checkbox screwing things up. You are taking visual control though, so do take care to make sure the checked and unchecked values are at least as clear as a checked or unchecked checkbox.

Chris’ Corner: Mentals and Models

Category Image 052

Josh Comeau has a new learning guide out for CSS grid: An Interactive Guide to CSS Grid. I like how Josh gets into the “mental model” right away, because that’s the biggest thing with big APIs like this: you need to get the basics of how it works in your head so you know when and why to reach for it. The niche details are less important. You can look them up. Mostly you need to understand that the thing exists and what it is capable of. Ideally you can write a basic setup from memory. Then the more niche stuff you reference. Josh’s guide, especially with the interactivity, loads you up with that mental model.

Josh has done the same before with an An Interactive Guide to Flexbox. The interactive bit goes a long way in locking in that mental model. In my CSS-Tricks days, our guide to flexbox was also decent at explaining the model I think, and also was a decent reference guide at the same time. But it didn’t have that interactivity so people were left to extracting the information to their own code to play. Once people are writing their own layout code, I’d wager that’s also a pretty big moment for locking in a mental model. CodePen editable embeds might be a good way to bring that to guides like this. I know that a very lot of people had their ah-ha moment with flexbox via Flexbox Froggy, and I think it’s that combination of interactivity and real code that made that so effective.


Speaking of Cool Josh Ideas, have you seen his operator lookup page? JavaScript has a pretty decent number of operators, and some of them you really have to look up to remember sometimes:

Sometimes my brain goes… what’s the one where you set the value, but if the value is null, provide a fallback. Which is this one.


Do you know about import maps yet? They aren’t some new niche thing, they are supported across the board. (Well, a little new, maybe).

I like Yoshi Huang’s article(s) on them, they do a good job of setting the stage.

My brain goes a little like this. This is really common code to see, but it’s actually invalid JavaScript:

import lodash from "lodash";

If you see code like that, traditionally, it means that the JavaScript will be going through a processor of some sort that is going to resolve "lodash" to some actual location where that code can be found. If we wanted that code to be valid JavaScript, we’d either have to:

  1. Import from a relative file path (e.g. that string has got to start with a dot or a slash)
  2. Import from a URL

The latter being like:

import lodash from 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm'

But now, the original import statement actually is valid. That is, as long as we use an import map. From Yoshi’s article, something like:

<script type="importmap">
{
  "imports": {
     "lodash": "/node_modules/lodash-es/lodash.js"
  }
}
</script>

Think of it like string replacement. The "lodash" in the import statement becomes "/node_modules/lodash-es/lodash.js" and a valid relative file path import. That could be a URL as well.

I like the idea that an import map can help orchestrate imports across an entire codebase from one place, and eliminate a lot of repetition, and be a tool in using less build processes.

I talk about them quickly in a video I did the other day if that’s helpful. There is some extra nuance to them, like an import map key can replace only part of an import path if that’s helpful.

It seems like a relatively small thing in the wide world of web development, but I think it has big implications. I know Baldur Bjarnason definitely thinks so, as he’s got a whole course called Uncluttered: Free yourself from Node with import maps and test-driven web development, which I’ve just started taking myself.


Shout out to Flavio Copes for the recent release of The Valley of Code which looks like a great reference, up from “first principles”, of web development work. Not a lot of guides like this are so comprehensive the start out with URLs and DNS before going on to higher level languages like HTML and CSS.

There is even a section on using CodePen so color me a little biased.


I shared a video of Szenia Zadvornykh’s Crowd Simulator the other day (just because it’s awesome). It’s just one image if you can believe that. Us early 2010’s developers remember sprite sheets.

It’s almost like those illustrated people are the result of some fancy drawing algorithm. Well, here’s something like that! CSS-PEEPS is “one CSS file, one <div>, and over 5 MILLION combinations” of people.

That’s me in 2 years when I inevitably need glasses and try hair regrowth techniques doing my “well actually” look.


A bit of a random add-on here, but I think I agree with Evert Pot when he says:

So while React/Next.js may be relegated to the enterprise and legacy systems in a few years, they completely transformed front-end development and created ripple effects in many other technologies. One of many great ideas stemming from this stack is JSX. I think JSX has a chance to stay relevant and useful beyond React/Next.

I’m maybe a little more bullish on Next.js because it does a lot really well, has a lot of momentum, support, and has some DX that is hard to match. But that’s a little besides the point. JSX, as an industry thing, might just end up having bigger influence over time than React itself. It’s just a pretty good HTML templating language.

Chris’ Corner: Fresh Type

Typography Definitions Cover

I like the feeling of a good fresh typeface. Like design itself, type design has trends, and without being able to articulate it particularly well, I feel like I can feel a fresh type look from a stale one. That’s probably the thinking of an amateur, and I’m sure the world’s fanciest designers probably used one typeface their entire career and would scold my fickle soul. But also whatever. I’m cool with being the ever-changing Pepsi logo to the never-changing Coca-Cola logo.

Saikrishna Vanneldas did a good job of rounding up some newer fonts in the article Bored with Poppins & Inter, Here are Some New fresh Sans-Serif For 2023. They are all free / open-source, so that’s nice, not that I don’t think we all should be paying for type (we should, just not all situations call for that).

Jakarata Sans on Google Fonts
Manrope on Google Fonts

You know how a “viewport unit” in CSS (e.g. vw, dvh, vmax, etc) essentially boil down to “1% of the browser window” in the given direction? Well hopefully you know that we also have container units now (supported across the board) which are very similar but “1% of the nearest container” in the given direction.

If you’ve been interested in implementing the idea of fluid type over the years, you know that a lot of it is done with viewport units and clamp() to achieve fluid type sizing across different size screens while capping the min and max sizes against extremes.

It’s worth thinking about making container units a part of this story. It’s pretty clear to most that container queries are the best way to style an element based on its size. But that doesn’t help as directly with things like sizing type. Container units certainly do.

It might be as simple as something like this:

.card {
  container: card / inline-size;
  ...

  h2 {
    font-size: clamp(1.4rem, 1rem + 5cqi, 4rem);
  }
}
Example Pen

I’m using cqi here which you can think of like “container units in the inline direction” and I think it’ll be a commonly used container unit.

Stephanie Eckles has the best deep dive article on this in Container Query Units and Fluid Typography. Stephanie covers setting up a proper system for all this with fallbacks and such.


Say you were going to publish a book online as a web page. A book, implying a whole lot of text. Call it 100,000 words. You need to think about the experience of that. Are there chapters of decently small length such that each of them could be almost like a blog post with an individual URL and you can proceed through them in a linked manner? Would you make the entire thing one massive single HTML page that you just scroll through? Maybe go old-school cool and use a library like Turn.js to make epic skeuomorphic page turns??

(Naturally, there are a bunch of cool examples of page turning on CodePen.)

There is no one right answer, but I have seen some good examples recently:

  1. Robin Sloan’s e-book template Perfect Edition uses horizontal scroll-snapping to create a book reading experience that is how most modern e-book readers look/work to me.
  2. Mat Marquis’ JavaScript for Web Designers by A Book Apart is published online for free and has an extremely classy paginated-blog-posts look.
  3. Jeremy Keith’s Resilient Web Design works offline (assuming you’ve been there once), which is a nice touch.
Perfect Edition

Elliot Jay Stocks has a new podcast called Hello, type friends! which is an easy subscribe for me. Elliot says they won’t get into visual nuance of typography on the show, because audio would suck for that, but everyone involved will be type people so sounds fun to me. I enjoyed the first one with Jessica Hische.


There is this thing called Emoji Kitchen which allows you to combine emoji together:

But in order to use it, it’s baked into Gboard, a keyboard replacement thingy with all sorts of random features (works on Android and iOS though which is cool). They do now have a page that lets you browser the combinations right from the web.

The UI was a smidge confusing to me at first. You pick one from the top, then that middle panel just shows you the combinations it can make. You don’t get to pick any two random emojis and see what happens. Still super cool.

What’s funny, though, is even though Emoji Kitchen is only a year old and they don’t really say how it works, don’t you kinda just assume it’s AI-powered? If they did these by hand, I bet they probably wouldn’t now, just a year later. Facebook is making stickers with AI which isn’t terribly different than this really, except for, ya know, it’s totally un-curated and can make questionable stuff.


Random periodic reminder that variable fonts are awesome, this time from Jason Pamental who has been tooting that horn for a lot of years. Fixel is an awfully nice new one. If by some chance you’re using a variable font, but find the file size a little worrying, know that there is an app to remove the axes you aren’t using which can have pretty big savings.

Chris’ Corner: Can Has Blurs, Filters, and Masks

Category Image 052

You’ve seen CSS’ new :has() selector right?

There are all these “basic” use cases that leave me smiling because the solutions of the past were inelegant at best, and now are easy and satisfying. Here’s one:

  1. You want margin below your <h2>
  2. … unless there is a <time> right below it, then no margin
  3. … but put the margin below the <time> instead.

One approach to this with :has() is just a few lines and reads very clearly to me:

h2 {
  margin-block-end: 1.2rem;
  &:has(+ time) {
    margin-block-end: 0;
  }
  &:has(+ time) + time {
    margin-block-end: 1.2rem;
  }
}
Demo

But as I mentioned, that’s a “basic” use case. The power of :has() is very deep, as it allows for inspection from any DOM element down the tree, then moving as far back up as needed. It’s a bit hard to wrap my mind around that sometimes. Like Jim Neilsen said:

I feel like lots of people have their own little oh yeah! moments with this CSS feature. Michelle Barker blogged a few of them, including an interesting combination with the :target selector. Does a certain “have” an element that is targetted? Yes? Animate the grid to reveal an otherwise hidden area:

Poking around my own code bases, I can see it starting to sprinkle in. It’s interested to see when it comes to unknown data coming into templates. Here’s a JSX example:

<div class="things">
  {things.map(thing => {
    return(
      <div class="thing" key={thing.id}>
        <h3 data-category={thing.category}>{thing.name}</h3>
        {thing.text}
      </div>
    );
  })
</div>

Here I’ve spat out a total arbitrary list of “things”. I found it most useful to have the data-category attribute on the header, as direct styling with that was useful. But what if the parent needs styling based on that? Easy:

.thing:has([data-category="widget"]) {
   background: yellow;
}

More, what if the entire group needs a special style? And if it does, make all the headers smaller?

.things:has([data-category="widget"]) h3 {
  font-size: 80%;
}

Go down, then back up!

I’m even very-mindblown-y on the idea that quantity queries are now easy. Does this list have at least 11 items in it? Yes? Then do something:

ol:has(li:nth-child(11)) {
  color: red;
}

Get out of dodge.


We’ve had blend modes in CSS for a while. You use mix-blend-mode when you’re trying to blend an elements content with it’s background. You use background-blend-mode when layering backgrounds and wanting to blend those.

It still strikes me as a surprisingly cool thing we have access to directly in CSS. And it’s niche enough that when I see it used, it’s usually a pleasant surprise.

Brad Woods has an awesome article showing off how they work. Interactive examples really does blending justice here.

Those look dramatic, but blending can be rather subtle. Brad has all sorts of other examples like blending gradients over images, blending textures, blending patterns, that all end up quite nice and the fact that they are programmatic just feels cool and powerful.

Koding Kitty has a similarly good explanation page, specifically using provided Tailwind class names to do the blending over top a single-color icon. I always thought Robin did a good job on the old CSS-Tricks page as well.

You know what I always think of with blending, though? It’s not a CSS property that you just learn and then you know it. All you can learn is the general category of what it can do and the circumstances it might be useful. Then, you have to guess and test your way to a good outcome. One might argue a lot of CSS is that way, but I feel like blending is particularly this way.


Speaking of excellent interactive tutorials!

Artur Bień is all over it in Blur Vignette effect in CSS.

How would you pull of this in CSS?

Quickly, it’s to layer two copies of the image, blur the top one, and use a mask to only reveal the edges of the blurred version. The hard part is crafting the mask. Artur does it with 6 layered gradients which gets the effect just right.

Don’t miss the Windows 98-ish interactive demo at the bottom which lets you totally control different Aspects of the effect.

Artur is the master of getting these kind of details right. Check out this quick screencast video he tweeted about getting a “glass overlay” effect just right. I’d be like “that’s what backdrop-filter is for!” That’s in there, but it doesn’t account for the, as Artur puts it:

In reality we see glass objects reflecting light even before they are placed directly between our eyes and the light source.


Well we’ve touched on filters, blending, and masking, I suppose it’s not out of line to hit shadows too. I enjoyed Preethi Sam’s thinking differently in A Few Interesting Ways To Use CSS Shadows For More Than Depth. Shadows can have properties that make them quite un-shadow-like, like having zero blur, being inside an element, being whatever color you want, and even being layered. Like how good are these hovers?

Nothing wrong with using shadows for shadows though! I ran across boxshadows.xyz the other day and it’s a pretty nice tool for doing layered shadows that have a better depth effect than any one shadow alone can do.

I just love that sort of look. It’s intense looking in that exact example, but a slightly more subtle version with a bigger shadow behind and a slight lighting effect inset on top is just a really juicy effect that works well on the web.

You know what else is hot right now? Blurred and colored blobs as backgrounds. As ever, you can make those as images and use a background-image (I’ve seen Figma plugins like this and this). But it’s fun to do programmatically of course as you can color them as needed, make different sizes, and even animate them.

Andrew Walpole took a crack at it with Glowing Blurred Backgrounds with CSS. The filter property does the heavy lifting getting the blurryness going, but getting the shapes together in which to blur is very clever.

Below the (left) turns to the (right).

Chris’ Corner: Things I Totally Didn’t Know About That I Learned From Taking the State of HTML 2023 Survey

Category Image 052

Lea Verou helped craft the State of HTML 2023 Survey — the first of it’s kind! HTML, you say? What is there to ask? HTML isn’t exactly what I’d think of as a fast-moving technology. I hear there is a <search> element now, so that’s new. It’s sugar for <div role="search">. I like it. Is there much more than that? Well lemme just have a click over to the survey and take it for myself. 😳. Uhm yes there is much more than that.

I actually do try to keep up with this sort of thing, and I’ll tell ya going through this survey had me clicking that “🤷 Never heard of it” choice quite a bit. Allow me to pick out a few that surprised me.

  1. I didn’t know you could programmatically open an input’s UI. Like if you have a reference to it, you can dateInput.showPicker(). Funny twist though, you can’t try it within the CodePen editor or else you’ll get a HTMLInputElement::showPicker() called from cross-origin iframe. error. It’ll work fine in Debug Mode though. I don’t think you can declaratively open it, though, right? You should be able to.
  2. I knew that you could make an element “editable” by adding the contenteditable attribute, but I didn’t know you could opt-out of the rich tech formatting with contenteditable="plaintext-only". Looks like everybody but Firefox already has it. Just to make everything about me: consider the UI of the header area of a Pen. If you own it and hover over the title, you can click a little ✎ icon to edit it. We don’t use contenteditable there because I’m worried someone will copy and paste the entire Yahoo! homepage in there (kidding, kinda). But rich text is entirely irrelevant there, and this would be a nice alternative to the text-element-flip-flopped-for-a-text-input like we currently do.
  3. I didn’t know that there is a plan to allow the name attribute across multiple <details> elements, which makes it so only one can be open at a time, a common “accordion” pattern. I somehow thought Safari was going to be first out of the gate with this with v17, but I was wrong. So nobody is shipping it, but I do like it. Clever idea, if a little hard to discover.
  4. I knew about <script> attributes like async and defer but didn’t know about this one that essentially does the opposite: blocking="render". That’s not, like, a great performance characteristic, but if you’ve got JavaScript that really needs to execute before a user sees anything (rather than showing something and having it flop out post-rendering), I could see this being useful. I guess any bundle that includes React should use this eh?
  5. I didn’t know there was a <model> element, for showing 3D models. I have no idea how it works. I would guess it’s largely semantic rather than functional. Seems early.
  6. I knew about JSON imports, like import json from './foo.json' assert { type: 'json' }; which I really like as it saves me from a ceremonious fetch-and-parse. I’ve also heard of the CSS version ala import sheet from './styles.css' assert { type: 'css' }; which then allows me to donk those styles onto the document or any resistant shadowRoot. But I didn’t know the idea was being extended to HTML like import { TabList } from "./tablist.html" with { type: 'html' }; I guess it’ll make it easier to define custom elements that reside within that chunk of HTML? I can’t quite picture it yet so would love to see examples.
  7. I had never heard of the focusgroup attribute. I read up a smidge and it’s very interesting! If I understand it right, it essentially allows you to make a group of focusable elements respond to arrow key navigation within the group. If you hit tab again, you’d leave the whole group of focusable elements. Like a group of radio buttons! But with whatever group you want.

While we’re deep in HTML land here, allow me to reach into my bag of links and share some of the most interesting ones related to HTML I’ve saved lately.


One of the most interesting things starting to arrive in HTML is popovers. “Popovers are everywhere on the web.” says Una Kravets introducing them. Menus, tooltips, button dropdowns, etc. It’s like a little chunk of UI that needs to sit over all the other UI. Often easier said than done! CSS’ darning z-index can only take you so far. If you’re deep in a nested DOM, you often can’t get a bit of popover UI high enough, and need to resort to JavaScript manipulation to move it somewhere higher in the DOM, which has it’s own set of problems, like positioning complexity and accessible connective tissue to what controls it. Native popovers promote themselves onto some magical higher rendering layer which is on top no matter what. Awfully fancy.

I would think anchor positioning goes together with this like peanut butter and jelly. If you just wank the popover in the middle (which I think it does by default)… isn’t that just a <dialog>? Fortunately Hidde de Vries has us covered here with Dialogs and popovers seem similar. How are they different? I wish I could but I can’t do better than his summary so:

OK, so, in summary: modality of a component is a state in which only that component can be used. When something is modal, everything else is inert: blocked from access in any way, unfocusable and usually obscured with a backdrop. Making something modal is a substantial decision, it should be used sparingly. Dialogs can be modal or non-modal (also called modeless). popovers are being proposed by Open UI as a new way to build non-modal dialogs with a specific set of behaviours and characteristics, like top layer presence, JS-less toggleability and browser-provided light dismiss. Unlike <dialog>, a popover does not have a built-in role: as a developer, you can add the popover attribute to the semantically most relevant element

You know what Safari 17 totally does have? Popovers. I’ll paste their example HTML here in case you wanna copy and paste it yourself into a new Pen in Safari 17 and have a test:

<button popovertarget="info-box" popovertargetaction="show">More info</button>

<article id="info-box" popover="auto">
  <h2>Additional Information</h2>
  <p>Here’s something I wanted to tell you.</p>
  <button popovertarget="info-box" popovertargetaction="hide">Close</button>
</article>

Just a quick high-five to Rian Rietveld for a darn fine overview of crafting the perfect link. Introductory content is everywhere, but the good stuff is hard to find (this is from 2021). Not a ton of code examples, which to me makes an article like this even harder to write.

I just used a little link-related trick I nearly forgot about the other day: using the download attribute like:

<a href="/files/pitch.pdf" download>Download Pitch PDF</a>

I think Dave has a good point here: Markdown images are an anti-pattern. I’ve always said images are hard, in part because of how many attributes you need to know about and put on the <img> tag. Just loading="lazy" alone is huge. Some Markdown processors allow for additional attributes in the Markdown syntax, but not all, and the format for that isn’t particularly pretty (and of course, totally non-portable to other processors). Thankfully Markdown supports HTML, so just use that.


I’ll leave you with the html review:

Our 2023 issue is made up of 17 contributions that span modes of digital literature and experiment. We have poetic instruments, interactive fictions, illustrated essays, movable lyrics, linguistic gardens, and pixelated memories.

Why I chose Codepen PRO over Copilot

Featured Imgs 23

Strange premise from Jon Ellwood, right? He explains:

I will acknowledge that CodePen and Copilot are two different products, and it might seem odd to be comparing the two – but the commonality for me is that my budget only allows for one of them to get my money each month.

While Copilot could give me code, it never sparked any ideas. It could suggest ways to accomplish what I thought I wanted – but on many an occasion, CodePen has taken a spark of an idea and ignited it into a full-fledged feature.

Thanks for the support, Jon! And speaking of which:

… if I am going to give money to a company and thereby publicly support them.. CodePen is what, 10-15 people? Maybe more, maybe less.

It’s less! Straight up, that support helps us run CodePen and fuel it’s future.

The post Why I chose Codepen PRO over Copilot appeared first on CodePen Blog.

Chris’ Corner: Web Components Don’t Need You

Category Image 052

Dave Rupert blogged a bunch of reasons about why you probably aren’t using them yet. Some of it is technological, and more of it is historical, marketing, and psychological reasons. Then Dave, a pretty avid Web Components follower and advocate, followed up with another surprise. Should you rewrite your app to use them? Probably not.

It’s not that you shouldn’t use them because they aren’t good, it’s:

If your components only have one place to go, then you probably don’t need Web Components. Even if your components service a couple different apps or product teams that all use the same uniform tech stack, you probably don’t need Web Components. Where Web Components shine is when your components need to go to many places.

The grid of logos on https://arewebcomponentsathingyet.com/ tells that story: very big companies.

Nolan Lawson followed that up with Use web components for what they’re good at, a more specific take on this, which largely agrees with Dave. Big companies are reaching for them because they solve actual problems for them. But enterprise isn’t very present on social media, so you just don’t hear about it as much.

So why are big enterprises so gaga for web components? For one thing, design systems based on web components work across a variety of environments. A big company might have frontends written in React, Angular, Ember, and static HTML, and they all have to play nicely with the company’s theming and branding. The big rewrite (as described above) may be a fun exercise for your average startup, but it’s just not practical in the enterprise world.

Having a lot of consumers of your codebase, and having to think on longer timescales, just leads to different technical decisions. And to me, this points to the main reason enterprises love web components: stability and longevity.

If you have some of those problems, you’ll probably benefit from Web Components and could or should use them, or maybe you already are. If not, whatever. Nobody needs permission to use them, and plenty of companies are doing it without a single care about what the social media vibe is on them. Web Components still have some problems, and fortunately, are still being actively worked on, so the story should get better year after year, in case you’re on the fence and watching.

Nolan does shout out one thing Web Components excel at, obviously and immediately:

To me, [client-rendered leaf components are] the most unambiguously slam-dunk use case for web components. You have some component at the leaf of the DOM tree, it doesn’t need to be rendered server-side, and it doesn’t <slot> any content inside of it. Examples include: a rich text editor, a calendar widget, a color picker, etc.

Dan Ryan has another take: they can be really simple. He used a header component as an example, which didn’t buy them anything extreme — just a simple update for a simple benefit.

So what did this gain us? For this example not much really. But where it really shines for us is only loading the CSS needed for the components used on a given page. Most of our visitors only view a single campaign page which uses just a few components. Previously though we were bundling all our CSS into a single file and serving it to everyone.

I’m the biggest fan of Web Components when you can just pluck one off the shelf and use it for something useful, knowing it’s lightweight and flexible. Nolan’s own emoji-picker-element is a classic example. When I see one-off componentry that isn’t a Web Component lately, I immediately wish it was. Check out this OverlayScrollbars “plugin”. Wouldn’t it be awesome as an <overlay-scrollbars> component, making it declarative and easy to use? (Yes.)

But I’m down for bigger approaches, too, so long as they are solving a problem. Google’s Material Design is an example of that. Material 3 is their latest take, and it seems to be mostly leaning into native apps, with the web version “coming soon”. When it does, it appears as if it’ll be Web Components-based. That’s cool and maybe even a touch surprising, being that Google could have used it as a way to promote Angular. But just because they went Web Components doesn’t mean they didn’t go Angular, assuming they work nicely in Angular, which let’s just hope they do.

Allow me to end with a little linky-uppy: Tram-Lite. I really like how you just use HTML to define the whole component, then go on to use it elsewhere. It requires no build process and has a very native feeling. Actually, check out the principals — they seem sound to me. And I’m not just saying that because it works great on CodePen.

Chris’ Corner: Even More SVG Tricks

Category Image 052

SVG has so many tricks up its sleeve. It’s really a full-featured drawing API literally designed for the web, but few of us really truly understand it nor reach for it enough. Heck, I even wrote a book about it, and I don’t. At the time, just getting people to use SVG for icons felt like an uphill battle, but thankfully, I think that one has been won.

Let’s look at some cool SVG examples that have crossed my desk lately.


Animate an SVG Shape’s Inner Stroke

Christopher Kirk-Nielsen with a variety of demos that are a good reminder that stroke is animatable (like the width of it), which can do some cool effects. This demo looks like the classic one where the stroke moves to the inside only, filling the shapes.

It was only in the last few years that browsers like Chrome GPU accelerated SVG animations, making stuff like this really smooth.


SVG viewBox padding

To be clear, the viewBox in SVG does not actually have padding. But it’s an important thing to think about. Chuan makes the point that if you make a 10✕10 area via the viewBox, then make a<rect> that fills that 10✕10 area, the stroke around it, the stroke will be half cut off. That’s because stroke straddles the edge of shapes in SVG. So you either gotta monkey with the coordinates of the shapes, or you gotta adjust the viewBox to handle it. Chuan’s thinking is: let a processor handle it.

viewBox="0 0 10 10 padding .5"

/* translates to */

viewBox="-.5 -.5 11 11"

Clever thinking, really. The CSS Doodle tool can do it.


So… you can set an SVG circle’s radius in CSS?

The very basic answer to Paul Hebert’s questions is: yeah, totally. Like if you have this:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="50" />
</svg>

You can adjust the radius in CSS like:

circle {
  r: 20;
}

Not CSS you see every day, but yeah, that’s totally fine. But Paul’s point is that normally you set the radius in the SVG code, but you might need it in CSS code. Like, a way to keep them in sync is good. In Paul’s demo, it looks like he doesn’t even set the radius in SVG at all, just does it in CSS via a --radius Custom Property, then uses that in the other calculations needed to make these percentage meters work.


Understanding SVG Paths

The <path> element in SVG is the most complicated of the shape drawing elements. In fact, as I understand it, all the other elements are just syntactic sugar over a path anyway. I once wrote An Illustrated Guide when I was learning it and figuring it out. But Nanda Syahrasyad has outdone me easily in Understanding SVG Paths.

The trick is understanding the commands. They are pretty understandable in the end, as it were. They are like “pick the pen up and move it here, then draw a line over to here” or “starting where you are, move the pen in this direction this far” or “draw a curve from here to there using these other two points as essentially gravitational poles.”

If you get into it, you’ll find yourselves (gasp) drawing your own shapes. I love Nanda’s opener:

I think you’re kind of a next-level front-end developer if you’re building bending ass buttons like that.


SVGs have additional pointer-events properties

If you’re like me, you think of pointer-events in CSS as a thing you use to set none once in a while. Maybe you set some colored overlay <div> over something, but you don’t want it to actually eat up clicks, so you set pointer-events: none on it and those clicks will slide right through.

When it comes to SVG, though, Stefan Judis has noted some additional values for it that are specific to SVG like:

.foo {
  pointer-events: visiblePainted;        
}

The demo by Martijn Cuppens helps. See number 4. Like ONLY the “painted” part is clickable there. I feel like that opens up some weird “click map” possibilities, so please send them to me if you do something weird.