Unleash the Power of the Platform with These HTML Tags
Tags: webdev, html, frontend, tutorial
Published: 2023-08-15 07:39:25

Get ready to spice up your HTML game with some seriously underrated tags! In this blog post we'll uncover some hidden gems that will make your web development skills shine brighter than a disco ball. From the sassy `<details>` tag to the snazzy `<mark>` tag, we'll cover a variety of elements that will take your web pages from drab to fab. So, buckle up and let's explore some exciting new ways to level up your HTML coding skills.

## The OG HTML modal - `<dialog>`

How many times did you reach for a library when you needed a modal?

I know I have so many times…

However, since last year, when Safari and Firefox added support for the `<dialog>` element, you can finally “use the platform”!

Creating a basic dialog looks something like this:

```html
<button>Open</button>

<dialog>
 <h2>Hello World!</h2>
 <form method="dialog">
  <button>OK</button>
 </form>
</dialog>
```

Whatever is in the `<dialog>` tag will be hidden from a user. The button in the above code is the means for the user to open the dialog, but in order for this to work we’d need to add a bit of JavaScript:

```js
const dialogElm = document.querySelector('dialog');
const buttonElm = document.querySelector('button');

buttonElm.addEventListener('click', () => {
 dialogElm.showModal();
})
```

In the video below, you can see how clicking on the `open` button opens the modal, and the `OK` button inside the dialog closes it:

<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fdc34a8def46344948f439b3bacc38cbf%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=dc34a8def46344948f439b3bacc38cbf&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

Let’s break it down:

- In order to show the dialog (modal) we use the built in `showModal()` function on the `<dialog>` element. This adds the `aria-modal="true"` attribute for accessibility purposes as well as provide the ability to close the modal with the `Esc` key. Furthermore, the initial focus of the user will be set on the first nested focusable element.
- The `<form method="dialog">` with the `<button>` (which defaults to `type=submit`) allows us to close to dialog. Another option is to provide the button with the `formmethod="dialog"` attribute and remove the method from the `<form>`.

### Styling the backdrop

You can customize the backdrop background using the `::backdrop` pseudo element:

```css
::backdrop {
 // you can go all out, if you want 😉
 background-color: lightcoral;
 opacity: 0.8;
}
```

Here's what our styles look like in action:

 ![A screenshot of an open dialog with a different backdrop color](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Ff4e6e5850ca842dabd26eecf44ce041f?width=800)
### Returning values from the dialog

When using a `<form>` element inside a `<dialog>` element, it’s possible to get a return value from the `<dialog>` `close` event.

Let’s observe a basic example. This is the HTML:

```html
<button id="show">Open</button>
<output></output>

<dialog>
 <h2>Hello Dialog!</h2>
 <form>
  <label for="name-input">Enter something</label>
  <input id="name-input">
  <button id="ok" value="" formmethod="dialog">OK</button>
  </form>
</dialog> 
```

And the Javascript:

```js
const dialogElm = document.querySelector('dialog');
const showButton = document.getElementById('show');
const outputElm = document.querySelector('output');
const nameInput = document.getElementById('name-input');
const okButton = document.getElementById('ok');

// open the modal
showButton.addEventListener('click', () => {
 dialogElm.showModal();
})

// set the input value as the button value
nameInput.addEventListener('change', (e) => {
 okButton.value = nameInput.value;
});

// when the dialog close event is sent, set the <output> as the return value
dialogElm.addEventListener('close', (e) => {
  outputElm.value = dialogElm.returnValue === '' ? "No return value." : `ReturnValue: ${dialogElm.returnValue}.`; 
});

// programatically prevent the default button event and use the dialog close
// event, sending the value of the input field.
okButton.addEventListener('click', (e) => {
 e.preventDefault();
 dialogElm.close(nameInput.value);
})
```

The next video shows how you can open the modal, fill in the inner form, close it using the confirmation button, and get the value of the input outside of it:

<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fe7d8d4da607a4bd5b8d844390994ecce%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=e7d8d4da607a4bd5b8d844390994ecce&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video> 

> For a deeper dive into the intricacies of the `<dialog>` element, I suggest checking out [Adam Argyle’s post on web.dev](https://web.dev/building-a-dialog-component/).

## Disclosure widget with `<details>` and `<summary>`

Using `<details>` and `<summary>` allows the creation of collapsible sections of content with a summary that can be clicked to reveal or hide the details:

```html
<details>
    <summary>I will be the title of the content underneath</summary>
    <p>Whatever is written here will be hidden by default</p>
</details>
```

In the video below we can see how clicking on the `<summary>` content reveals the rest:

<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F1febd193f30244b6a8ad8f5974a94e20%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=1febd193f30244b6a8ad8f5974a94e20&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

Show and hide content with no JavaScript?!

Is this magic?!

No. It’s part of the platform.

You can also control the open/close state with JS, but the beauty is you don’t have to. In order to render an open widget, one can add an `open` attribute to the `<details>` element.

Notice that we do get some browser default styles like the triangle on the left.

If we wanted to change styles we could use the `list-style` CSS property to change the triangle and the `details[open]` selector to change the content styles based on the open state.

Check out a working example of these elements below:

{% codepen https://codepen.io/hamatoyogi/pen/rNQXPqe  %}

## Native autocomplete with `<datalist>`

Did you know that your browser has an element that basically gives you an autocomplete with no JavaScript?

Using `<datalist>`, `<option>`, and an `<input>` element is all you need!

Check it out:

```html
<label for="ice-cream-choice">Choose a flavor:</label>
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice">

<datalist id="ice-cream-flavors">
    <option value="Chocolate">
    <option value="Coconut">
    <option value="Mint">
    <option value="Strawberry">
    <option value="Vanilla">
</datalist>
```

This will show us an input in which, when we start typing, will give us suggestions:

<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F6df20f6e47cd456eb6760bb5461864c7%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=6df20f6e47cd456eb6760bb5461864c7&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

The bonus is that we get keyboard controls for the suggestions, and easily navigate through the list.

## Value bars with `<meter>` / `<progress>`

`<meter>` is an HTML element that allows you to display a value within a predefined range. It's often used to show progress bars or levels. It accepts the following attributes: `value`, `min`, `max`, `low`, `high`, and `optimum`.

With these attributes, we can indicate to the browser what the color of the bar would be, depending on the values.

This is best understood through an example. Let’s take this fuel level example:

```html
<label for="fuel">Fuel level:</label>

<meter id="fuel"
       min="0" max="100"
       low="33" high="66" optimum="80"
       value="70">
    at 70/100
</meter>
```

> What you put between the opening and closing <meter> tag does not display.

This results in the a green bar in the browser:

{% codepen https://codepen.io/hamatoyogi/pen/Jjegxqy %}

The bar is green because our value (70) is higher than the `high` attribute, therefore, we get green.

If we change the value to something lower than the `high` value, for example, `60` our bar will change its color to yellow, without needing to change any CSS:

{% codepen https://codepen.io/hamatoyogi/pen/vYQobwr %}

And if we set the `value` attribute to lower than the `low` (33) value, that would result in a red bar:

{% codepen https://codepen.io/hamatoyogi/pen/poQMGXJ %}

Pretty neat, no?

### Flipping colors

Now, let’s say we want to display something that has the opposite definition, meaning, when we have more, it’s bad, and when we have less, it’s better.

For example, let’s say we want to display how much space we have left on a hard drive. In order to do this, all we have to do is define our attributes opposite to what we did with the fuel example:

```html
<label for="disc-space">Disc space:</label>

<meter id="disc-space"
       min="0" max="1024"
       low="750" high="300"   
       value="850">
</meter>
```

This will result in a red bar:

{% codepen https://codepen.io/hamatoyogi/pen/YzRmBoL %}

When we have more disc space (value is less than low, for example 650) we’ll get a green bar:

{% codepen https://codepen.io/hamatoyogi/pen/XWyvOvN %}

### Using `<progress>`

The `<progress>` element differs from `<meter>` only slightly:

- It only has 2 attributes: max + value (the minimum value is always 0).
- It only displays one color out of the box.

Here’s a simple example:

```html
<progress value="70" max="100">70 %</progress>
```

{% codepen https://codepen.io/hamatoyogi/pen/OJaKdKd %}

However the one cool feature about this element, is that if you omit all of the attributes, you get an animated loading bar with a blue ellipsis moving back and forward:

{% codepen https://codepen.io/hamatoyogi/pen/eYQqXOd %}

When using this element, just remember that there are [some accessibility concerns](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress#accessibility_concerns).

## Highlight text with `<mark>`

As the name suggests, `<mark>` can be used to mark/highlight text within a block of content. For example:

```html
<blockquote>
  It is a period of civil war. Rebel spaceships, striking from a hidden base,
  have won their first victory against the evil Galactic Empire. During the
  battle, <mark>Rebel spies managed to steal secret plans</mark> to the Empire's
  ultimate weapon, the DEATH STAR, an armored space station with enough power to
  destroy an entire planet.
</blockquote>
```

Will render with the words in the `<mark>` tag as highlighted yellow:

{% codepen https://codepen.io/hamatoyogi/pen/NWEQJKQ  %}

One thing to note about accessibility is that in order for screen readers to announce “marked” content, you need to use CSS in combination with `:before` and `:after `pseudo elements, like so:

```css
mark::before,
mark::after {
  clip-path: inset(100%);
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

mark::before {
  content: " [highlight start] ";
}

mark::after {
  content: " [highlight end] ";
}
```

## Responsive image sources with `<picture>`

One of the most underrated HTML tags is the `<picture>` element, which allows you to serve different images based on the user's device and screen size. This can greatly improve the loading speed and user experience of your website.

To use the `<picture>` tag, you just include multiple `<source>` elements within the tag, each with a different image source and media query to determine when it should be displayed.

Here's an example of how to use the `<picture>` tag:

```html
<picture>

	<source srcset="image-large.jpg" media="(min-width: 1200px)">

	<source srcset="image-medium.jpg" media="(min-width: 768px)">

	<source srcset="image-small.jpg">

	<img src="image-fallback.jpg" alt="Image">

</picture>
```

In this example, the browser chooses the appropriate image source based on the user's device and screen size. The first `<source>` element is used for devices with a minimum width of 1200 pixels, the second for devices with a minimum width of 768 pixels, and the third for all other devices.

If the browser does not support the `<picture>` tag, it will fallback to the `<img>` element (although, all major browsers have supported this for a few years now).

By using the `<picture>` tag, you can optimize your images for different devices and improve your website's performance and user experience.

Below we can see this in action, when we resize the window, the browser renders a different image:

<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F6a164f42f08c4514819c5080eefe44e8%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=6a164f42f08c4514819c5080eefe44e8&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

For more about image optimizations, I suggest checking out [“Optimal Images in HTML”](https://www.builder.io/blog/fast-images) a post that [Steve](https://twitter.com/steve8708) wrote a while back.

## Fun with math and science (elements)

[MathML](https://developer.mozilla.org/en-US/docs/Web/MathML) is an XML based language for describing mathematical notations.

The gist of it is that there are many elements that you can use to display equations and “sciencey” stuff, in case you need to.

I will not dive in too deeply here, as I probably lack the math knowledge to actually explain anything significant.

It’s just pretty cool to know that you can use the `<math>` element with a variety of other sub elements to do something like this:

```html
<p>
  The infinite sum
  <math display="block">
    <mrow>
      <munderover>
        <mo>∑</mo>
        <mrow>
          <mi>n</mi>
          <mo>=</mo>
          <mn>1</mn>
        </mrow>
        <mrow>
          <mo>+</mo>
          <mn>∞</mn>
        </mrow>
      </munderover>
      <mfrac>
        <mn>1</mn>
        <msup>
          <mi>n</mi>
          <mn>2</mn>
        </msup>
      </mfrac>
    </mrow>
  </math>
  is equal to the real number
  <math display="inline">
    <mfrac>
      <msup>
        <mi>π</mi>
        <mn>2</mn>
      </msup>
      <mn>6</mn>
    </mfrac></math
  >.
</p>
```

Which would render this:

{% codepen https://codepen.io/hamatoyogi/pen/dyQxrym %}

### Yeah science!
<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F393f8fe625d046778cb46dd70caa00b6%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=393f8fe625d046778cb46dd70caa00b6&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

With the `<sub>` element you can do stuff like this:

```html
<p>
  Almost every developer's favorite molecule is
  C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>, which is commonly known
  as "caffeine."
</p>
```

Which would yield this:

 ![a screenshot of a text paragraph that has the correct molecular notation for caffeine.](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F521855c6a4f3417b8186c73c4f26f711?width=758)

This can come in handy for your chemistry website, or if you want to add footnotes.

Some more useful elements are `<sup>` which can be combined with `<var>` to show off your algebra:

```html
<p>The <em>Pythagorean theorem</em> is often expressed as the following equation:</p>

<p><var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var></p>
```

Which would render this:

 ![text with superscript and variable tags used to illustrate the Pythagorean theorem](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fbc0c5f81937f45a79d5a16dc72ae2ad8?width=296)

But you could also use `<sup>` to add ordinal numbers, like so:

```html
<p>
  The ordinal number "fifth" can be abbreviated in various languages as follows:
</p>
<ul>
  <li>English: 5<sup>th</sup></li>
  <li>French: 5<sup>ème</sup></li>
</ul>
```

Which gives this result:

 ![text with superscript and variable tags used to illustrate the Pythagorean theorem](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fe05e7865be73491ebe81b37296a472e3?width=788)

Or superior lettering (not sure what that is for, but you can), like for certain French abbreviations (apparently, as [I’ve learned from MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup#superior_lettering)):

```html
<p>Robert a présenté son rapport à M<sup>lle</sup> Bernard.</p>
```

That would render:

 ![text with superscript and variable tags used to illustrate the Pythagorean theorem](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fbba074371a994480b434796ef46e5498?width=788)

## Moaaaaaar elements!

- You can show text diffing with `<del>` and `<ins>`.
- You can use `<kbd>` to show textual user input from a keyboard, voice input, or any other text entry device.
- `<abbr>` is used to provide an abbreviation or acronym for a term.
- Use `<cite>` to, well, cite creative work.
- The `<bdi>` element can help contain text when you need to isolate bi-directional text, for example mixing a left-to-right (LTR) language with a right-to-left (RTL).

## Conclusion

In conclusion, HTML has a wide variety of elements that can help you create rich and interactive web pages. From the lesser-known elements like `<dialog>` and `<picture>`, to the more commonly used elements like `<div>` and `<p>`, each element provides unique functionality that can help you create a great user experience on your website. By taking advantage of these elements, you can make your website more accessible, more performant, and more engaging for your users.

Happy coding!

 ![](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F83677fb912dd4a539a3f3bb5c0c82de1?width=405)<video muted autoplay loop playsinline controls>
      <source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F77cc5249f71948568195e7314bcc5766%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&amp;token=77cc5249f71948568195e7314bcc5766&amp;alt=media&amp;optimized=true" type="video/mp4">
    </source></video>

Visually build with your components

[Builder.io](https://www.builder.io/m/developers) is a headless CMS that lets you [drag and drop](https://www.builder.io/m/products) with [**your** components](https://www.builder.io/m/developers) right within your existing site.

[Try it out](https://builder.io/signup) [Learn more](/m/developers) 
```ts
// Dynamically render your components
export function MyPage({ json }) {
  return <BuilderComponent content={json} />
}

registerComponents([MyHero, MyProducts])
```

##### _Read the [full post](https://www.builder.io/blog/powerful-html-tags) on the [Builder.io blog](https://www.builder.io/blog)_