Accessibility
Where can aria-label and aria-labelledby be used for naming elements?
aria-label and aria-labelledby are ARIA attributes that allow authors to provide an accessible name to elements.
aria-labelsupplies the name as a text string directly in the attribute.aria-labelledbyreferences another element whose content is used as the accessible name.
Which elements can they be applied to?
aria-labelandaria-labelledbyare intended for elements whose roles support author-provided accessible names.- Those roles can be either implicit (native to the HTML element) or explicit (assigned via ARIA).
This is a lot to unpack, so let's break it down into smaller parts.
Your Grid Lanes will likely fail WCAG 2.4.3
I saw a great introduction to CSS Grid Lanes, aka Masonry Layouts, by Patrick Brosset at CSS Day 2026. I liked the versatility of its use cases, but I was also concerned that it's inaccessible by default.
Can Your AI Pass the Accessibility Test?
Last week at Microsoft Build, Jessie Lorenz, Carie Fisher, and I gave a short talk on a question every AI-enabled product team should be asking: can your AI pass the accessibility test?
The core point was straightforward: AI does not fix a broken process; it accelerates whatever process you already have. If accessibility is already in the workflow, AI can help scale inclusion. If it’s not, AI will scale the same barriers teams are already shipping.
"Out of the box, most coding agents are pretty terrible when it comes to accessibility. That’s not surprising though. As Jessie said, they’re trained on what we created, and the web we created has not been all that accessible, so they learned from us."
"Left to their own devices, most of the code they write only passes about 8–25% of automatable accessibility checks."
CSS
In-N-Out Animations: View Transitions (Part 3/3)
Effective View Transition animations come from designing explicit “in”, “open”, and “out” states and then using the View Transition API’s pseudo-elements to animate between them in a controlled way.
A workaround for hiding empty slots in Chromium
Solving the :host(:has([slot])) problem with @scope.
Named slots are one of web components’ biggest superpowers. Imagine a Button component with an optional icon; in Web Components we don’t need a separate Button and IconButton, a single Button component with <slot name="icon"> will do. Or a card component with a handful of predefined slots for image, title, description, price, metadata, etc. Not 100 different cards… one card.
Slots are a wonderful way to declaratively compose UI, but one shadow styling challenge that has vexed my team over the years is how to contextually hide a <slot> when there’s no slotted content.
Wiggly/Wavy Input Range Slider
Say goodbye to the boring straight range slider and say hello to the fancy wiggly range slider.
A fancy demo powered by border-shape, Scroll-Driven Animations, @property, and more.
The HTML code is nothing but the native <input> element. No extra element and, of course, no JavaScript.
Modern CSS theming with light-dark(), contrast-color(), and style queries
The combination of light-dark(), @container style(), and contrast-color() creates a theming system that’s declarative, composable, and takes advantage of different levels of color theming. It respects user preferences (via color scheme) for macro theme, and lets you build dynamic micro themes. You can take this even further by building out an entire brand system using modern CSS color functions.
Experimenting with random() in CSS
CSS is getting a random() function that lets you set properties with a random value, letting you make interesting and creative new designs.
Improving card patterns with anchor positioning
Accessible and elegant solutions for the clickable surfaces of cards can be a bit tricky to achieve, especially when secondary actions require dead space. I believe that anchor positioning can help, and this post is an attempt to document a useful variation of existing patterns.
Let’s Play With Gap Decorations
Let’s take a look at a quite new CSS feature: Gap Decorations. As its name suggests, it allows us to decorate gaps across different layout types (e.g., flexbox, grid, and multi-column). With a few lines of code, you can easily add decorative lines between elements.
font-family recommendations
Argues that most CSS font stacks are unnecessarily complex. Instead of long lists of specific fonts, use generic families like serif, sans-serif, and monospace, always include an appropriate generic fallback, and trust modern browser/platform defaults. The main goal is better reliability, simplicity, and performance.
HTML
Lost, forgotten, and unfamiliar HTML
Automated scans taught me about some web stuff I forgot or never even know.
JavaScript
The problem with useEffect
Almost every useEffect bug is the same bug in disguise: the effect runs more often than you think. Here's why it loops, and how to stop it.
annotate.js — Turn any website into a collaborative review board
One <script> tag turns your live page into a review surface. Highlight, draw, pin and comment — anchored to the real content, saved in the browser, shared as a single JSON file.
Bulletproof React: Building React Apps That Survive Growth
A deep dive into Bulletproof React, the popular GitHub architecture guide that helps teams organize React applications. Learn how Bulletproof React uses feature-based architecture, public APIs, TanStack Query, Zustand.
react-parallax
A performant, accessible React parallax component with scroll and pointer-based motion.
GitHub repo here.
window.showDirectoryPicker opens up a whole new world
Chrome introduced a new API, window.showDirectoryPicker() that allows the user to grant access to a directory on their computer and allow a website to read/write everything inside.
TanStack Start: A Mental Model for Next.js Developers
Understand TanStack Start from a Next.js developer’s perspective: its router-first architecture, explicit server boundaries, typed routing, caching, rendering, and server functions.
MotionScript — Open Source Motion Design Tool
Create stunning motion graphics with code. An open-source After Effects alternative powered by the web.
Motion Script lets you describe animations as TypeScript/JSX scenes and render them in real time in the browser. You write declarative scene code; the engine turns it into frames using a Skia (CanvasKit) rendering backend, and the bundled player gives you a timeline-based editor to preview, scrub, and export.
kamod-hooks - a lightweight collection of typed, tree-shakeable hooks built specifically for Preact
Production-ready hooks for Preact — fast to adopt, easy to tree-shake, and built with zero runtime dependencies beyond preact itself.
kamod-hooks is a Preact-first hook library inspired by ahooks. It brings together state, lifecycle, browser, async, and utility hooks in a single TypeScript-friendly package, backed by a live docs site with interactive demos and visible source code.
Wely — Lightweight Web Component Framework
Lightweight Web Component framework — one defineComponent(), no class syntax, no framework lock-in.
Lit powers rendering internally but is never exposed. Developers interact exclusively through the Wely API. Output is native custom elements — fully portable, they run in plain HTML, React, Vue, Angular, Svelte, anywhere.
How to Resolve Promises Sequentially in JavaScript
Sequential promise resolution comes down to one loop and one habit: pass functions, not already-running promises, so the work waits its turn. And don't forget to add a try/catch when a single failure shouldn't end the batch, and graduate to for await...of when the data itself arrives asynchronously.