DEV Community

Cover image for Unleash the Power of the Platform with These HTML Tags
Yoav Ganbar for Builder.io

Posted on • Originally published at builder.io on

Unleash the Power of the Platform with These HTML Tags

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:

<button>Open</button>

<dialog>
 <h2>Hello World!</h2>
 <form method="dialog">
  <button>OK</button>
 </form>
</dialog>
Enter fullscreen mode Exit fullscreen mode

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:

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

buttonElm.addEventListener('click', () => {
 dialogElm.showModal();
})
Enter fullscreen mode Exit fullscreen mode

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:

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:

::backdrop {
 // you can go all out, if you want 😉
 background-color: lightcoral;
 opacity: 0.8;
}
Enter fullscreen mode Exit fullscreen mode

Here's what our styles look like in action:

A screenshot of an open dialog with a different backdrop color

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:

<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> 
Enter fullscreen mode Exit fullscreen mode

And the Javascript:

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);
})
Enter fullscreen mode Exit fullscreen mode

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:

For a deeper dive into the intricacies of the <dialog> element, I suggest checking out Adam Argyle’s post on web.dev.

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:

<details>
    <summary>I will be the title of the content underneath</summary>
    <p>Whatever is written here will be hidden by default</p>
</details>
Enter fullscreen mode Exit fullscreen mode

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

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:

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:

<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>
Enter fullscreen mode Exit fullscreen mode

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

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:

<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>
Enter fullscreen mode Exit fullscreen mode

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

This results in the a green bar in the browser:

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:

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

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:

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

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

This will result in a red bar:

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

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:

<progress value="70" max="100">70 %</progress>
Enter fullscreen mode Exit fullscreen mode

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:

When using this element, just remember that there are some 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:

<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>
Enter fullscreen mode Exit fullscreen mode

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

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 :afterpseudo elements, like so:

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] ";
}
Enter fullscreen mode Exit fullscreen mode

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:

<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>
Enter fullscreen mode Exit fullscreen mode

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:

For more about image optimizations, I suggest checking out “Optimal Images in HTML” a post that Steve wrote a while back.

Fun with math and science (elements)

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:

<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>
Enter fullscreen mode Exit fullscreen mode

Which would render this:

Yeah science!

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

<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>
Enter fullscreen mode Exit fullscreen mode

Which would yield this:

a screenshot of a text paragraph that has the correct molecular notation for caffeine.

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:

<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>
Enter fullscreen mode Exit fullscreen mode

Which would render this:

text with superscript and variable tags used to illustrate the Pythagorean theorem

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

<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>
Enter fullscreen mode Exit fullscreen mode

Which gives this result:

text with superscript and variable tags used to illustrate the Pythagorean theorem

Or superior lettering (not sure what that is for, but you can), like for certain French abbreviations (apparently, as I’ve learned from MDN):

<p>Robert a présenté son rapport à M<sup>lle</sup> Bernard.</p>
Enter fullscreen mode Exit fullscreen mode

That would render:

text with superscript and variable tags used to illustrate the Pythagorean theorem

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!

Visually build with your components

Builder.io is a headless CMS that lets you drag and drop with your components right within your existing site.

Try it out Learn more

// Dynamically render your components
export function MyPage({ json }) {
  return <BuilderComponent content={json} />
}

registerComponents([MyHero, MyProducts])
Enter fullscreen mode Exit fullscreen mode
Read the full post on the Builder.io blog

Top comments (0)