10 Native Web Features You Can Use In 2026 (You Probably Don't Know Half of Them)

While we were busy configuring Webpack and debating which JavaScript framework to use this year, browsers shipped a lot of new features...

Cristian Tabacitu
Cristian Tabacitu
Share:

While we were busy configuring Webpack and debating which JavaScript framework to use this year, browsers shipped a lot of new features. Quietly. Without much fanfare.

Some of these features replace entire JavaScript libraries. Some replace CSS preprocessors. Some are things we thought were "impossible in CSS" for 20 years. And most developers I talk to... don't know they exist.

Here are 11 native web features you can use today. No npm install. No build step. Just HTML, CSS, and a little bit of JavaScript.


1. Native Modals with <dialog>

Remember installing React Modal? Bootstrap Modal? jQuery UI Dialog?

Now it's just HTML:

<dialog id="my-modal">
  <h2>Hello, I'm a native modal!</h2>
  <p>I have proper focus trapping, a backdrop, and accessibility built in.</p>
  <button onclick="this.closest('dialog').close()">Close</button>
</dialog>

<button onclick="document.getElementById('my-modal').showModal()">Open Modal</button>

That's it. The <dialog> element gives you:

  • A proper backdrop (styleable with ::backdrop)
  • Focus trapping (can't tab out of it)
  • Closes with Escape key
  • Accessibility handled automatically

You'll still want to add some CSS to make it look nice (the default styling is pretty bare), but the behavior is all there for free.

Browser support: All browsers since 2022.


2. Native Popovers (No JavaScript Required!)

Tooltips, dropdowns, menus - we've been using JavaScript libraries for these forever. Now:

<button popovertarget="my-popover">Click me</button>

<div id="my-popover" popover>
  I'm a popover! I'll close when you click outside.
</div>

The Popover API gives you:

  • "Light dismiss" (click outside to close)
  • Proper stacking (always on top)
  • No JavaScript needed for basic popovers

Browser support: All browsers since 2024.


3. CSS Nesting (Native!)

The #1 reason people used Sass? Nesting. It's now native CSS:

.card {
  background: white;
  padding: 1rem;

  &:hover {
    background: #f5f5f5;
  }

  .title {
    font-size: 1.5rem;
    color: #333;
  }

  .body {
    color: #666;
  }
}

This is valid CSS. No preprocessor. Just works.

Browser support: Chrome 120+, Firefox 117+, Safari 17.2+ (all shipped in 2023).


4. CSS Variables (Custom Properties)

Another Sass killer. Dynamic variables that can even be changed with JavaScript:

:root {
  --primary-color: #3490dc;
  --spacing: 1rem;
  --border-radius: 8px;
}

.button {
  background: var(--primary-color);
  padding: var(--spacing);
  border-radius: var(--border-radius);
}

.button-danger {
  --primary-color: #e3342f; /* Override locally */
}

And you can manipulate them with JS:

document.documentElement.style.setProperty('--primary-color', '#ff6b6b');

Boom. Theme switching without a framework.

Browser support: All browsers since 2017 (!).


5. The :has() Selector (The "Parent Selector")

For 20+ years, CSS couldn't select a parent based on its children. "Impossible," we said. "Use JavaScript."

Now:

/* Style a form differently if it has invalid inputs */
form:has(:invalid) {
  border: 2px solid red;
}

/* Style a card differently if it has an image */
.card:has(img) {
  padding: 0;
}

/* Style a label if its checkbox is checked */
label:has(input:checked) {
  font-weight: bold;
}

This changes everything about what's possible in pure CSS.

Browser support: All browsers since late 2023.


6. Container Queries

Media queries are based on the viewport. But what if you want styles based on a component's container?

.card-container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

@container (max-width: 399px) {
  .card {
    display: block;
  }
}

Now your card component adapts based on where it's placed, not the screen size. Sidebar? Compact layout. Main content? Full layout. The component doesn't need to know where it is.

Browser support: All browsers since 2023.


7. Native Lazy Loading

We used to need JavaScript libraries (or Webpack plugins) for lazy loading images:

<img src="big-image.jpg" loading="lazy" alt="...">
<iframe src="video-embed.html" loading="lazy"></iframe>

One attribute. That's it. The browser handles everything.

Browser support: All browsers since 2020.


8. View Transitions API

SPA-like page transitions... without an SPA:

@view-transition {
  navigation: auto;
}

Add that CSS, and your multi-page app gets smooth transitions between pages. Automatically. The browser figures out what changed and animates it.

For more control:

.hero-image {
  view-transition-name: hero;
}

Now your hero image morphs smoothly from one page to the next.

Browser support: Chrome/Edge since 2023, Safari and Firefox in progress. (It's progressive enhancement - in unsupported browsers, navigation just works normally without the animation. No harm done.)


9. Import Maps

I wrote about this in another article, but it's so important I'll repeat it here. You can map bare module imports to URLs without a bundler:

<script type="importmap">
{
  "imports": {
    "lodash": "https://esm.sh/[email protected]",
    "confetti": "https://esm.sh/[email protected]"
  }
}
</script>

<script type="module">
  import confetti from 'confetti';
  confetti(); // 🎉
</script>

Clean imports. No bundler. No npm (for browser code).

Browser support: All browsers since 2023.


10. <details> and <summary> (Native Accordions)

Accordions/collapsibles without JavaScript:

<details>
  <summary>Click to expand</summary>
  <p>Here's the hidden content that shows when you click!</p>
</details>

Fully styleable. Accessible by default. Animatable with CSS.

Browser support: All browsers since... 2011! (We just forgot about it.)


11. fetchpriority Attribute

Fine-grained control over which resources the browser should prioritize:

<!-- Load this image first, it's above the fold -->
<img src="hero.jpg" fetchpriority="high" alt="...">

<!-- This can wait, it's below the fold -->
<img src="footer-image.jpg" fetchpriority="low" loading="lazy" alt="...">

<!-- Analytics can definitely wait -->
<script src="analytics.js" fetchpriority="low"></script>

Browser support: All browsers since 2023.


Bonus: What About Safari?

I know, I know. "But Safari doesn't support it!"

Here's the thing: Safari has gotten a lot better. Most of these features have full Safari support. Apple has been shipping major CSS and HTML features consistently.

Check caniuse.com for the specific feature you need, but don't assume Safari is the blocker anymore. Times have changed.


The Bigger Picture

All these features have something in common: they reduce the need for JavaScript libraries and build tools.

  • Need modals? No library needed.
  • Need popovers? No library needed.
  • Need CSS nesting? No preprocessor needed.
  • Need lazy loading? No library needed.
  • Need page transitions? No SPA framework needed.
  • Need package management for browser JS? Import maps.

The web platform is catching up to (and in some cases surpassing) the abstractions we built on top of it. The "modern" toolchain was solving problems that the browser now solves natively.

Does this mean you should throw away all your tools tomorrow? No. But it does mean you should know what's available before reaching for a dependency.

Sometimes the browser is enough.

Cheers! 🍻


Further reading:

Want to receive more articles like this?

Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.

Reactions & Comments

What do you think about this?

Latest Articles

Wondering what our community has been up to?