Accessibility
role=presentation is no alternative for aria-hidden=true
This post is part of a series called #WebAccessibilityFails, where I collect common issues I find in accessibility audits so that you can avoid them in the future.
In the previous post, I explained how to hide presentational SVGs using aria-hidden="true".
That's a reliable technique, but sometimes I see developers use role="presentation" instead, which may or may not work as expected.
Before I show you where it fails, let's first try to understand the difference between role="presentation" and aria-hidden="true".
Did you know some ARIA roles remove child semantics?
Sometimes ARIA roles seem to wipe child semantics, and at other times they do not.
This difference isn’t arbitrary. It depends on whether the ARIA role introduces a new widget model or aligns with an existing native one.
Once you recognise this distinction, a lot of previously confusing ARIA behaviour starts to make sense.
Understanding which ARIA roles replace structure, and which merely reinforce it, is important. Especially when building non-native widgets.
A guide to accessible focus indicators
Have you ever lost your mouse cursor on your screen? This is what it is like when keyboard users don’t have focus indicators. It’s like navigating with an invisible cursor. This means focus indicators aren’t just a “feature” but a necessity for those who navigate the internet with keyboards.
The WebAIM Million - The 2026 report on the accessibility of the top 1,000,000 home pages
For the eighth consecutive year, WebAIM conducted an accessibility evaluation of the home pages for the top 1,000,000 web sites. The evaluation was conducted using the WAVE stand-alone API (with additional tools to collect site technology and category data). The results provide an overview of and insight into the current state of web accessibility for individuals with disabilities as well as trends over time.
CSS
CSS is DOOMed - Rendering DOOM in 3D with CSS
No, CSS is awesome. CSS is better than ever and it is only getting better. And that is why I built DOOM in CSS. Every wall, floor, barrel, and imp is a , positioned in 3D space using CSS transforms. The game logic runs in JavaScript, but the rendering is entirely CSS. You can play it right now.
CSSSunflower - CSS-only puzzle game (no JavaScript)
Guide sunlight from the sun ☀️ to the sunflower 🌻 by rotating mirrors.
Click a mirror to rotate it 90°. Find the arrangement that sends the beam all the way to the plant.
This is pretty cool, definitely worth a look.
What Is CSS Containment and How Can I Use It?
Continuing my work on web performance for design systems, I want to look at a woefully underused CSS feature called containment. I fear it’s underused because there isn’t much written about it, so this piece aims to be the post I wish I’d been able to read a few years ago. Hopefully it demystifies things a little for you, too.
CSS containment is a way of telling the browser where the boundaries really are. You use it to say "this bit of the DOM is independent of the rest; you can treat it as a self-contained island". In return, the browser is free to skip work outside those islands when things change.
In this post, we’ll take a look at what CSS containment actually is, what each contain value does, and how to use it confidently on real projects without creating hard-to-debug side effects. We’ll also look at my most favourite real-world example of just how effective containment can be.
CSS subgrid is super good
I’m all aboard the CSS subgrid train. Now I’m seeing subgrid everywhere. Seriously, what was I doing before subgrid? I feel like I was bashing rocks together.
HTML
Email obfuscation: What works in 2026?
Here are some of the best techniques for keeping email addresses hidden from spammers—along with the statistics on how likely they are to be broken.
Last updated: January 30, 2026.
JavaScript
heerich.js - a tiny engine for 3D voxel scenes rendered to SVG
heerich.js is a minimalist JavaScript engine that constructs 3D voxel compositions and distills them into pristine SVG. By extruding volumes, carving negative space, and applying boolean operations, you wield a programmatic chisel—projecting complex spatial arrangements into a flat, resolution-independent vector canvas.
Basic Physics Engine in about 100 lines of pure JavaScript
A couple of years ago I wrote a silly physics experiment using the great Matter.js physics engine. Today let's try to create a similar contraption (admittedly simplified), without any external libraries.
Your options for preloading images with JavaScript
I just learned that the task of preloading images with JavaScript is surprisingly quirky. There are actually several ways to do it, and the best one to choose can very much depend on the circumstances. Let's explore them through the lens of what I was trying to accomplish before running into all of this.
Your Debounce Is Lying to You
Debouncing alone does not guarantee correct or safe behavior in async UI scenarios (like search inputs or API calls). Debouncing reduces load, but it doesn’t solve race conditions, you must explicitly handle stale async results.
In this article, we will keep debounce for what it is good at (UI smoothing), then harden the request path with cancellation, retries, and better error handling.
You probably don't need to lift state
This comes up a lot, and it’s easy to get wrong. It’s really easy to default to “lift state up” in React. I’m guilty. But that’s not always the right move.
Quick rule of thumb:
- Keep state as close as possible to where it’s actually used
Lift it when:
- Multiple components need it
- You need to coordinate behavior between components
Why this helps (most of the time):
- Less prop drilling
- Way easier to follow what’s going on
- Fewer accidental re-renders
If you remember one thing:
- If only one component cares, keep the state there.
Signals, the push-pull based algorithm
We have been using Signals in production for years via several modern front-end frameworks like Solid, Vue, and others, but few of us are able to explain how they work internally. I wanted to dig into it, especially diving deep into the push-pull based algorithm, the core mechanism behind their reactivity.
What makes Signals interesting is not just that they update some UI, but how they propagate change through a reactive graph:
- push for eagerly propagating invalidation;
- pull for lazily re-evaluating only when necessary.
This combination gives us a fine-grained reactivity system already adopted by many frameworks like Solid, Vue, Preact, Angular, Svelte, and others. Each comes with its own API surface, but shares the same underlying logic.
Miscellaneous
The Legibility of Serif and Sans Serif Typefaces - Reading from Paper and Reading from Screens (2022)
To sum up 159 pages for you, from page 130:
Nevertheless, the overwhelming thrust of the available evidence is that there is no difference in the legibility of serif typefaces and sans serif typefaces either when reading from paper or when reading from screens. Typographers and software designers should feel able to make full use of both serif typefaces and sans serif typefaces, even if legibility is a key criterion in their choice.
Direct PDF here.
The emerging control plane for AI development
A lot of the talk around AI coding still assumes a pretty simple setup: you open a chat, paste something in, get something back.
That is not where things are going.
What’s starting to show up now is a different kind of system. Not just a coding assistant, and not quite a new IDE either, but something closer to a control plane for the development environment itself: agents running for a while, tools exposed remotely, state that persists, and the ability to check in from a phone, browser, or terminal.
This post is a survey of that space while it is still taking shape. There are many tools that are sprouting up everyday to suit people's personal needs. Here, I am looking at only several of them. Things are moving fast so this post will almost certainly not be relevant past March 2026.