HTML5 elements you didn't know you need

2 days ago 1

As you know, we love unusual tech at Lingo.dev. So when in my last essay, David commented he was surprised to not see "dialog" HTML element, it hit me - wait, but there's so many HTML5 elements that we don't even know about!

In our rush to embrace sophisticated frameworks and libraries, we've overlooked some of the most elegant solutions built right into HTML5. There's something beautiful about achieving with a single tag what might otherwise take dozens of lines of JavaScript.

The best code is often the code you don't have to write. How many times have you reached for a JavaScript library to create a modal window? Or written complex CSS for collapsible sections? What if I told you that HTML5 already has native elements for these exact purposes?

These aren't just any HTML elements - they're the ones that make you go "Wait, we could do that all along?" Let's explore eight surprisingly powerful HTML elements you probably aren't using - but absolutely should be.

1. The <dialog> Element: Native Modal Windows

Picture this: you're starting a new project and need to add a modal dialog. Your first instinct? Reach for React, grab a UI library, or write a bunch of JavaScript. I get it - I've done the same thing countless times.

But HTML5 has a built-in element specifically designed for this purpose:

<dialog id="myDialog"> <h2>This is a Native Dialog</h2> <p>No JavaScript frameworks required!</p> <button id="closeDialog">Close</button> </dialog> <button id="openDialog">Open Dialog</button>

Enter fullscreen mode Exit fullscreen mode

You still need a bit of JavaScript to handle the open/close actions:

const dialog = document.getElementById('myDialog'); document.getElementById('openDialog').addEventListener('click', () => { dialog.showModal(); // Makes the dialog appear as a modal }); document.getElementById('closeDialog').addEventListener('click', () => { dialog.close(); // Closes the dialog });

Enter fullscreen mode Exit fullscreen mode

The browser handles focus management, backdrop rendering, and keyboard accessibility. Most developers I talk to have never used this element, despite it being supported in all major browsers since around 2022.

You can style it however you want:

dialog { padding: 20px; border-radius: 8px; border: 1px solid #ddd; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } dialog::backdrop { background-color: rgba(0,0,0,0.6); }

Enter fullscreen mode Exit fullscreen mode

I've been using this in production for a couple of years now. The main gotcha is iOS Safari support, which was spotty until 2023, but it's solid now. For complex modals with lots of interactive elements, you might still want a dedicated library, but for most use cases, the native element works perfectly.

2. The <details> and <summary> Elements: Native Accordions

Accordions are everywhere on the web - FAQs, product details, settings panels. Most developers reach for a JavaScript solution, but HTML5 has native elements for this:

<details> <summary>Click to expand</summary> <p>This content can be expanded and collapsed without any JavaScript!</p> </details>

Enter fullscreen mode Exit fullscreen mode

That's all you need. The browser handles the toggle functionality, accessibility attributes, and keyboard navigation.

You can style it to match your design system:

details > summary { list-style: none; /* Removes the default triangle */ } details > summary::before { content: '▶'; display: inline-block; margin-right: 0.5em; transition: transform 0.2s; } details[open] > summary::before { transform: rotate(90deg); }

Enter fullscreen mode Exit fullscreen mode

These elements are particularly useful for nested navigation. I used them recently in a documentation site where we needed three levels of collapsible navigation:

<details> <summary>Programming Languages</summary> <details> <summary>Frontend</summary> <ul> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul> </details> <details> <summary>Backend</summary> <ul> <li>Python</li> <li>Java</li> <li>Ruby</li> </ul> </details> </details>

Enter fullscreen mode Exit fullscreen mode

The main limitation is animation - if you need smooth animations when opening/closing, you'll need to add JavaScript. But for many use cases, the default behavior is perfectly fine.

3. The <datalist> Element: Native Autocomplete

Autocomplete functionality is a staple of modern web forms. Most developers reach for a third-party solution, but HTML5 has a built-in element for this:

<input list="browsers" name="browser" placeholder="Choose a browser"> <datalist id="browsers"> <option value="Chrome"> <option value="Firefox"> <option value="Safari"> <option value="Edge"> </datalist>

Enter fullscreen mode Exit fullscreen mode

This gives you a text input that shows suggestions as you type, with the ability to select from the list or enter custom text.

One interesting use case is creating a color picker with named colors:

<input type="text" list="colors" placeholder="Choose a color"> <datalist id="colors"> <option value="#FF0000">Red</option> <option value="#00FF00">Green</option> <option value="#0000FF">Blue</option> </datalist>

Enter fullscreen mode Exit fullscreen mode

The user can either type a color name or a hex code. Add a bit of JavaScript to show a preview:

const input = document.querySelector('input'); const preview = document.getElementById('colorPreview'); input.addEventListener('input', () => { preview.style.backgroundColor = input.value; });

Enter fullscreen mode Exit fullscreen mode

The main limitation of <datalist> is styling - you can't easily customize the appearance of the dropdown options. If you need custom styling for the suggestions, you might still need a JavaScript solution. But for many use cases, the native element is perfectly adequate.

4. The <meter> Element: Semantic Measurement Display

When displaying values within a known range, most developers use a div with a background color. But HTML5 has a dedicated element for this:

<meter value="75" min="0" max="100" low="30" high="70" optimum="80"></meter>

Enter fullscreen mode Exit fullscreen mode

The browser styles it based on the thresholds you set. If the value is in the "low" range, it might show as yellow. If it's in the "high" range, it might show as orange. And if it's near the "optimum" value, it shows as green.

This is particularly useful for dashboards:

<!-- Disk usage (lower is better) --> <meter value="75" min="0" max="100" low="70" high="90" optimum="0">75%</meter> <!-- Battery level (higher is better) --> <meter value="35" min="0" max="100" low="20" high="60" optimum="100">35%</meter> <!-- CPU usage (lower is better) --> <meter value="82" min="0" max="100" low="60" high="80" optimum="0">82%</meter>

Enter fullscreen mode Exit fullscreen mode

The optimum attribute indicates whether higher or lower values are better, which affects the color.

Browser support is good, but styling options are limited. If you need a highly customized appearance, you might still need a custom solution. But for dashboards and monitoring UIs, the native element works well and communicates semantic meaning to screen readers.

5. The <output> Element: Dynamic Calculation Results

When building calculators or interactive forms, most developers use a div to show the result. But HTML5 has a dedicated element for this:

<form oninput="result.value = parseInt(a.value) + parseInt(b.value)"> <input type="number" id="a" value="0"> + <input type="number" id="b" value="0"> = <output name="result" for="a b">0</output> </form>

Enter fullscreen mode Exit fullscreen mode

The for attribute creates an explicit relationship between the inputs and the output, which helps screen readers understand that the output is a result of those specific inputs.

I used this in a side-project last year for a mortgage calculator:

<form id="mortgageCalc"> <div> <label for="principal">Loan Amount: $</label> <input type="number" id="principal" value="200000"> </div> <div> <label for="rate">Interest Rate: %</label> <input type="number" id="rate" value="3.5" step="0.1"> </div> <div> <label for="term">Loan Term (years):</label> <input type="number" id="term" value="30"> </div> <div> <button type="button" id="calculate">Calculate</button> </div> <div> <p>Monthly Payment: $<output id="payment">954.83</output></p> <p>Total Interest: $<output id="totalInterest">143,739.01</output></p> </div> </form>

Enter fullscreen mode Exit fullscreen mode

The main advantage is semantic meaning - screen readers can announce that the value is a calculation result. It's also a form element, so it can be included in form submissions if needed.

6. The <mark> Element: Semantic Highlighting

When highlighting text, most developers use a span with a background color. But HTML5 has a dedicated element for this:

<p>The <mark>quick brown fox</mark> jumps over the lazy dog.</p>

Enter fullscreen mode Exit fullscreen mode

By default, browsers style it with a yellow background, but you can customize it:

mark { background-color: #fff9c4; padding: 2px 4px; border-radius: 3px; }

Enter fullscreen mode Exit fullscreen mode

This is particularly useful for search results:

const searchTerm = "HTML"; const content = "HTML elements are the building blocks of HTML pages."; const highlighted = content.replace( new RegExp(searchTerm, 'gi'), match => `<mark>${match}</mark>` );

Enter fullscreen mode Exit fullscreen mode

The advantage is semantic meaning - screen readers can announce that text is highlighted, giving users a better understanding of why certain text stands out.

I've found this especially useful in documentation sites and knowledge bases, where highlighting search terms helps users quickly find what they're looking for.

7. The <time> Element: Semantic Dates and Times

Most developers display dates and times using regular text elements, but HTML5 has a dedicated element for this:

<p>The article was published on <time datetime="2025-05-20">May 20, 2025</time>.</p>

Enter fullscreen mode Exit fullscreen mode

The datetime attribute allows you to specify the date in a standardized format (ISO 8601) that machines can understand, while displaying a human-friendly format to users.

This is useful for search engines, which can extract the exact date, and for browsers or extensions that might want to offer features like adding events to calendars.

You can use it for various date and time formats:

<!-- Just a date --> <time datetime="2025-05-20">May 20, 2025</time> <!-- Date and time --> <time datetime="2025-05-20T14:30:00">2:30 PM on May 20, 2025</time> <!-- Just a time --> <time datetime="14:30:00">2:30 PM</time> <!-- A duration --> <time datetime="PT2H30M">2 hours and 30 minutes</time>

Enter fullscreen mode Exit fullscreen mode

One practical application is for relative times:

<p>Posted <time datetime="2025-05-18T14:30:00" class="relative-time">2 days ago</time></p>

Enter fullscreen mode Exit fullscreen mode

With JavaScript, you can update these periodically:

function updateRelativeTimes() { document.querySelectorAll('.relative-time').forEach(el => { const date = new Date(el.getAttribute('datetime')); el.textContent = getRelativeTimeString(date); }); } // Update every minute setInterval(updateRelativeTimes, 60000);

Enter fullscreen mode Exit fullscreen mode

This element is particularly valuable for blogs, news sites, and social media platforms, where accurate date and time information is important.

8. The <figure> and <figcaption> Elements: Semantic Image Captions

Most developers implement image captions with divs and paragraphs, but HTML5 has dedicated elements for this:

<figure> <img src="chart.jpg" alt="Sales chart for Q2 2025"> <figcaption>Fig.1 - Company sales increased by 25% in Q2 2025.</figcaption> </figure>

Enter fullscreen mode Exit fullscreen mode

The <figure> element isn't just for images - it can be used for any content that is referenced as a single unit:

<!-- Code snippet with caption --> <figure> <pre><code> function greet(name) { return `Hello, ${name}!`; } </code></pre> <figcaption>A simple JavaScript greeting function using template literals.</figcaption> </figure> <!-- Quote with attribution --> <figure> <blockquote> <p>The best way to predict the future is to invent it.</p> </blockquote> <figcaption>— Alan Kay</figcaption> </figure>

Enter fullscreen mode Exit fullscreen mode

These elements are particularly useful for content management systems and blogs, where editors need to add captions to images and other media.

A simple CSS setup can create a nice-looking gallery:

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px; } figure { margin: 0; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 5px rgba(0,0,0,0.1); transition: transform 0.3s; } figure:hover { transform: translateY(-5px); } figure img { width: 100%; height: 200px; object-fit: cover; display: block; } figcaption { padding: 10px; background-color: #f5f5f5; font-style: italic; }

Enter fullscreen mode Exit fullscreen mode

The main advantage is semantic meaning - screen readers can announce that the text is a caption for the associated content, improving accessibility.

Conclusion?

Embrace the Power of Native HTML.

We've explored eight HTML5 elements that offer elegant, built-in solutions to common web development challenges:

  1. <dialog> for native modal windows
  2. <details> and <summary> for collapsible content
  3. <datalist> for native autocomplete
  4. <meter> for semantic measurement display
  5. <output> for dynamic calculation results
  6. <mark> for semantic highlighting
  7. <time> for semantic dates and times
  8. <figure> and <figcaption> for semantic image captions

These elements reduce dependency on JavaScript, improve accessibility, and make your HTML more semantic and meaningful.

They're not perfect for every use case - building Lingo.dev oftentimes requires more customization or browser support than they can provide. But they're worth considering before reaching for a third-party solution.

What other HTML elements have you found useful in your projects? Let me know in the comments!


Useful links:

Read Entire Article