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?