There is a variety of HTML that you can just leave out of the source HTML and it’s still valid markup.
Doesn’t this look weird?
<p>Paragraph one.
<p>Paragraph two.
<p>Paragraph three.
It does to me, but the closing </p>
tags are optional. The browser will detect it needs them and manifest correctly in the DOM anyway.
This probably happens to HTML you write and you don’t even know it. For example…
<table>
<tr>
<td></td>
</tr>
</table>
That looks perfectly fine to me, but the browser will inject a <tbody>
in there around that <tr>
for you. Optional in HTML, but the DOM will put it in anyway.
Heck, you don’t really even need a <body>
in the same fashion! Jens Oliver Meiert shares more:
<link rel=stylesheet href=default.css>
Some attributes are “optional” too in the sense that they have defaults you can leave out. For example, a <button>
is automatically <button type="submit">
.
Jens further argues that these are almost considered optimizations, as it reduces file size and thus network speed.
Me, I don’t like looking at HTML like that. Makes me nervous, since there are actual situations that screw up if you don’t do it right. Not all file names can be left unquoted. Sometimes, leaving off closing tags means enveloping a sibling element in a way you didn’t expect. I’d even sacrifice a tiny smidge of performance for a more resilient site. Sorta like how I know that * {}
isn’t a particularly efficient selector, but worrying about CSS selector performance is misplaced worry in most cases (the speed difference is negligible).
I actually quite like JSX in how strict it forces you to write “HTML.” That strictness helps code formatting (e.g. Prettier) too, as a bonus.
But hey, a perf gain is a perf gain, so I wouldn’t say no to tooling that automatically does this stuff to compiled output. That’s apparently something HTMLminifier can do.
I am developing a Mega-Menu WordPress plugin for a client. It is involving some inserted
‘s and I noticed that in Chrome (probably other browsers) it would automatically add the closing
‘s in the menu even though the source code didn’t have them there…this did not sit well with me obviously, so I put in the work to figure out the bug that was causing the missing closing ‘s . If I didn’t think to look, I would have probably missed this. This behavior makes it more annoying to diagnose stuff like this.
Looks like it stripped out the div tags in my reply. Oops.
IIRC, XHTML stopped allowing authors from leaving out “optional” closing tags, i.e. if you did it, then your XHTML wasn’t valid. HTML and web browsers may let authors get away with plenty of nasty habits, but it is just not good style, and isn’t worth any negligible performance gain I would say. Consider others who have to maintain your ugly code after you’ve left that job, etc. By omitting closing tags, you can also confuse “pretty-print” tools, if you ever need to use one. Write beautiful code.
I completely agree with Chris. I also suggest my coworkers to always put the
type
attribute in every button, even if it’s a submit button, because it makes it more explicit. Removing unnecessary tags and attributes is a job for a minifier and I’ll gladly let it do it for me :)I remember a time when we didn’t bother closing
<option>
for example.I think it was before xHTML was a thing. xHTML forced us to close our tags (
<img />
,<br />
, etc.). I guess it’s cleaner now, and leaves less room to interpretation.Removing closing tags might reduce bandwidth usage, but:
1) I bet it’s not much after GZIP compression. All those closing LIs won’t be 5 bytes each over the wire.
2) What does it do to the page-parser time? My guess is that it slows the page-parser a lot.
Also, Colin is right – there’s something to be said for legibility.
The weird inconsistencies in HTML make a lot more sense if you think of it in the context of evolution. As what we demand the markup be capable of changes, we act both as the agents of influence and the agents of change… evolving HTML just enough that it adapts to our new needs, but not so much that it becomes something entirely new.
Just as with any biological evolution, this results in leftover… vestigial stuff. Unlike that parallel though we can just drop browser support for those now defunct features so we’re not sitting here wondering what this particular thing is for.
That cleanup does leave a lot of room for inconsistencies though… like how some elements need their closure, some closures are optional, some elements don’t have one at all, and some (optionally) have self-closing slashes.
I think the paragraph example works because nested paragraph elements are not valid HTML, so the browser would know this and close the element before starting a new one for you.
No sources on this, it’s just the way I reason about it
It also makes me wonder if any HTML minifier is using any of these tricks!
Closing list element tags () are optional as well
Remy Sharp, answering why the p tags are like that:
I wish we could disable it, for debugging purpose.
Working on front-end we sometimes see odd behaviour on different browsers.
In most cases the developer made a small mistake (closing tag on wrong loop level etc) and the browsers tend to “fix it” differently.
Than having to prove it’s not a CSS issue can sometimes get cumbersome as you don’t always get to see the original code.
If you use a good validator like CSS HTML Validator then you can set an option to require the optional end tags.
For some reason in the homepage the first example was normalized to include the missing tags.
Question: some HTML minifiers by default don’t remove
</p>
or</li>
. What might happen if they removed those by default?In looking back at the evolution of markup languages, SGML and DTDs gave some life to HTML and its DTD. When HTML 5 came about the DTD was no longer seen as viable.
The ability to read a DTD to infer how the markup is to be applied got buried in the browser.
!–=================== Paragraphs =======================================–>
!ELEMENT P – O (%inline;)* — paragraph –>
!ATTLIST P
%attrs; — %coreattrs, %i18n, %events —
>
“-” start tag required
O end tag optional
https://www.w3.org/TR/html4/struct/text.html#edef-P