The blog

Writing from the workshop

119 articles on the parts that actually hurt.

section
You built your modal with a `<div>` and a focus trap library. The native `<dialog>` does all of that.
HTML

You built your modal with a <div> and a focus trap library. The native <dialog> does all of that.

The `<dialog>` element ships with focus trapping, Escape-to-close, backdrop rendering, and correct ARIA semantics — no library, no boilerplate. It's been Baseline since 2022.

Aug 8, 2026 · 5 min
Stop importing `uuid`. `crypto.randomUUID()` has been native since 2021.
JavaScript

Stop importing uuid. crypto.randomUUID() has been native since 2021.

The `uuid` package is downloaded hundreds of millions of times a week. Most installs exist to call uuid/v4 — exactly what `crypto.randomUUID()` does natively, with no import, no bundle cost, and guaranteed cryptographic randomness.

Aug 8, 2026 · 3 min
You're installing date-fns for 'X hours ago'. `Intl.RelativeTimeFormat` does it natively.
JavaScript

You're installing date-fns for 'X hours ago'. Intl.RelativeTimeFormat does it natively.

Most apps display relative timestamps — '3 minutes ago', 'last week'. Developers still reach for date-fns or moment for this. The Intl.RelativeTimeFormat API handles it natively, with full locale support and zero dependencies.

Aug 7, 2026 · 4 min
You use `obj.hasOwnProperty(key)` to check property ownership. It can silently fail. `Object.hasOwn()` is the safe replacement.
JavaScript

You use obj.hasOwnProperty(key) to check property ownership. It can silently fail. Object.hasOwn() is the safe replacement.

Two real cases where `obj.hasOwnProperty(key)` throws or returns wrong results — and why `Object.hasOwn(obj, key)` is the ES2022 fix that ESLint's `no-prototype-builtins` rule has been nudging you toward for years.

Aug 6, 2026 · 4 min
Container queries can check more than size — style queries let components read custom property values
CSS

Container queries can check more than size — style queries let components read custom property values

Size queries react to container width. Style queries react to CSS custom property values on a container ancestor — enabling component-level theming and variant switching in pure CSS, no JavaScript involved.

Aug 6, 2026 · 4 min
You're collecting async iterable results with a for-await loop. `Array.fromAsync` does it in one call.
JavaScript

You're collecting async iterable results with a for-await loop. Array.fromAsync does it in one call.

A for-await loop that pushes into an array, or the `await Promise.all([...asyncIterable])` workaround that silently fails — `Array.fromAsync` replaces both with a single awaited call. It's Baseline 2024.

Aug 5, 2026 · 4 min
Your browser renders everything, even what you can't see — `content-visibility: auto` fixes that
CSS

Your browser renders everything, even what you can't see — content-visibility: auto fixes that

Browsers lay out and paint the entire page on load, including the 80% below the fold. `content-visibility: auto` tells the browser to skip that work for off-screen elements — and it's Baseline 2024.

Aug 4, 2026 · 5 min
CORS Explained: The Complete Guide (with Cheat Sheet)
Security

CORS Explained: The Complete Guide (with Cheat Sheet)

A complete guide to CORS: the same-origin policy, preflight requests, and Access-Control-Allow-Origin headers — with worked examples and a cheat sheet.

Aug 3, 2026 · 14 min
Your UI is freezing because you never gave the browser a break
JavaScript

Your UI is freezing because you never gave the browser a break

Long synchronous tasks block the main thread and make your interface unresponsive. `scheduler.yield()` is the native way to hand control back to the browser mid-task so it can paint, handle input, and resume your work exactly where it left off.

Aug 3, 2026 · 5 min
You're writing dark-mode colors twice. `light-dark()` fixes that.
CSS

You're writing dark-mode colors twice. light-dark() fixes that.

Every `@media (prefers-color-scheme: dark)` block duplicates your color definitions. `light-dark()` lets you write both values on the same line, in the same rule, with no separate block and no build step. Baseline 2024.

Aug 2, 2026 · 5 min
You've been wrapping `new URL()` in try/catch. `URL.parse()` does it natively.
JavaScript

You've been wrapping new URL() in try/catch. URL.parse() does it natively.

Validating an untrusted URL before parsing it used to mean a try/catch wrapper or a regex. `URL.canParse()` checks validity without constructing. `URL.parse()` parses and returns null on failure. Both are Baseline 2024 — no wrapper needed.

Aug 1, 2026 · 5 min
CSS has no native scoping. `@scope` changes that.
CSS

CSS has no native scoping. @scope changes that.

BEM, CSS Modules, and scoped component styles all exist because CSS leaks — a rule written for one component can silently affect another. `@scope` gives the cascade a lower boundary so styles stay where you put them, natively, with no build step.

Jul 31, 2026 · 5 min