Heading image for post: React Has Been Teaching You Invalid HTML!

React

React Has Been Teaching You Invalid HTML!

Profile picture of Dorian Karter

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 divs/spans. 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>
<!-- ... -->

Broken Assumptions

In fact, the W3C’s official HTML validator will show 3 errors if you try to do that: W3C HTML Validator

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.

React - What have you done to my HTML?

That’s not all, our beloved linter, ESLint, particularly the ESLint-plugin-React, has been auto-“correcting” our code too:

ESLint in action

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.