Are you an author writing HTML?
Just so we’re clear: Not XHTML. HTML. Without the X.
If you are, repeat after me, because apparently this bears repeating (after the title):
You are not required to close your
<br> tags in HTML.
(The same applies to over a dozen other elements but these are the most common ones.)
There are a number of reasons it is good practice to do so (which I’ll get to later in this article), but it is not wrong or inherently bad practice not to do so with elements with optional end tags or elements without end tags (believe it or not, these exist — they’re called void elements). Browsers do not treat missing optional end tags as errors that need to be recovered from.
Anyone telling you otherwise about these elements was unfortunately misinformed by the one before them. Please correct them, perhaps by pointing them to this article; chances are you were referred here by me or someone else for this very reason.
For the sake of convenience, “HTML5” refers to either WHATWG HTML (the living standard) or W3C HTML5, whichever you’re personally more comfortable with. None of the differences between the two are pertinent to this article, so I won’t even make any references to either specification.
Table of contents
- The rules in HTML, and XHTML
- Best practices in HTML
I see the following examples of misinformation being spread almost every day on Stack Overflow, in both comments and answers (that get upvoted!):
Your markup is invalid — you must close all your tags or browsers will fix them for you.
You have not closed your
imgtags properly, this is how they should be:
<img src="..." />
bodytags are missing; your page will not render correctly without them.
As well as the following examples of confused comments, directed at me when I post HTML snippets with optional tags omitted for brevity, or when I state the same thing I just massively did above:
Are you sure that’s valid? I’ve never seen a table without
Did you forget to close your
ptags or is that on purpose?
why self-close tags?is in the same category as
why use DOCTYPE?No one will complain if you don’t. But the guy is learning. Maybe you should learn strict coding standards instead of the quirky [sic] ones?
These are all adapted from real comments; that last one was from just this week. Now, spreading misinformation is one thing. But spreading misinformation under the guise of “the guy is learning” (and attempting to school me about “strict coding standards”1)? Sorry, but I can’t allow that. That’s why I finally got around to writing this article after sitting on it for years — for the benefit of those who are learning.
(BTW, no, those two questions aren’t in the same category at all. The DOCTYPE is mandatory, period. Self-closing void element tags in HTML using the
/> syntax is entirely a matter of personal preference — I cover this in full detail below.)
These misconceptions appear to stem from the XHTML fad of the 00s, before HTML5 emerged. XHTML, being based on XML as opposed to SGML, is notorious for being author-unfriendly due to its strictness, requiring start and end tags for all elements (including void elements using the
/> syntax) and quotes around attribute values, as well as forbidding minimization of Boolean attributes such as
required. (Nevertheless, everyone attempted to write XHTML, although almost no one ended up actually writing and serving true XHTML.) It would seem that many authors who don’t know better have mistakenly believed that these rules carry over to HTML5 as they moved away from XHTML, and the misinformation has been spreading ever since.
The rules in HTML, and XHTML
Let’s start with some markup examples. The following fragments are valid HTML and well-formed XHTML:
<p>This paragraph has an end tag.</p> <p>So does this one.</p>
<ol> <li>This list item has an end tag.</li> <li>So does this one.</li> </ol>
Stuff you’re probably used to, where every element has a matching pair of start and end tags.
On the other hand, if the following fragments make you uncomfortable, relax — they may not be well-formed XHTML, but they are valid HTML, because the end tags of
li are optional and browsers are told exactly when to implicitly close a previously open element (again, this is not error recovery!):
<p>This paragraph does not have an end tag. <p>Neither does this one.
<ol> <li>This list item does not have an end tag. <li>Neither does this one. </ol>
This is actually how I was taught HTML growing up! According to the Neopets HTML Guide,
<p> tags were simply a way to start new paragraphs of text, and similarly
<li> tags represented the bullets or numbers themselves. Following this logic, end tags weren’t needed.2 So, it actually baffles me any time someone claims that
li have “always required” end tags. Au contraire, they never did, and never have in over 20 years. But I digress; enough about my childhood.
In situations where line breaks and indentation are involved, the only difference between these two pairs of fragments is how inter-element whitespace is treated: there is no inter-element whitespace between each pair of elements without their end tags — the whitespace all becomes part of the text content of the first element in each pair. This does have certain implications in CSS, particularly in inline layout where whitespace processing plays a crucial, if not central, role.
Next, let’s look at the shortcut “self-closing” syntax
/>. This syntax comes from XML, so it follows that it’s used in XHTML. So, if HTML5 is a language in its own right and neither based on SGML nor XML, what is
/> doing in HTML5? It’s there for exactly one reason: ease of migration from XHTML.3 You have an XHTML document with all these void elements closed with the
/> syntax as expected in XHTML. Migrating it to HTML5, provided there are no other compatibility issues such as the use of obsolete elements like
acronym, is as easy as switching the DOCTYPE declaration to
<!DOCTYPE html>. Bam. Done.
Alright, so, I keep mentioning void elements. What is a void element? A void element in HTML is an element that has a start tag and no end tag (and therefore no content, hence “void”). Common examples of void elements include
meta. A full list can be found in the spec. In previous versions of HTML, they were known as empty elements, however XML and now HTML make a distinction between empty elements and void elements, so the term to use going forward is “void elements.” In summary:
- An empty element is one that has no content, regardless of whether it is allowed to have content in the first place.
- A void element is one that cannot have any content.
Additionally, it can be said that all void elements are empty elements by definition, but an empty element does not necessarily represent a void element.
Now that you understand where the
/> syntax came from and why it’s in use today, let’s look at some examples. The following fragment is valid HTML5 and well-formed XHTML, but not valid in any older version of HTML:
<p><img src="lightbulb.jpg" alt="" /><br /> I'm aware that the use of <code>br</code> here is incorrect; this is simply for illustrative purposes.</p>
Again, stuff you’re probably used to, especially if you were taught to always self-close your void element tags using
But, as the title of this article states, you are not required to do that. The following fragment is not well-formed XHTML, but it is valid in all versions of HTML:
<p><img src="lightbulb.jpg" alt=""><br> I'm aware that the use of <code>br</code> here is incorrect; this is simply for illustrative purposes.</p>
Before I go on, you may also have noticed that there has always been a space before the
/> in HTML5 and XHTML, even in the example fragments in this article. This is also not required in either dialect, in the sense that
<br/> validates just as well as
<br /> does.4 However, it is a tradition dating back nearly 20 years (again!), and the reason for this tradition was that Netscape Navigator 3 (you read that right, not even Netscape 4, but Netscape 3) would choke on
Yes, an actual browser bug. I’m totally fine with tradition that has roots in actual cross-browser problems, because while those problems may no longer be relevant today, they were once upon a time, so people didn’t really have a choice back then. In contrast, no browser in the history of XHTML has ever treated the
/> syntax itself incorrectly — evidently, NN3 handled that just fine, provided you included the space — so there really is no excuse for claiming that
/> is required for void elements in HTML.
Speaking of which, best practices to come shortly, I promise. (You can also skip straight over right now if you prefer, because what follows is advanced stuff.)
For now, this is where things get really interesting. The following fragment is well-formed XHTML5, but not valid in any version of HTML:
<div /> <p /> <input type="text"></input>
</input> end tag is allowed in XHTML because XML always permits using either an explicit end tag or the
/> syntax to close an empty element. However, because
input is a void element, it does not have an end tag in HTML, and therefore specifying an explicit one is forbidden.
But because the
/> syntax comes from XML and not SGML, even though it exists in HTML5 solely to ease migration from XHTML, apart from foreign elements it is completely meaningless in HTML5 and invalid in all older, SGML-based versions of HTML. And since void elements don’t have end tags, whether or not you self-close them is entirely a matter of personal preference.
What about non-void elements? Well, not only is
<div /> treated exactly the same as
<div> (resulting in a
div that is missing an end tag), but the same fragment above actually produces different DOM trees in HTML and XHTML (when served as
application/xhtml+xml as intended) for this reason.
In the HTML DOM, the
input is a child of the
p, which in turn is a child of the
div (inter-element whitespace not significant for the purposes of this example; explicit end tags added for clarity):
<div> <p> <input type="text"> </p> </div>
In the XHTML DOM, the
input are empty siblings of one another (again, explicit end tags added for clarity):
<div></div> <p></p> <input type="text"></input>
For most authors, this will never be a problem since anyone who tries to use
/> to self-close non-void elements tags in
text/html will quickly find out that it doesn’t work anyway. (They probably spend a tad longer confused if writing “XHTML”, i.e. XHTML that’s not served as
application/xhtml+xml as intended, but as mentioned almost no one ever serves it with the correct MIME type to begin with, so again this really is a non-issue.)
Alright! Now for best practices. What you can do, and what you should do when in doubt.
Best practices in HTML
Disclaimer: this is just my opinion, not gospel. But, if I do say so myself, I feel it’s advice worth considering. Having said that, if you have any views of your own that you’d like to share, feel free to leave a comment and we can discuss, so long as we promise to be respectful to one another.
Here’s what I recommend to anyone building a new site, whether they’re a new or seasoned HTML author: Be consistent. You really have two choices here: you can either
- take advantage of any or all of the conveniences HTML offers to you, such as leaving out optional tags where appropriate, attribute minimization (e.g.
checked="checked"), not self-closing your void element tags with
/>, etc; or
write XHTML in accordance with the XML rules (so-called “strict coding standards”), which means always writing out all tags (because they’re all required), expanding Boolean attributes (e.g.
checked), self-closing void element tags, etc, all at the cost of significantly more verbose markup. This verbosity may mean improved or diminished readability depending on how you see it, though.
If you do decide to write XHTML, keep in mind that you’re still writing HTML as long as you’re serving it as
text/html — if you want to serve HTML5 as XHTML, aka “XHTML5”, your server needs to be configured to serve your pages as
application/xhtml+xml, and Internet Explorer 8 and older will not be able to open your pages at all.
As for the rest of us:
- For those who are still getting the hang of it, even if you decide that HTML is not XML (which is true) or you just don’t want to put up with the verbosity that is XML, I still recommend that you always open and close your non-void element tags explicitly, even in situations where they’re not required. It’s a good habit to cultivate as it will help you keep track of where all your elements begin and end, especially when you’re nested several levels deep, and you don’t have to remember which elements require end tags and which ones don’t. You can never go wrong with closing all your non-void element tags.
For the well-versed, there’s no harm in leaving out optional tags for the sake of brevity, especially when you’re writing technical documentation and including short, self-contained example fragments like the ones in this very article, as long as you know what you’re doing. Tables benefit the most from this, as depending on how you use line breaks and indentation you can nearly halve the number of lines just by removing unnecessary end tags! (It also gives you an excuse to link back to this article when you get questioned the same way I do, but don’t tell anyone I told you that!)
For void elements, it gets a little complicated. First, learn what the void elements are; here’s the link to the spec again (HTML being a living standard, the list is subject to change over the years). Then, should you decide to self-close them with
/>, to keep my advice on being consistent you should also quote all your attribute values and expand all your Boolean attributes. While the following fragment validates as HTML5:
<input type=checkbox checked />
… it’s considered very unusual because you’re mixing HTML syntax with XML syntax, and it does not validate in any other version or dialect of the language for this reason. So again, be consistent: choose either one of these, and stick to it everywhere:
<!-- Or single quotes, or none at all where allowed, but I recommend always quoting attribute values for the same reason I recommend always closing your non-void element tags even when not needed. --> <input type="checkbox" checked>
<!-- Or single quotes; quotes are normally mandatory in XHTML --> <input type="checkbox" checked="checked" />
As mentioned in the very beginning of this article, any time someone yells at you to close your
<br> tags because “your markup is invalid”, and you haven’t stated outright that you’re writing XHTML, refer them to this article, and don’t worry about it. You are doing nothing wrong. Even if you meant to include the end tags (perhaps based on my suggestions above) and simply left some out by accident, that’s a separate issue altogether. My point is that it’s not invalid as many seem to claim.
And here’s what I recommend when migrating an existing site to HTML5: If it ain’t broke, don’t fix it. In the vast majority of cases, provided your site already validates according to whatever DTD it had before, switching the DOCTYPE to
<!DOCTYPE html> should be enough. It doesn’t matter whether the site was previously XHTML or an older version of HTML. Roll with it. HTML5 is cool like that, by design.
When the time comes for a redesign, then you can throw out everything you learned about XHTML and just focus on writing standards-compliant HTML6 — which does not necessitate using the
/> syntax or expanding Boolean attributes. Don’t let anyone tell you otherwise.
- I built and maintained over half a dozen sites and WordPress themes that remained entirely Valid XHTML 1.0 Strict for over 10 years combined. I think it’s safe to say I know strict markup better than you do. (Any WordPress theme developer from that era knows that the things are a nightmare to make XHTML 1.0 Strict-compliant.) ↩
In fact, the original 1993 draft of HTML that predates 1995’s RFC 1866 (HTML 2.0) described both
liin nearly the exact same way as Neopets did, and defined them as having an empty content model, just like
br, meaning they originally didn’t have end tags either! ↩
- See also the obsolete polyglot markup TR. ↩
- In fact, the vast majority of other XML documents don’t include the space because it’s considered unnatural to do so. ↩
It’s invalid XHTML 1.0, though, in the context of the
bodyelement because it doesn’t permit
inputbeing a child of
- Unless you really like XHTML — I for one would probably call myself an XHTML apologist. ↩