Skip to content

Markup » Void elements

Maximilian Goisser edited this page Jan 18, 2024 · 2 revisions

This page provides markup guidance on void elements in HTML documents — that is, the area, base, br, col, embed, hr, img, input, link, meta, source, and track, wbr elements — while explaining the context for the checker “Trailing slash on void elements has no effect and interacts badly with unquoted attribute values” message.

Trailing slashes

In the HTML Standard, the section defining requirements for the start tag of an element includes the following paragraph:

If the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/), which on foreign elements marks the start tag as self-closing. On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.

Note, in particular, the standard states the following two points about trailing slashes (/ U+002F SOLIDUS characters):

  • Trailing slashes in void-element start tags do not mark the start tags as self-closing.
  • Trailing slashes directly preceded by unquoted attribute values become part of the attribute value.

The following sections provide a few more details about those two points.

Trailing slashes in void-element start tags do not mark the start tags as self-closing

What the quoted paragraph above from the HTML standard is saying is that, to mark up, for example, an hr element, both of the following are allowed:

  • Start tag without trailing slash:

    <hr>
  • Start tag with trailing slash:

    <hr/>

However, what the standard also explicitly states is that in the <hr/> case, the trailing slash does not mark the start tag as self-closing.

In other words, the standard states that you can use a trailing slash in a void-element start tag for literally any purpose except to mark the start tag as self-closing.

So, for example, the following are all acceptable reasons for using a trailing slash in a void-element start tag —

  • ✅ I use a trailing slash because I like how it looks.
  • ✅ I use a trailing slash because I run my HTML markup through a formatting tool that’s hardcoded to add trailing slashes to all void-element start tags, without any option for me to prevent the tool from doing that.
  • ✅ I use a trailing slash because I write a lot of JSX code, and JSX requires the trailing slash — without any option for me to prevent JSX from doing that — so for consistency with what I’m accustomed to in JSX, I follow that same style in actual HTML documents.

However, the following reason does not concur with what the HTML standard states —

  • ❌ I use a trailing slash to mark start tags as self-closing.

For more about this, see the Promoting the right mental model for void elements section.

Trailing slashes directly preceded by unquoted attribute values

Consider the following two cases for marking up an img element for the image at http://www.example.com/logo.svg:

  • img element without trailing slash:

    <img alt=SVG src=http://www.example.com/logo.svg>
  • img element with trailing slash:

    <img alt=SVG src=http://www.example.com/logo.svg/>

In the first case (without the trailing slash), http://www.example.com/logo.svg becomes the value of the src attribute in the DOM, as expected.

However, in the second case (with the trailing slash), http://www.example.com/logo.svg/ unexpectedly becomes the value of the src attribute in the DOM — which breaks display of the image. See https://software.hixie.ch/utilities/js/live-dom-viewer/?saved=10856 for a live demo of that problem.

And that’s why the HTML standard states that trailing slashes should be used only with caution — to avoid cases like the one above, where the trailing slash can unexpectedly become part of an attribute value.

Configuring tools to not output trailing slashes for void elements

This section provides how-to info on configuring particular tools to not add trailing slashes to void elements.

  • Prettier is hardcoded to add trailing slashes to all void-element start tags, and provides no option for users who want the choice of not having trailing slashes in void elements — though there is a highly-upvoted issue that’s been open since 2018 asking for such an option. There is a community-maintained plugin to not use trailing slashes in void elements.

  • VS Code, with the Prettier plugin installed, adds trailing slashes to all void elements. But you can prevent that — by adding the following to your settings.json file:

    "editor.formatOnSave": true,
    "[html]": {
        "editor.defaultFormatter": "vscode.html-language-features"
    }
    
  • Autoptimize can be configured to output void elements without trailing slashes, by using a filter with the autoptimize_html_after_minify hook — like this:

    add_filter( 'autoptimize_html_after_minify', function( $html ) {
        return str_replace( '/>', '>', $html );
    } );
  • Joomla adds trailing slashes to void elements output by, for example, $doc->addHeadLink — but there’s an open issue asking for that behavior to be made optional.

  • Symfony adds trailing slashes to input elements — but there’s an open issue suggesting that be changed.

  • Hugo has a {{ hugo.Generator }} call which causes a meta element to be output with a trailing slash. To avoid that, rather than using that call, you can instead use this HTML markup:

     <meta name="generator" content="Hugo {{ hugo.Version }}">
  • Umbraco Forms adds trailing slashes to input elements; a related issue was closed without a fix, with this comment:

    there is as discussed the option of taking copies of the view files, saving them on disk in the expected locations, and updating them to your preference. For Forms 10, the default theme views are shipped as part of a Razor Class Library, but you can get copies of them for reference/adapting via the documentation.

  • ASP.NET Core has a mechanism for automatically adding a CSRF token to a document, and that mechanism creates an input element with a trailing slash; a related issue was closed without a fix.

Suppressing the “Trailing slash on void elements has no effect” message

If you want to persistently suppress/filter/ignore the “Trailing slash on void elements has no effect” messages from the checker, you can use the Message Filtering button in the checker UI:

message-filtering

After you do that, the “Trailing slash on void elements has no effect” messages will be persistently filtered out for all future documents you check.

When using the checker from the command line, you can suppress/filter/ignore the “Trailing slash on void elements has no effect” messages using the --filterfile or --filterpattern command-line options.

And when running your own instance of the checker service, you can suppress/filter/ignore the “Trailing slash on void elements has no effect” messages using one of the several different mechanisms provided.

Promoting the right mental model for void elements

When learning about HTML, teaching about HTML, and designing HTML tools, it’s important to have and promote the right mental model about how HTML actually works.

And the way HTML works is that there’s a discrete set of void elements, hardcoded into HTML parsers, and people who write HTML must learn and remember which elements those are — without any trailing slash needing to be added to those elements to indicate they are special.

Using trailing slashes in void elements (and teaching others to use trailing slashes, and making your tools output trailing slashes) promotes a misleading mental model of HTML where the trailing slash looks like it has some special significance — when in fact, as the HTML standard says, it’s “unnecessary and has no effect of any kind”.

For more explanation, see the following: