All the issues with HTML, the Frontend land where time stood still
Foreword: I have a fairly successful article about HTML from not so long ago. From then to now I definitely changed my mind about it.
In a previous article about our web development stack, I talked about our approach to the Web nowadays: to not question the HTML + CSS + JS(DOM) stack as it is and focus on build tools around the limitations and quirks of that stack. In a day and age where computers got quite powerful and browsers’ engines are well optimised, the final generated code (that is the one that actually runs) becomes hidden to developers below this layer of abstractions and then gets relegated to a secondary role.
To get a better broad view of this, I wanted to deep dive into what are the actual problems with the aforementioned stack. This is not so obvious to see, as Frontend developers, for the reason I just mentioned: we have been made oblivious to the raw reality by these tools (like packagers, builders and JS frameworks that generate compliant markups). In my opinion though, even though tools and browsers should be praised for their great job, we should not forget we are dealing with a chaotic stack and, particularly for HTML, with the clumsy extension of a markup language devised in the 1980s.
HTML was an outstanding idea back in 1989: an accessible markup, created for the exchange of brief academic papers, but with the revolutionary addition of links. This single feature (which is fundamental to the concept of “web”) would be the key superpower that allowed the Web to have its commercial boom some years later. The new commercial websites from the mid-1990s had visual requirements very different from academic papers, though, and since early on HTML was exposed in its limitations (I remember reading a small rant against HTML in a Geocities website from around 1998).
I want to be fair to whoever was in charge of the early Web standards, though. They knew that something was wrong: CSS was created to counter HTML limitations. I cannot help but think of this as a bad move… but let us keep this for the next article. For now, let’s focus on what HTML has: the good, the bad and the deprecated.
Its syntax was never the issue: the basic foundation of HTML syntax, which was used later for XML (and XHTML) is flexible and matches fairly well its tree-like structure. The fact that many people in the JS community choose to use JSX, which is a JS dynamic lookalike of HTML, tells me that it somehow works. I would just say, just because I tend to be too opinionated, that non-closing tags add an unnecessary cognitive load to the markup (you have to remember which ones are them) and self-closing tags are much better.
I like the syntax extensibility and this separation between properties (parameters) versus content is well resolved and affordable. Although it is not very well suited for free-formed data, as proved by XML being largely replaced by JSON or YAML, it fits very well indeed for placing elements hierarchically on a visual application.
Headers and headaches
Let us focus on just the non-content tags now, or the “headers”. There are some nice ideas there: preloads, meta tags, even the page title itself (it belongs to the small group of simple things that just work). Of course, not everything is beautiful: some ideas got too old and I would like to go deeper into some of them.
First, let me take one elephant into the room: why HTML doesn’t expose its version anymore? I am well aware that versioning before HTML5 was quite clumsy but it sounds like quite an immodest thing to assume the latest version of a technology will be the “last” or the “definitive” like it was done with HTML5 and its <!doctype html>
that does not bother to mention the version. Even in the HTML specs it is stated that “DOCTYPEs are required for legacy reasons”, which is not entirely true to the original view that doctypes would communicate the markup version. In the end there was this normative view with HTML5 that JS and CSS would expand but HTML would be somehow good enough forever.
Wandering into the land of largely ignored tags, we could talk about link
and the lack of clarity on its core purpose, especially when confronted with meta
and style
. It is meant to be used to declare the CSS style file, although there is also style
for that, which adds to the confusion. It is also used for the icons on the page (favicons) and possible app icons. With new “manifest” files which can include icon definitions and also when taking into account that favicons can be safely omitted from the HTML header and work as long as the naming is standard, link
can become a soon-to-be-deprecated tag. Also, as a side note, it makes me wonder why the tag for the links in content is called a
and not link
, while this tag we are talking about is not that much of a “link” as it is more like an external asset.
I praise the existence of meta
though. It is a tag that opens the door for a more future-proof markup and it has uses today for important optional features like preloading assets. HTTP-equivalence with the http-equiv
parameter though is mostly deprecated and can be removed in favour of a simpler approach for overriding CSP headers, for example. Another thing that could be simplified is establishing the charset. Back in the day, when simple ASCII was the default charset and people like me had to be going back and forth to different charsets to read content in their languages properly, this declaration was important and because of that, it could be set in at least two ways inside the HTML header. Today most people around the world benefit from the Unicode standard on the Web, with charset issues being largely a relic of the past. Even though overriding this should be allowed, content-type
should be buried together with “ascii” encoding.
The meta tag for refresh
should be also buried. It is useful only in times when people wanted to force page redirections and neither JS nor backend languages were even a thing yet.
Meta tags usually are there to mark things that the user of the website or app should not care about and, in that, tags which add information that could be relevant to code readers are also fine (as long as they are not enforced). There was a push on the early days of the Web for developers to insert information on highly innocuous meta tags like author
and generator
which didn’t catch on and two standardised types of meta tags born with the very best intentions in mind ultimately were made deprecated in practice: description
and keywords
. In the beginning, manual search engines like Yahoo and early crawlers like AltaVista took the content of those tags to index the websites, but soon enough it became clear that they could be very easily abused with malicious content just to generate more traffic. By the time Google was created, those tags were already known to be a very unreliable source of information and their use was ultimately relegated to rogue (probably useless) SEO practices, so much that today they can be safely ignored.
To sum up for now, I would say the problems with the HTML non-content features are:
- Not featuring versioning information on the markup itself;
- Having way too many legacy features, even those that are not officially deprecated yet (like meta
refresh
anddescription
); - Having unclear purpose and bad naming (talking about you
link
, sorry).
Let us talk now about the content (body) tags.
HTML, sorry, but your body is a mess
A semantic issue
I think that a big portion of the issues with HTML comes from the fact that there are just too many deprecated features still active and even being used. One possible theory on why this happens is because of cognitive overload: there are just too many tags in general and people, even the smartest ones, just give up keeping track and use whatever they know that works — no wonder why div
and span
are so popular. It sounds nice to have almost 150 tags when you are a developer that first came to know the possibilities, but when you are revealed that most of those tags only differ semantically (that means, they have no special functionality) and a lot of them are in fact deprecated and replaced by functionally identical versions (think of b
and strong
) this starts making sense.
As mentioned in my previous article, the migration from HTML to a media for content only, with CSS taking over presentation, was well-intentioned but not very well understood and it did not feel natural at all. The problem was not that people kept using b
and i
and center
for a while, neither that people did not know how to use article
or aside
, but rather that people started using semantic HTML because the felt they had to do so, only because Google made websites rank better for a while with it.
Eventually SEO became a non-issue for this now, because Google already has enough intelligence to infer things without caring too much about semantics on the markup. The reason why Google dropped it as a serious ranking measurement is also roughly the reason why everyone should drop it: nobody gets it right — which goes well with what I said before about there being too many tags on HTML. Google users want to find content and Google want its users to find this content, and whether or not the content is there does not depend at all on whether the markup is a sea of div
s or if it is all tidily semantic.
The Web was always largely “uncompliant” to semantics because, well, we are humans, and to force using completely right elements that are subtly different in meaning but all identical in functionality is unrealistic. It would be much better to work on the actual content and make smart tools like Google take care of the rest and, also very importantly, support accessibility tools to improve their intelligence so they can infer more information from the set they are bound to have in real-life, whether enforcers want it or not—or do you really think people get those aria-*
parameters all right?.
In the end, especially in the age of AI, we don’t need semantic HTML tags. For example, we don’t need a header tag when we can infer that some text is a header when its element has a font size bigger than the rest and it is placed before some other elements or text. Having a header element as a style shortcut is another story, but even that would be ideally unnecessary for markup code like this. Another example: it is absolutely clear where navigation menus are on a page if you look at a normal code, even without specific tags. Google does not have their AI at such a high level to struggle with things like this, and neither should screen readers. I am not saying that elements should not have any kind of optional helper meta information to guide screen readers or whatever else, but I am adamant in saying that complex mandatory rules are not going to work with most developers.
The missing point of semantic tags becomes more obvious when we stop to think about all quirks and the overall questionable naming among semantic HTML tags. For example, nav
is a tag that is recommended for what is usually called “breadcrumbs”, but not for navigation menus, which should use menu
but also ul
(unordered list, on older tag) is “kind of allowed” as nobody really uses menu
. Also, someone may stumble on a tag called menuitem
thinking it is an ideal child for menu
, but no, it is only one of the many deprecated tags that are just lying there…
One other case, this time with elements that bear actual functionality: HTML had in its early days a tag image
, supposedly an alias for img
but this alias was made deprecated and now some browsers render an image for this tag, while others don’t (I guess because many people may just write image
accidentally, as it feels very natural to do so). To make it all worse we also have picture
, and what is the difference between picture
and img
(and figure
too)? There are differences, for sure, but they are not affordable, so in practice developers just use what is more at hand, usually img
.
Which elements used in the HTML body (other than the form ones, which we’ll talk about later) we could consider useless then? Well, most of them, as either:
- they are created for all the edge cases of building a semantic-driven markup:
abbr, address, article, aside, caption, cite, code, data, dd, del, details, dfn, dl, dt, em, fieldset, figcaption, figure, footer, header, ins, kbd, label, legend, li, main, mark, menu, nav, output, p, picture, pre, q, samp, section, small, strong, summary
- they are replaceable by attributes on a generic element or for generic elements with custom or special style definitions:
a, bdi, bdo, blockquote, h1...h6, meter, progress, rp, rt, ruby, sub, sup, wbr
plus all list elements (ul, ol, li
) and all table elements (table, thead, tbody, tfoot, tr, th, td, col, colgroup
) - they are deprecated, heritage from a time where HTML was designed to go in different ways:
acronym, applet, area, b, base, bgsound, big, blink, content, dir, embed, font, frame, frameset, hr, hgroup, image, isindex, i, keygen, map, marquee, menuitem, nobr, noembed, noframes, object, param, plaintext, rb, rtc, s, shadow, spacer, strike, u, xmp
A lot of elements on this list, right? Of course, this is just an opinion, but to me, this shows how much useless information we carry on our heads when developing websites. The last group are the ones I care the less, as they are meant to be dead anyway: should HTML have some usable versioning we would never have to hear from them anymore. The first group is also clear in its status, for the reasons already discussed about semantics. The ones in the second group bring some functionality and/or style out of the box conflicting with features already there in JS or CSS. There is also the curious case of wbr
, which can be actually replaced by a character, ­
.
Some relevant insights arise when going through this list: links (a
) and button
s (from the “button” type) can be seen as respectively “inline” and “block” ways of having links, either for other websites or as programmatic click event triggers, so in theory, there would be no need to specific elements for them as long as links could be triggered from generic elements, which sounds to me quite feasible. Also, table elements are strictly not needed because they can be now done using CSS grids in a fairly flexible way.
Forms and limitations
Forms are, without a doubt, one of the most important aspects of HTML now. Today, though, if given the option and if time allows, developers usually prefer to redo these controls from scratch or they use libs such as Bootstrap that do it. To achieve a native-looking select
, for example, one could have a generic box with a border and background and a separate menu box with options shown on demand. With so much boilerplate and logic involved there, why do people bother? Because native form controls are not flexible enough. Entering the half of 2021 and we still have to hide the inflexible and inconsistent visual implementation of <input type=file>
to have a workaround built with JS, that usually does not do much other than a “virtual” click on the hidden element using a more flexible element as façade.
Looking at proposed elements like dialog
I see HTML sometimes going in the direction of mimicking frameworks. If that is true that they could mimic a common framework functionality to allow editing inside form controls using slots, maybe using the same slot
tag that is available now to use for Web Components inside template
, which would be an “entry point” to various aspects inside elements where some inner points of it can be replaced. For example, select
could have the options completely free to style via a slot, or validation messages on fields can have more flexibility to be displayed, elements like progress
or the range type input
can be made useful and so on: the possibilities are vast.
Finally, on forms, I should moan again about naming: having so many different implementations under the same tag, input
, feels extremely wrong to me, especially with other controls that also input things having other names (select
, textarea
). Also, it puzzles me how there is a submit type input
and also a submit type button
and an image type input
that acts as a submit too. This is what happens when standards are not reviewed.
Other considerations
The element canvas
, to me, is a case of a technical choice going too far of its boundaries: we don’t really need, conceptually, an element to expose a specific JS functionality, as special as it may be. In other words, canvas
doesn’t make sense in the context of HTML, as its result is not a special type of content, on the opposite: it outputs just a plain ol’ image. Ideally, it should be exposed through exactly that: an image, or at least a generic box. Either would suffice as an element to serve as a placeholder, and all the logic is completely independent of the markup content, so no need to have an element for this.
iframe
s were very successful back one or two decades, but in our current context, they bring very little value while being security and privacy nightmares in potential. On the other hand, portal
s (basically non-interactive iframes) can be useful and much less of a risk, although their use is much more restricted and not primary in concern for current Web apps and pages.
One brief word about attributes (also called properties, or parameters): their definition, which is an important part of HTML, often suffers from the same illnesses as the elements themselves, with many deprecations, inconsistent naming conventions and attributes that are simply not useful, adding to the immense cognitive load already mentioned. Examples: we have type
and inputmode
for input
fields, one for the actual data and the other for the “mobile keyboard”. A pointless redundancy, that should never have happened.
The generic elements strike back
They didn’t have to have those names: box
or block
would be much better than div
(born as “page division” by the hands of Netscape) and, well, any name could be better than span
, which just keeps reminding me of Monty Python. The important point, though, is that most of the content of any existing website or web app can be put on those two tags, especially div
, other than very specific up-to-date browser functionalities like picture
, video
, audio
and form controls.
These two generic elements, in my view of an ideal world, could be as effective as semantic elements by having all kinds of optional information that the developers judge to be relevant, preferably in a meta attribute. In an edge case, a “box” could have some metadata saying that, for example, the element is “not meant to be read” or “presentational” and the tools that interpret the markup would do whatever they wanted with that info.
Like it was said before, semantic tags like aside
are not being used properly by too many of the web developers, and because of that these tags should go. Blaming developers for missing the marvels of semantics is the wrong attitude. Instead, having easy to follow standards and extend them in free and optional ways (for the tools that may read the code) is always a better way to go than forcing a whole class of people to know by heart a list of hundreds of tags almost identical and expect them to do it always right.
In summary, I would say that the problems with the HTML content (body) elements are:
- The unbelievable number of deprecated elements lurking like ghosts;
- A significant number of functionally innocuous elements with subtle and arguable differences between themselves, built for the conceptual vision of a “semantic Web” that is both misguided and unattainable;
- For the same reason above, developers get admonished for using
div
andspan
, which are the obvious choices most of the time; - Having some elements that could be better replaced by CSS and basic parameters, including the ubiquitous
a
; - Having elements that never made sense conceptually like
canvas
; - Form elements that are dear to developers but, at the same time, bypassed whenever possible because of poor customisation possibilities;
- Standard attributes that are often useless, and definitely too many;
How I would change HTML, if I could
If magically imbued with a power to change unilaterally HTML I would, first of all, humble this markup by rescuing versioning, in a sensible and simple way like <html version="6">
.
Then, free from the zombies of deprecation and also without commitment to semantics, I would ditch all elements but some:
- On headers:
meta, title,
maybebase
- For content,
div
andspan
, basically all the Web needs for simple content (possibly with name aliases that would make those tags even better); also media tags:audio, video
(andtrack
, a complementary for them) andpicture
, optionally with animg
-like short syntax; - On forms:
form
,select
,textarea
and mostinput
types, but with their own elements and not under the “umbrella tag”input
(grouping only the text fields:text, url, email, number, password, search, tel
). - Basic structure:
html, head, body, script
. There is actually a deeper discussion that I intend to have on subsequent articles about the entry point of a web app or website, but for now let’s keep it like this.
For form and media elements, I would definitely implement slot
s on those for better customisation.
Finally, about attributes, I would ditch a whole lot of them, including the beloved aria-*
ones, for reasons already explained above. I would possibly add a highly optional meta-*
instead, without any sort of constraints (like data-*
but meaningful for tools like crawlers and screen readers).
Conclusion
That is it for the HTML. I apologise for the length of it, I know it sounds like a lot, but most of the issues with it come from the lack of maintenance and innovation, which was a conscious choice made when HTML5 was first specified, more than 13 years ago. In my view, this choice is unfortunate and HTML should have been rediscussed since then, in the name of all developers’ long-term sanity.
I also am aware that this old and weary markup language is just the least important part of a stack that gives developers a lot of unnecessary headaches. To understand this context better I will cover next the one that I judge as the most difficult of all: the cascading style sheets, or CSS.