React
React Has Been Teaching You Invalid HTML!
Modern JavaScript front-end libraries such as React, with their convenient JSX markup, have been teaching us invalid HTML syntax for the past few years. In this post I will explore what are void/non-void HTML elements and the consequences of using a self-closing non-void element in pure HTML.
HTML5 has a class of elements called void elements. These include:
area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr
You can self-close these elements (e.g. <hr />
), meaning - no additional closing tag is necessary (and adding one is generally considered improper). But what about all the other elements? Can you self-close a span
? a div
?
It seems logical and necessary in today’s JavaScript and CSS focused web development to self-close div
s/span
s. We usually do that when we want a placeholder that would be later hydrated with content from Javascript. Another use case is for styling - a self-closing div
can be sized and given a background image in CSS for example.
Nevertheless this is not valid HTML and the consequences can be pretty dire! HTML parsers (such as your browser) are trying to be extra helpful in this case and interpret the tag as un-closed and nesting everything below it as children of the tag. So you write this:
<!-- ... -->
<div class="placeholder" />
<input type="text" />
<!-- ... -->
And the browser interprets it like this:
<!-- ... -->
<div class="placeholder">
<input type="text" />
</div>
<!-- ... -->
In fact, the W3C’s official HTML validator will show 3 errors if you try to do that:
At the very best, this will just produce unintended markup, maybe some improper styling or some time spent debugging, at the very worst it can lead to errors in production (for example when you replace the contents of placeholder using JavaScript, unknowingly removing all elements below the current “self-closed” element).
By now, if you’ve done this you probably feel bad… but it’s not your fault. Front End frameworks (like React) have been spoiling us for years, fixing our HTML for us and, in the process, teaching us how to write some terribly invalid HTML.
That’s not all, our beloved linter, ESLint, particularly the ESLint-plugin-React, has been auto-“correcting” our code too:
This particular rule react/self-closing-comp
is enabled by default on CodeSandbox.io and Airbnb's ESLint Config. Both very popular.
Conclusion
When writing HTML outside of front-end frameworks such as React, you should never self-close non-void HTML tags. Hopefully something changes - either in React and all the other "convert-to-html" markup in JavaScript frameworks, or on browsers and HTML parsers. Since I personally find self-closing elements useful as containers, I would much rather see browsers and parsers supporting self closing non-void elements, and see it included as part of the HTML spec, but until then, I'll be writing valid W3C HTML.