Five years ago, “the web platform” meant a <div> and a fetch. In 2026 it means a graphics-capable, GPU-programmable, file-system-aware, multi-process runtime with a richer component library than most operating systems shipped in 2015. The features below have all reached the “use it in production without a polyfill” point — and they change what a web app can be.
View Transitions API
The single biggest UX win of the last few years. View Transitions let you animate between DOM states with one function call, and the browser handles the interpolation for you.
// Before: instant, jarring
document.body.innerHTML = newHTML;
// After: smooth crossfade
document.startViewTransition(() => {
document.body.innerHTML = newHTML;
});
That’s it. The browser snapshots the old state, applies the new state, and crossfades. With a few lines of CSS you can animate individual elements (the shared element transition):
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
}
::view-transition-old(.card),
::view-transition-new(.card) {
animation-duration: 0.4s;
}
It works for SPAs (route changes), MPAs (full page loads, with a meta tag and same-origin navigation), and Vue/React/Svelte router transitions. Browser support hit cross-browser stable in 2024 and is now the recommended way to handle page transitions in a new app. The last time I wrote a hand-coded FLIP animation by hand, the View Transitions spec was a draft.
Popover API
The popover, dialog, and <select> elements have always been a mess of focus traps, escape-key handling, light-dismiss behavior, and ARIA. The Popover API standardizes all of it.
<button popovertarget="menu">Open menu</button>
<ul id="menu" popover>
<li>Cut</li>
<li>Copy</li>
<li>Paste</li>
</ul>
That’s a fully accessible, top-layer, light-dismissing, escape-key-closing popover menu. No JavaScript. No z-index wars. The popover attribute puts the element in the browser’s top layer (above all other content, including modal dialogs from other components), and the browser handles focus, escape, and click-outside behavior automatically.
Three modes:
popover(auto) — light dismiss, multiple popovers can be open.popover="manual"— programmatic open/close only, no light dismiss.<dialog>— modal, with backdrop, traps focus, requires explicit close.
For dropdowns, tooltips, action menus, and pickers: popover. For modal dialogs that block interaction: <dialog>. Stop building dropdowns with position: absolute and a click-outside listener — that’s the 2019 pattern.
WebGPU compute shaders
WebGPU has been “almost ready” since 2023, but the compute shader story only matured in 2025. You can now run arbitrary GPU compute on the browser, on every modern OS, with a sane API.
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const shader = device.createShaderModule({ code: computeWGSL });
const pipeline = await device.createComputePipeline({ layout: 'auto', compute: { module: shader, entryPoint: 'main' } });
// ... bind buffers, dispatch, read results
What you can do with it:
- Dev tools. A regex tester that runs millions of matches on the GPU. A JSON formatter that parses a 500MB file in 200ms. A diff tool that compares two 100MB files in under a second.
- Local-first apps. Image processing, video transcoding, ML inference — all in the browser, no server.
- Visualisation. Anything that was previously “this would be 60fps if I could get it on the GPU” can now be on the GPU.
WebGPU requires HTTPS in production (the API is gated on a secure context, like crypto.subtle). It also requires a recent browser and a real GPU — fallback to WebGL2 or a JS-only path is still necessary for old hardware.
File System Access API
The File API gives you a snapshot of a file the user dragged in. The File System Access API gives you a live handle you can read from and write back to.
const handle = await window.showSaveFilePicker({
suggestedName: 'config.json',
types: [{ description: 'JSON', accept: { 'application/json': ['.json'] } }],
});
const writable = await handle.createWritable();
await writable.write(JSON.stringify(data, null, 2));
await writable.close();
You can also re-open a file, get a FileSystemFileHandle, and keep using it across sessions with IndexedDB (the handle is serialisable). For dev tools, this is the difference between “download a file after every change” and “edit in place”.
Browser support: Chrome and Edge since 2023, Safari and Firefox as of 2025. For unsupported browsers, fall back to Blob and <a download> — the feature detects cleanly.
CSS subgrid
display: grid was the single biggest layout improvement in a decade. subgrid is the second-biggest. It lets a grid item participate in its parent’s grid:
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3;
}
Now every card has a header, body, and footer of identical height, without a flexbox hack or a magic number. Subgrid landed in all three engines in 2023-2024 and is safe to use without a fallback.
The practical takeaway
If you started web development in the last few years, you may not have noticed how much the platform has changed. The “use a library for everything” reflex — animations, dropdowns, file pickers, modals, even layout — is increasingly obsolete. Native is faster, smaller, more accessible, and less likely to break in a framework upgrade.
The next time you’re about to npm install a 50KB package for a problem the browser can solve in 20 lines of HTML, check the platform first. The answer is increasingly “yes, the browser does that”.
A fast way to test: every dev tool on DevSpeedTools runs entirely client-side using the same platform features (Web Crypto, File System Access, the Popover API, CSS subgrid). If you can build a JSON formatter with zero npm dependencies, you can build most things.