The HTML Features Nobody Uses (But Should)
Everyone loves talking about the latest JavaScript framework or the newest CSS trick. Meanwhile, HTML — the tag soup we all pretend to know cold — has quietly been shipping genuinely useful features for years, and most developers have no idea they exist. Half the internet is still reaching for a JavaScript library to do things the browser can now do on its own.
Here's a tour of the HTML features that are sitting right there, free, unused, gathering dust.
1. <dialog> — A Real, Native Modal
For years, "build a modal" meant a <div>,
a pile of CSS for positioning and overlay, some JavaScript for focus trapping, and an ARIA attribute
checklist. The <dialog>
element does most of that for you, natively:
<dialog id="myDialog">
<p>Hello from a native modal!</p>
<button onclick="this.closest('dialog').close()">Close</button>
</dialog>
<button onclick="document.getElementById('myDialog').showModal()">
Open Dialog
</button>
Call .showModal() and
you get a centered, backdrop-covered modal with built-in focus trapping and Escape-to-close — no
JavaScript library, no ARIA gymnastics. There's even a
::backdrop
pseudo-element you can style directly.
2. The Popover API — Tooltips and Menus Without the JS
Chances are you've built (or copy-pasted) a dropdown menu or tooltip component that manages its own open/close state, click-outside detection, and z-index stacking. The Popover API does all of that natively, with a single attribute:
<button popovertarget="myPopover">Open</button>
<div id="myPopover" popover>I'm a popover, no JS required.</div>
Click outside, and it closes automatically. Press Escape, and it closes. It's the kind of feature that quietly makes an entire category of npm packages unnecessary.
3. loading="lazy" — Free Image Performance
You've probably installed a whole library for lazy-loading images at some point. Modern browsers do it with one attribute:
<img src="huge-photo.jpg" loading="lazy" alt="A huge photo">
Images outside the viewport won't load until the user scrolls near them. No IntersectionObserver boilerplate, no dependency, no bundle size cost.
4. <search> — A Landmark Element for Search
New enough that plenty of developers haven't even heard of it:
<search> is a
semantic wrapper specifically for search and filtering forms:
<search>
<form>
<input type="search" name="q" placeholder="Search…">
<button type="submit">Go</button>
</form>
</search>
It gives assistive technology a proper landmark for search functionality — something that used to
require a manual role="search"
attribute, if anyone remembered to add it at all.
5. inert — Disable a Whole Section, Instantly
Ever built a modal and had to carefully make sure background content wasn't still focusable or
clickable behind it? The inert
attribute solves that in one word:
<div id="background" inert>
<!-- Nothing in here is focusable, clickable, or reachable by screen readers -->
</div>
It's the accessibility fix that used to require a small essay of JavaScript, now a single HTML attribute.
6. <details> and <summary> — Accordions for Free
Want a collapsible section? You don't need a JavaScript accordion component:
<details>
<summary>Click to expand</summary>
<p>Here's the hidden content, revealed with zero JavaScript.</p>
</details>
It's keyboard accessible, screen-reader friendly, and works out of the box. Pair multiple
<details>
elements with the name
attribute to make them behave like an exclusive accordion (only one open at a time) — also with no
JavaScript.
7. View Transitions — Smooth Page Animations, Natively
The View Transitions API lets you animate between DOM states — including full page navigations — without hand-rolling a transition library:
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.4s;
}
document.startViewTransition(() => {
updateTheDOM();
});
The browser automatically crossfades (or animates however you configure it) between the old and new states. It's the kind of polish that used to require a dedicated animation library, now built into the platform.
8. enterkeyhint and inputmode — Better Mobile Keyboards for Free
Two attributes, zero JavaScript, dramatically better mobile UX:
<input type="text" inputmode="numeric" enterkeyhint="search">
inputmode tells
mobile browsers which keyboard layout to show (numeric, email, tel, and so on), and
enterkeyhint
customizes what the Enter key says and does ("Search," "Go," "Send"). Small, but the kind of detail
that makes a form feel genuinely native.
9. <template> — Inert HTML You Can Clone
<template>
holds markup that's parsed but never rendered, ready to be cloned into the DOM via JavaScript:
<template id="rowTemplate">
<tr><td class="name"></td><td class="value"></td></tr>
</template>
It's a clean, framework-free way to define reusable HTML fragments, and it predates most of the component-based frameworks that eventually made the same idea popular.
10. srcset and <picture> — Responsive Images Done Right
Not brand new, but still wildly underused: instead of shipping one giant image to every device, you can let the browser choose:
<picture>
<source srcset="photo-large.avif" media="(min-width: 800px)">
<source srcset="photo-small.avif" media="(max-width: 799px)">
<img src="photo-fallback.jpg" alt="A photo">
</picture>
The browser picks the right image for the screen size and format support automatically — real performance gains, entirely in markup.
Why These Go Unused
Mostly inertia. A lot of developers learned "how to build a modal" or "how to build an accordion"
back when the only option was JavaScript, and that habit never got revisited once the platform
caught up. Framework culture doesn't help either — when your component library already has a
<Modal> or
<Tooltip>,
there's rarely a reason to go check whether the browser grew a native equivalent while you weren't
looking.
The Bottom Line
The browser has quietly been absorbing a huge amount of what used to require a JavaScript library — modals, popovers, lazy loading, accordions, focus management, page transitions. None of it needs a build step, a dependency, or a bundle size hit. It's just sitting there in the spec, free, waiting for someone to actually read the MDN page. Next time you reach for a library to solve a UI problem, it's worth a quick check: does HTML already do this now?