JavaScript for Impatient Programmers (ES2022 edition)

A book on JavaScript by Axel Rauschmayer.

This book makes JavaScript less challenging to learn for newcomers, by offering a modern view that is as consistent as possible.

Covers all essential features of JavaScript, up to and including ES2022. You can read the entire contents online, or order PDF/EPUB/MOBI versions for $34

JavaScript for Impatient Programmers →

Lights at Sea — A map of Lighthouses

This map shows all the blinking beacons from OpenStreetMap. More specifically, it asks the Overpass API for all elements with an seamark:light:sequence attribute, decodes these, and displays them as coloured circles on the map using Leaflet. It also tries to take the seamark:light:range and seamark:light:colour into account.

The cool part is that the size and colors of the dots are accurate, as are the blinking patterns.

LighthouseMap →

Two posts on Semantics

I recently enjoyed reading Hidde de Vries‘s post (that was a talk) on Semantics:

One of the web’s killer features is that it comes with a language for shared semantics. When used right, HTML helps us build websites and apps that work for a broad range of users. Let’s look at what semantics are and how to get them right.

In a world where bootcamps are skipping out on the foundations, articles like these are more important than ever.

More to give than just the div: semantics and how to get them right →


As Scott O’Hara notes in his post “Div divisiveness”: it’s OK to use a div in many cases — but not all.

<div>s are meant to represent nothing. They can be made into just about anything… just don’t make them into soup. I think we can at least all agree that’s not what <div>s are for.

To be clear, Scott also notes:

I am not advocating for the use of <div>s when semantic elements would be more appropriate.

Div divisiveness →

Getting Started With CSS Cascade Layers

Stephanie Eckles, writing for Smashing Magazine:

Cascade layers introduce the new at-rule of @layer. The intent is to help CSS authors be more intentional about ordering the “layers” of CSS rules as a new method of cascade management.

Getting Started With CSS Cascade Layers →

How I Got Pwned by My Cloud Costs

The author of the Have I Been Pwnd website got a nasty surprise: an AU $5,000 bill from Azure (that eventually racked up to $11,000). The culprit: a sudden spike of outgoing bandwidth due to a file no longer being cached properly.

I guess I’m looking at this a bit like the last time I lost data due to a hard disk failure. I always knew there was a risk but until it actually happened, I didn’t take the necessary steps to protect against that risk doing actual damage. But hey, it could have been so much worse; that number could have been 10x higher and I wouldn’t have known any earlier.

Let this be a reminder to set up data and billing alerts for your cloud services.

How I Got Pwned by My Cloud Costs →

Nixery — Ad-Hoc Container Images

Nixery is a Docker-compatible container registry that is capable of transparently building and serving container images using Nix. Images are built on-demand based on the image name.

For example:

docker pull

The command above will give you an image with an interactive Shell, that also has git and htop installed. Keep adding more path segments to the URL, to have more packages pre-installed.

Nixery →

Comparing CSS Specificity Values

In CSS, Specificity is expressed as a triad/triple (A,B,C). An example value would be (1,1,2). To compare specificity — i.e. to see which value has a higher specificity — you need to compare each component of the triple until you find a difference:

function compareSpecificity(x, y) { // x and y being arrays such as [1, 1, 2] that represent a specificity triple
  // Compare A-component
  if(x[0] !== y[0]) {
    return y[0] - x[0];

  // Compare B-component
  if(x[1] !== y[1]) {
    return y[1] - x[1];

  // Compare C-component
  if(x[2] !== y[2]) {
    return y[2] - x[2];

  // Equal!
  return 0;

To more easily sort Specificity triads, Kilian looked for something else:

The goal is to end up with a single number for each specificity that we can then compare and sort with.

Now, it’s not as simple as adding up each component of the triad, because a B-value of 10 does not beat an A-value of 1. Instead, you’ll need to pad the numbers.

Comparing CSS Specificity Values →

💡 This is the exact same approach PHP does internally for its PHP_VERSION_ID constant. PHP 5.2.7 for example, gets a value of 50207.

CSS Cascade Layers in 5 Minutes

In this video, Una digs into Cascade Layers:

Quick show and tell on CSS cascade layers and the @layer property, coming to browsers in Chromium 99+ and Firefox 97+, plus they’re in the current Safari Tech Preview.

The demo can be found on CodePen:

Awaiting her post on the subject, you can check out my Cascade Layers deep dive right here.


The Future of CSS: Detect at-rule support with @supports at-rule(@keyword)

In CSS you can do feature detection using @supports. With it you can detect support for property-value pairs and selectors. What currently isn’t possible though, is to detect support for certain at-rules (such as @layer, @scroll-timeline, etc.)

Hot off the press is a new CSS Working Group decision that defines the at-rule function — to be combined with @supports — which will allow just that.


The problem

While working on my articles and demos that use @scroll-timeline, I ran into an issue: how do I feature detect support for this at-rule?

Thankfully I could use a workaround by checking for support of a “telltale” property: animation-timeline: Browsers that have implemented @scroll-timeline, also have implemented the animation-timeline property. By checking for animation-timeline‘s existence, we can feature detect support for @scroll-timeline.

@supports (animation-timeline: works) {
  /* @scroll-timeline compatible code here */ 

But detecting a telltale property isn’t always 100% accurate or possible. Take the wonderful @layer for example: that one doesn’t come with a telltale property. How do we detect support for it?


The solution

To solve this, the CSS Working Group just decided to introduce a new function that be used in conjunction with @supports: at-rule().

With it, we can feature detect at-rule support as follows:

@supports at-rule(@foo) {
  /* @foo is supported */

It’s also possible to detect support for certain descriptors. For @scroll-timeline this will come in handy, as the descriptors changed over time.

@supports at-rule(@foo; desc: val) {
  /* @foo is supported. The descriptor `desc` with value `val` parses as part of that at-rule. */

Winging back to detect support for @layer, the CSS would look like this:

@supports at-rule(@layer) {
  /* @layer is supported */


The solution, bis

Apart from the syntax above, there’s a follow-up issue that will allow you to pass in a full at-rule into at-rule():

@supports at-rule(@foo bar {baz: qux}) {
  /* The entire at-rule with all its descriptors is supported. Unknown descriptors are ignored. */

Note that in this form you’ll have to pass in a valid — thus, complete — at-rule.


Browser Support

This is hot off the press. Currently, no browser supports this. I’ve filed issues at all browser engines to add support for this:


To help spread the contents of this post, feel free to retweet the announcement tweet:


🔥 Like what you see? Want to stay in the loop? Here's how:

Test your CSS Selector Skills with CSS Speedrun

Now that’s a fun little quiz by Vincent Will:

A small fun app to test your CSS knowledge. Find the correct CSS selectors for the 10 puzzles as fast as possible.

Finished my in 04:38:7. Level 8 tripped me up though: didn’t immediately see the pattern and lost more than 2 minutes on it 😅.

The source is available on GitHub, so you can create your own quizzes, by editing the contents of the src/js/puzzles folder.

And no worries if you score “bad” on this — See it as a learning opportunity to brush up your CSS selectors knowledge.

CSS Speedrun →
CSS Speedrun Source (GitHub) →