Custom HTML Elements and Page Layout: Past, Present, and Future
As we prepare to enter the year 2021, allow me to make a bold statement: it’s totally unnecessary—perhaps even an anti-pattern—to use
<span> tags in your HTML.
Now before you shake your fist at your smartphone or computer screen and write me off as a veritable nutcase, let us briefly review the history of HTML.
How We Got Here
HTML stands for “HyperText Markup Language”. It was originally designed as a text format for sharing academic materials. It had virtually no styling abilities, and in fact didn’t even ship with a proper image tag.
Throughout the 1990s, as Netscape rose to prominence and the internet transitioned from higher academia to the public stage, the race was on to make HTML ever more capable in terms of visuals and interactivity.
HTML gave way to DHTML—Dynamic HyperText Markup Language. Netscape had their own idea of how DHTML should work, called the LAYER tag. But that tag never achieved widespread adoption and instead we ended up with a potent combination of CSS and…the DIV tag.
From the HTML4 introduction to DIV and SPAN dating from 1999:
The DIV and SPAN elements, in conjunction with the id and class attributes, offer a generic mechanism for adding structure to documents. These elements define content to be inline (SPAN) or block-level (DIV) but impose no other presentational idioms on the content. Thus, authors may use these elements in conjunction with style sheets, the lang attribute, etc., to tailor HTML to their own needs and tastes.
Suppose, for example, that we wanted to generate an HTML document based on a database of client information. Since HTML does not include elements that identify objects such as “client”, “telephone number”, “email address”, etc., we use DIV and SPAN to achieve the desired structural and presentational effects. We might use the TABLE element as follows to structure the information…
While it’s true you could use
<div> tags in the late 90s, it was slow going in terms of page layout because of the limitations of CSS itself. Many website designs used tables instead, or even resorted to proprietary plugins such as Flash.
But eventually the industry transitioned away from tables, Flash, etc. to “float-based” layouts (and since flexbox and grid)—and the tag most commonly used to hang styles off of remained the most generic tag of all: DIV.
However, that’s not the end of our story! Concurrent with the developing power of CSS to handle complex page layout was the development of XHTML. Everyone in the decade of the 2000s went bananas over XML, and the web community was no different. XHTML was a change that saw HTML switch from being based on SGML (Standard Generalized Markup Language) to being based on XML (eXtensible Markup Language). XML was envisioned as providing a newer/easier/better method of defining new document types/schemas than its predecessor SGML, and one of the benefits of XML provided to XHTML was the ability to mix in other XML schemas. In other words, you could extend HTML itself. (Read this W3C documentation on XHTML modularity.)
Yes indeed, you could add new elements to XHTML using externally-defined DTDs (Document Type Definitions), turning HTML itself into nothing more than one building block among many other building blocks for a bigger, more expressive, more structured, semantic web.
Only that never happened.
XHTML was eventually rejected as The One True Path Forward for the web. In its place, we got HTML5, and HTML5 defined the decade of the 2010s.
Unfortunately, in weaning web developers back off of XML, the modular nature of XML largely was lost, and thus enthusiasts of expressive, semantic markup were relegated to the fringe edges of hypertext theory.
Or were they?
Introducing Custom Elements
While everyone was rocking their DIVs and SPANs for accomplishing, well, pretty much anything and everything in HTML page layout, a curious new spec emerged—largely in parallel to HTML5 itself.
First drafted in 2013, the Custom Elements spec defined how browsers could “upgrade” a custom element (recognizable by its hypenated nature…i.e.
<my-tag>, rather than simply
Because browsers already allowed virtually unlimited tag names!
Sure, it wasn’t “valid” HTML by any means, and you might occasionally run into the odd side-effect, but because browsers were always very liberal about how they interpreted an HTML document, there wasn’t really anything stopping you from using
<paragraph> instead of
<navbar> instead of
That’s right, all that’s required to add a custom element to your HTML5 document is…to add it. 😄 Here’s how you do it:
Take a bare HTML5 page:
<!doctype html> <html> <head> <title>My HTML Page</title> </head> <body> </body> </html>
<text-greeting>Hello World!</text-greeting> as a child of
<!doctype html> <html> <head> <title>My HTML Page</title> </head> <body> <text-greeting>Hello World!</text-greeting> </body> </html>
Er, So What the Heck is Special About DIV Then?
The only obvious difference between a custom element and a
<div> tag is that custom elements are styled
display: inline by default, just like
<span>. So in that sense, your use of
<span> and a custom element is completely interchangeable.
To make your custom element behave like a
<div>, simply style it with
display: block, and voila! Now your custom element is equivalent to
<div>. It’s that simple.
Also, unless you do use the custom elements registry and define a web component, a custom element will be of the
HTMLSpanElement. That’s pretty much it.
The answer is…inertia and ignorance.
Everyone’s already been trained to use
<span> tags everywhere, so that’s just what we do. It’s what everybody does. Nobody ever got fired for adding a
<div> tag to a React component or an ERB template or a WordPress theme. And if nobody tells us there’s a better alternative, we’ll never change!
But whatever the reason, I’m here to tell you that right here, right now, you can use the Custom Elements spec to your advantage and eliminate virtually all of your DIVs/SPANs in favor of expressive, semantically-useful custom elements.
Don’t believe me? Well, I’ll let you in on a little secret:
This website is DIV-free. 🤯
That’s right, all the
<span> tags are gone. (Well, 99.9% of them anyway.) Go ahead, view source. I dare ya. Look in your dev inspector. It’s custom elements (and sure, plenty of regular HTML5 elements) all the way down.
Not only that, but I installed the
linthtml linter as part of this site’s build process so that you can’t add any new DIVs/SPANs unless you explicitly bypass the lint rule. Excessive? Probably. Unwise? Maybe. But I’m here to make a point. It’s time to ditch your ancient 90s-era markup and teleport into the future. Custom elements (as well as web components proper) and here and they’re here to stay. We can finally have our HTML cake and eat XML-like extensibility too. Finally.
Keep reading for “part 2” of this story where I do a deep dive into how I converted the Bridgetown website over to using custom elements along with a few neat tips & tricks along the way for organizing and styling your custom element library.