Tiffany B. Brown

HTML5 does NOT allow “self-closing” tags

… on non-void elements, at least.

One of the big misconceptions about HTML5 is that any tag can be self-closed. That’s not true, though it appears that way.

What HTML5 does is provide parsing rules for handling mismatched tags and markup. While it seems like self-closing tags are acceptable, that’s not the case. This post explains what’s really at play. Let’s take a look.

‘Self-closing’? Our old friend />

Let’s separate void elements from empty tags that don’t contain content. You’re probably familiar with "void" elements — elements that can’t have any content. They include the img, br, hr, and meta elements.

In XHTML, we closed void elements according to the rules of XML syntax, which requires all elements to be closed with end tags or self-closing tags. That’s where we get the familiar space-slash ( />) of XHTML. HTML5, however, uses HTML parsing syntax, making the  /> unnecessary for void elements. It is, however, valid to use it. Yes: <meta charset="UTF-8"> and <meta charset="UTF-8" /> are both acceptable.

Here’s the thing: a void element is not the same as an element that doesn’t contain any content. And ‘self-closing’ does not mean the same thing as “the end tag is optional.”

To state it clearly: Most HTML5 elements are not self-closing, but many elements do not require an end tag.

Wait, what? End tags are optional? It’s like HTML 3.2 all over again!

Yes, some HTML5 elements do not require an end tag. Those circumstances are outlined in the HTML5 specification. The p element, for example, does not require an end tag if the p element is immediately followed by an address, article, aside, blockquote, dir, div, dl, fieldset, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, menu, nav, ol, p, pre, section, table, or ul, element, or if there is no more content in the parent element and the parent element is not an a element.

In fact, some tags can be omitted altogether. Browsers with compliant HTML5 parsers (such as the recently released Opera 11.5 snapshot) will add the end tags to the DOM.

But again: "end-tag optional" is a different concept than self-closing.

How about some examples?

Let’s take a look at the following bit of code:

<!DOCTYPE html>
<html lang="en-us">
<head>
    <meta charset="UTF-8">
    <title>HTML tag example</title>
    <link rel="stylesheet" href="styles.css" media="screen">

</head>
<body>

<header>
    <hgroup>
        <h1>When self-closing tags fail</h1>
        <h2>Not all HTML5 elements are self closing, though some are ‘end tag optional’</h2>
    </hgroup>
</header>

<article>
<p>This is to demonstrate that all HTML elements are <em>not</em> actually self closing. There is a "self-closed" <code>p</code> element following this closed paragraph. And it’s followed by a a "self-closed" <code>a</code> tag and another paragraph.</p>

<p id="notaselfclosinggraf" /><a id="notaselfclosinganchor" />

<p>As you can see, this paragraph is part of the preceeding link.</p>

</article>

</body>
</html>

You can view the code yourself. Notice that the last paragraph is actually treated as the link text of the of the supposedly self-closed link before it.

Let’s take a look at another example:

<!DOCTYPE html>
<html lang="en-us">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,user-scalable=yes,initial-scale=1.0"/>
    <title>HTML tag example</title>
    <link rel="stylesheet" href="styles.css" media="screen" />
    <style>
        .trigger1{
            background: #369;
            border-radius: 4px;
            display:block;
            padding:3px;
            color:#fff;
        }
        
        
        #tvFinderImg{
            background:#0c0;
            display:block;
            width: 10px;
            height:10px;
        }    
        
        #tvFinderImg h3{
            border:1px dashed #c09;
        }
    </style>
</head>
<body>

<header>
    <h1>Spans aren't self-closing either</h1>
</header>

<div>
<a
class="trigger1" href="#tvFindersrchd">Lorem ipsum <span id="tvFinderImg" /></a>
<p>This is some copy after the "self-closed" tag.</p>
</div>
</body>
</html>

In older browsers — Internet Explorer 8, for example — the supposedly self-closed tags are handled like unclosed tags. In those browsers, you will see a pink border around This is some copy after the “self-closed” tag.

In browsers that do have HTML5-compliant parsers — Firefox 4, the Opera 11.5 labs build mentioned above — the browser re-writes the DOM and adds a closing span tag. Yep. HTML5 saves developers from ourselves by providing rules for handling bad markup. View the DOM of that page in Opera 11.5 with Dragonfly, or Firefox 4 using Firebug (or in Chrome, Safari or IE9 using their developer tools) to see what I mean.

Let me restate this point for clarity: it only appears that self-closing tags are permitted in HTML5. In actuality, the browser parser treats non-void, self-closed tags as start tags and closes them for you.

Don’t believe me? Try running these pages through the W3C Markup Validator.

So I can go back to sloppy code?

Maybe. I think you can make an excellent argument for using relaxed markup rules when targeting end-users who may be paying per byte of bandwidth or who are on slow connections — Canadian mobile users, for example. Send less code. Make the browser handle it.

But keep in mind that older browsers do not have HTML5 parsers. Internet Explorer 7 & 8 do not. Opera 11.10 beta does not. Opera Mobile does not. (Older versions of WebKit technically don’t either, but WebKit has long supported the /> syntax.) If you have a large proportion of older browser users in your audience, stick to the stricter, XML-style syntax: if you have a start tag, use an end tag. The space-slash is optional for void elements. Don’t forget to validate!

18 Responses to “HTML5 does NOT allow “self-closing” tags”

  1. Enlightening, thanks!

  2. Interesting, but I have to say that I’ve never before seen anyone self-close a tag or tag.
    And I don’t see the point of doing this ?!

  3. Anonymous says:

    There’s an example on BestBuy’s mobile site. If you run the following command from a terminal window, you can see it:

    curl -LA “Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7″ http://bestbuy.com/

    Look for this code:

    A few sites optimized for mobile Safari also use instead of because WebKit supported that syntax in XHTML.

  4. We all know what “best practice” is and we should always practice it. If someone looks at your code and it is lacking the proper closing it can confuse and tell them it is ok to cut corners. I for one will keep using the best practice and keep code clean and readable. Thanks for the post.

  5. Quemaltrip says:

    ITS SOOO TRUE

  6. porneL says:

    You’re not setting application/xhtml+xml MIME type, so you’re not requesting XML syntax to work in HTML5.

    In text/html mode HTML5 merely tolerates some XML-like talismans, without giving them any meaning.

    Please don’t forget that HTML5 has *two* syntaxes — text/html and XML — and the one that has detailed parsing rules in the spec is the text/html one.

  7. Anonymous says:

    Not quite. HTML5 is served as text/html. If you serve it with an application/xhtml+xml MIME type, you are serving XHTML. It is a slight, but significant difference.

    But this post is about non-void elements, not empty elements. In HTML5, and are perfectly valid, </a> is not, though some browsers will treat it that way. See the first sentence after the headline.

    IIRC, in both syntaxes, ONLY void elements can be self-closed. Other elements do not require a closing tag. For these elements, HTML5 parsers will auto-close them. Most inline items, and the script and style elements DO require it.

  8. Michel says:

    Firefox oddity: We have an xml structure where a link is created like this:
    text inside linkhttp:….</link>
    When entering that into an editor that parses the output to an iFrame, Firefox (and IE6-8 not)  will remove the </link> for you, ending up with invalid xml. A case in point is THIS EDITOR RIGHT HERE which did the bad deed right now!!!! I had to enter the end tag using & lt;

  9. Jacob says:

    Can I self close a script tag in the header if it has a src attribute set? E.g.

    Instead of

    Seems it would be redundant to close it properly like if there is no actual content inside the tag, as the content is coming in via the src attribute.

  10. Anonymous says:

    No. You still need the closing .

    Some older versions of Safari supported self-closed script tags if you used the space-slash syntax, but with its new parsing engine, it no longer does.

    The HTML5 specification is pretty clear about when tags can be self closed (for non-void elements such as ), when a closing tag is optional ( in most cases), and when a closing tag is required (most other elements).

  11. Anonymous says:

    Can you update your post to include a link to the HTML5 specification whereit shows “when tags can be self closed (for non-void elements such as ), when a closing tag is optional ( in most cases), and when a closing tag is required (most other elements).”? That’d be helpful for many readers. Excellent post, thanks!

  12. kontur says:

    Interesting read, but all in all: Stick to proper and logical syntax no matter what. Half of the postings on html5 found on the web are confusing, misleading or advocate that you disregard reasonable practices, like, euhm, ensuring your website can be properly viewed.

  13. Thulasiraman says:

    Hi,  even if I specify the self closing tag for img, br and hr, while do view source /> got changed to >.  So I am getting error in W3C validator.  How to keep closing tag?  Thanks

  14. Anonymous says:

    br and hr do not need to be self closed in HTML. they’re what’s known as void elements.

    if you’re seeing errors in the validator, make sure that you are using the right DOCTYPE and that you are serving content with the appropriate MIME or Content-type header value. If you’re using the /> to close your br and hr tags, you should make sure that your pages are served as XHTML and not XML.

  15. Thulasiraman says:

    Sorry.  In below text, doctype not getting displayed.  I am giving it again.Initial doctype (got validator error):
    <<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

    Changed to doctype (No error.  But not xhtml)
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

  16. Jonathan says:

    actuallly if you serve a page with application/xhtml+xml MIME type, it is not XHTML, but it is a  HTML5 document that is also a well formed XML document (XHTML5 Polyglot)

    http://www.w3.org/TR/html-polyglot/
    http://dev.w3.org/html5/html-xhtml-author-guide/

  17. Anonymous says:

    My interpretation of those documents – which I actually used as the basis for previous comment – is that you are *indeed* serving XHTML, though not in the sense that there’s an XHTML5 DOCTYPE. Perhaps a clearer way to explain it is to say that XHTML5 has been redefined to mean “HTML syntax served with an application/xhtml+xml content type and parsed according to the rules of XML well-formedness.” Now in terms of coding practices, again: that means using /> to close *void* elements — img, meta, br, hr — is fine, but not necessary in HTML5. It becomes mandatory, however, if you’re serving those pages with an  application/xhtml+xml content type.But using /> to close elements such as a or span *is not* valid “XHTML5,” even though it is certainly valid XHTML1.0. 

  18. JM says:

    good information about the html self-closing tags.  should save me the work having to go back and fix my tags later…