Accessibility
Meeting WCAG is an achievement
Reaching WCAG is something to celebrate. It is so difficult to have accessibility wins, and it makes the whole process so draining. Clients feel like they cannot do anything correct enough which leads to frustration and burn out. Especially for those who are invested in making accessibility a reality.
WCAG is deliberately achievable, and everyone who works in accessibility will say “easily achievable”, but in reality, the obstacles are not technical but human or organizational or political. And reaching WCAG compliance despite those headwinds is an achievement.
Too Many Cooks Spoil Accessibility — Unless You Map The Cooks
Imagine building a website and saying “Accessibility? Oh, devs will do that later.” The problem is, when “later” rolls around, everyone’s pointing at everyone else. The designers say “I didn’t know alt text was your job,” content folks say “I thought you’d structure the headings,” and developers say “I have too many other tickets.” Result: accessibility becomes the leftover side dish nobody wants to eat.
Enter ARRM — Accessibility Roles and Responsibilities Mapping — a draft W3C / WAI resource designed to ensure accessibility isn’t an accidental afterthought.
CSS
Introducing CSS Grid Lanes
It’s here, the future of masonry layouts on the web. After the groundwork laid by Mozilla, years of effort by Apple’s WebKit team, and many rounds debate at the CSS Working Group with all the browsers, it’s now clear how it works.
Inverted Border Radius CSS Generator
Instantly design unique inverted corners using SVG. Preview live, adjust easily, and copy clean CSS for any project.
You can choose which corners to be inverted along with other properties, after finishing you can export your shape as CSS mask, clip-path or SVG.
Stylish dialogs
Campsite has some of my favorite UI styling on the web. Naturally, I cracked open their source hoping to learn something. What I found: React components rendering <div>s inside <div>s, with piles of JavaScript doing what <dialog> does for free.
So I borrowed their visual design and rebuilt it with semantic HTML and CSS using affordance classes. I want to walk you through all of the choices I’ve made and how it all comes together.
text-decoration-inset is Like Padding for Text Decorations
The text-decoration-inset property solves a problem that we’ve had since the beginning of the web, which is that text decorations such as underlines extend beyond the first and last characters, resulting in vertical misalignment.
HTML
Semantics beyond the tag name
There is a terrible epidemic that plagues the web: divitis.
To avoid divitis, authors are often encouraged to use semantic HTML. As it turns out, HTML has over a hundred elements that are not named div or span. Semantic HTML elements describe what their content is.
You can make up HTML tags
Instead of writing HTML like this:
<div class=cool-thing>
Hello, World!
</div>`
You can write HTML like this:
<cool-thing>
Hello, World!
</cool-thing>`
And CSS like this:
cool-thing {
display: block;
font-weight: bold;
text-align: center;
color: #ff0;
}
Browsers handle unrecognized tags by treating them as a generic element, with no effect beyond what’s specified in the CSS. This isn’t just a weird quirk, but is standardized behavior. If you include hyphens in the name, you can guarantee that your tag won’t appear in any future versions of HTML.
I've used this in the past to implement <yes-script>, the opposite of <noscript>, to be able to designate parts of a UI to be hidden if JS was disabled (a "copy to clipboard" button that only works with JS). You can of course do the same thing with classes, but custom tags are fun.
While this is neat to know about, It's definitely possible to take it too far. When a lot of tags in your HTML are custom elements, it creates new readability problems. You can't immediately guess what's inline, what's block, etc. And it's just a lot of overhead for new people to learn.
JavaScript
How To Dynamically Install Custom Elements
Today, I want to look into one very specific topic in excruciating technical detail: how to dynamically load custom elements. This is a pattern I’ve been playing with for a while and was partially inspired by David Bushell’s Anatomy Of A Web Component article, so maybe read that first.
What you will need:
- A file system
- A browser
- Some custom elements. The term Web Components isn’t relevant here. Shadow DOM is not a necessary component of what I’m doing. Also, people inexplicably seem to hear “component” and go straight to “React”.
The Inverted Reactivity Model of React
Compared to almost every other FE framework, including Vanilla JS, React has an "inverted" model of reactivity.
In React, the component function is the unit of reactivity whereas in Vue and Vanilla JS, the callback function is typically the unit of reactivity.
Understanding this difference is important regardless of which direction you're headed (React to Vue or vice versa).
For React developers heading into Vue, this can often reduce the mental burden when writing complex components by reducing the need to explicitly think about code placement, avoiding excess allocations (explicit memoization), and unintended side effects.
Velox Framework - Zero VDOM. Fine-Grained Reactivity. Instant Performance.
Velox is a next-generation web framework designed for ultimate performance and developer experience. Unlike traditional frameworks that rely on heavy Virtual DOM diffing, Velox compiles your declarative JSX directly into surgical DOM operations. The result is an application with O(1) updates and a runtime that is barely there.
Key Features
- Zero Virtual DOM — We don't diff trees. We update nodes directly using fine-grained reactivity.
- Surgical Precision — Only the specific text node or attribute that changed is updated.
- Tiny Footprint — The entire runtime is < 3kb (min+gzip).
- Modern Tooling — Built on Vite for instant Hot Module Replacement (HMR).
- Simple API — If you know React hooks, you know Velox signals (
createSignal,createEffect). - Universal Compatibility — Works seamlessly with existing JS/TS ecosystems.
URL Pattern API
The URL Pattern API defines a syntax that is used to create URL pattern matchers. These patterns can be matched against URLs or individual URL components.
Since September 2025, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
My HTML Web Component boilerplate for 2026
I created web component boilerplate years ago. Since then, my approach to writing web component has changed quite a bit.
I just updated the boilerplate, adding everything I’ve learned from working on Kelp UI. Today, I wanted to explain how it works.
Dialog view transitions
In a recent project I was wondering if I can combine two of my favourite modern web features: view transitions and the <dialog> element. Turns out it’s possible and not too complicated.
Explore DOM Events
Want to understand how events really work in the browser? Curious about event bubbling and capturing? Dive into domevents.dev — an interactive way to learn the ins and outs of DOM events.
Using NgRx Signal Store for State Management in Angular
NgRx Signal Store is a lightweight and reactive approach to managing state in Angular applications. It integrates seamlessly with Angular’s signal-based reactivity model and removes the need for traditional boilerplate around reducers, selectors, and effects.
Cereb - User input handling and orchestration library, from low-level events to high-level gestures
Create streams from various input sources, transform and compose streams with operators like filter, map, merge, throttle, debounce, and more.
The Problems Cereb Solves:
- Spaghetti Event Code — Scattered handlers, shared mutable state, duplicated logic
- Lightweight Bundle — ~77% smaller than Hammer.js (1.73 KB gzipped for pan gesture)
- Resource Efficiency — Event listener reuse, single-responsibility operators
FracturedJson - JSON formatter that produces highly readable but fairly compact output
FracturedJson is a family of utilities that format JSON data in a way that's easy for humans to read, but fairly compact. Arrays and objects are written on single lines, as long as they're neither too long nor too complex. When several such lines are similar in structure, they're written with fields aligned like a table. Long arrays are written with multiple items per line across multiple lines.
It is available as a browser page, a .NET Standard 2.0 library, a JavaScript package, and a Visual Studio Code extension.
Miscellaneous
CSRF Protection without Tokens or Hidden Form Fields
A simpler modern technique based on the browser’s built-in Sec-Fetch-Site request header, which modern browsers automatically send. By rejecting requests with this header set to cross-site, a server can protect against CSRF attacks without requiring tokens or hidden form fields. The author also discusses handling subdomains and fallback to the Origin header for older browsers, and notes that this modern approach has recently begun to be recognized by OWASP as a defense method.
Chrome DevTools for Debugging Web Performance
This is a step-by-step guide on how I use Chrome DevTools to detect Web Performance issues on a website, as well as validate hypotheses to fix some of the problems found.