‹ go back

HTML Day 2024.

Published 16 July 2024 at Yours, Kewbish. 2,805 words. Subscribe via RSS.


Introduction

July 13th last week was HTML Day 20241. HTML Day is a community-organized event where folks gather around the world to freewrite HTML. The meetups seem to take place generally in parks or beaches (so no Internet access) with fun prompts like “make a website inspired by the sounds you hear” or “make a website inspired by your favourite, lesser-known element”. Some folks even handwrite their HTML — note that the event descriptions state to bring a “HTML-writing device” or “something to write HTML on” and not “a laptop”. The intent is less of a “Google all the things and make a technically challenging website” and more of a “go back to the roots of raw HTML and have fun” vibe.

I was planning to go to my local HTML Day as well, but it was a bit of a transit trek. By the time I’d gotten to one of my transfers, I decided just to head to a library and have my own little HTML day instead. Armed with a slice of surprisingly high-quality carrot cake from a cafe nearby, I sat down for an afternoon to hack away.

I’d originally come up with some slightly cursed ideas with raw CSS: building a Shamir Secret Sharing tool with server-generated CSS files that could be recombined to regenerate the secret was my initial plan. I’d also thought about making some kind of HTML emoji canvas with bufo emojis as a little puppet show. Going back to my spaced-repetition enjoyer roots, making a CSS-based Leitner system was on the list as well. I wondered if I could somehow rig up a hash function in CSS to get to a sort of blockchain, and I considered using CSS as an API as mentioned in this CSS Tricks post. However, these ideas all hinged around abusing CSS instead of HTML. It’s the one thing about HTML Day: HTML is supposed to be the star of the show.

I was feeling pretty uninspired at some point, so I looked to the html.energy page for past event prompts. I found a pic in their event gallery that mentioned finding a lesser used HTML element and making a page around that, and I started thinking of older, retro (to me) tags like <marquee> and <blink>. They’re what I think about when I imagine the Internet of the 90s/00s (please keep in mind I was not around for said Internet era): the “the more I know”-esque, Neocities-core, loud and gaudy and interactive pages. I don’t know if these tags were ubiquitous then, but they’re pretty well-used now by tongue-in-cheek people looking to recreate that aesthetic.

Unfortunately, they’re also deprecated. In particular, <blink> isn’t even implemented in modern browsers anymore — it has to be recreated via a CSS animation. I started thinking of other tags that had seen better days and were no longer implemented, and I set out on a quest to find the weirdest tags that I’d never heard of and bring them back to life via a little extra CSS or JS. I started envisioning a circus with a freak show of resurrected tags brought back from the dead, but not quite behaving the same way: think PT Barnum crossed with Frankenstein.

The result was 1pt bar<number>'s travelling circus: html element freak show' — an ASCII-art heavy little page showing off a few freaks of Internet nature. In this post, I’ll expand a little on some things I learned while making the page, both about the tags themselves and the Web in general. This post is full of links to obscure pages and jumping-off points for further reading, and I hope it’ll spark some rabbitholes of your own!

Here’s an embed of the site if you’d like to check it out:

The <blink> tag used to, as may be obvious, blink text. According to this article by Fast Company, it was the result of a joke turned challenge: engineers working on Lynx were laughing at some of their wilder ideas for the browser, seeing as it couldn’t even blink text. One of the engineers took this as a dare, and returned the next morning with a working blinking tag. It was never standardized, and few browsers supported it, but up until 2013, Firefox supported it, and Google’s WebKit fork was even named after it. There was also a text-decoration: blink CSS declaration available, but it’s also deprecated and usually not supported.

One reason for its removal seems to have been accessibility concerns: the blinking makes it hard to read text and could potentially trigger seizures for those with epilepsy. But the other reason cited is its lack of standardization.

Part of the beauty of the web is standardization: for the most part, you can trust that things will render the same across browsers. However, there’ll always be little differences, even in well-specified standards — how else would we be able to do browser fingerprinting even without user agent headers? It makes sense that browsers would want to reduce extra surface area for divergence and focus on the specification, especially since you can recreate its functionality with the rest of the standard.

To implement the blinking eye on the page, I used a looping CSS animation that would toggle visibility: hidden on and off. visibility: hidden differs from display: none in that it keeps the element’s block present, so it doesn’t shift around on the page, but stops rendering the element itself.

<keygen> and Early-Web Auth

The <keygen> element was used to generate a public/private keypair to be used in forms to validate the server’s response (yes, back when PHP was all the rage!) Here’s a video I found of the tag: the ‘High Grade’ refers to the strength of encryption via the length of the generated key. This page lists 2048 as the ‘High Grade’ encryption, which isn’t nearly as low as I thought considering the feature was implemented well before 2016.

When a form containing a <keygen> had its submit handler called, a public/private keypair would be generated locally. The private key would be kept local, and the public key sent to the server and signed by the server’s own certificate to create the client’s certificate. This was later used to authenticate the user. Most (then-) modern browsers implemented <keygen>, including Netscape, where it originated, Opera, Firefox, and Safari, and the feature was used in quite a few places, including in early online banking. However, IE notably decided not to support the feature, which might have led to its eventual decline, deprecation, and removal from the HTML standard. This SE comment seems to imply that client certificates were all the rage before being supplanted by passwords — it makes sense, since early Internet users were likely fairly technical in order to onboard in the first place, but this demographic and thus this need for easier-to-understand auth shifted as adoption among the general public increased. There’s a very in-depth doc here that explains a bit more of the background context.

If you want to really fake a <keygen> element, this blog post shows you how to do it. Surprisingly, as of a few years ago when this article was published, some CAs still required the use of a <keygen> element, and their official guidance was to install and use IE11 to work around the tag’s removal in modern browsers2.

But if you’re happy just making a little <keygen> that displays an ASCII key when clicked, as I’ve done on the page, it’s nowhere near as complicated. I felt like using JS was a bit too easy and besides the point of HTML Day, so I made a CSS-only click handler. The TL;DR is that we can wrap the <keygen> element in a <a> with some href="#target", and when the <keygen> (really, the <a>) is clicked, #target is appended to the end of the URL. Interestingly, there’s a pseudo-element :target that allows you to style tags that are targetted, so I simply added a <span> with a key symbol and set that to display: block only when the element is targetted. The downside of this is that it’ll jump to said target, causing a bit of a jarring visual effect, and if #target is removed from the URL, the key symbol no longer displays. I figured it was enough of a proof-of-concept even with these rough edges, though. This DigitalOcean post has more details here.

DYK: There’s a <V> Tag?

There a few special-purpose text formatting tags like <big>, <center>, <s> (strikethrough), and <u> (underline) that were also deprecated. Scrolling down this list should give you a sense of the deprecated presentational tags — look for the red trash-can icon beside each element’s name.

I also wanted to call out a counterexample of these text formatting tags getting deprecated: <small>. <small> was supposed to be the counterpoint to <big>, but isn’t deprecated. This is because of its reclassification as a semantic element: the Mozilla docs state that it’s intended to represent copyright and legal small print, and importantly, it represents these things independently of its styled presentation.

This is exactly the reason these tags were deprecated in the first place. While these presentational tags were part of previous HTML standards, they’ve been deprecated because they focus on the the styling of some text instead of its semantics. Note that <b>, which wraps bold text, is by default rendered the same way as <strong>. However, again, <b> marks the content just as bold, whereas <strong> denotes some sort of emphasis. This gives the user the freedom to represent the semantics however they want: perhaps a user likes to see <strong> text italicized in a different font instead3.

If you’re getting tired of all this deprecation and thinking “to hell with the standard, I just want to have have presentational elements!”, go right ahead. The proper way to create custom HTML elements is with JavaScript and the Web components API. You can use templates and slot in your own content and even register it for use in HTML docs. Custom elements are very powerful because they allow you to hook into different lifecycle events, like attributes changing.

One glaring problem with custom elements, though, is that they must follow the standardized naming convention. This forbids you from using a custom name like <leet> without a hyphen, making it obvious that you’re using a custom element. This is fine for most (all) use cases, but for my HTML day page, I really wanted the markup to be as clean as possible and avoid relying on JS.

So imagine my surprise when I tried just writing <blah>content</blah> and adding a simple blah { color: red } style and seeing the text brighten up on my screen. I didn’t realize that browsers would parse this as valid HTML (they’re instanceof HTMLUnknownElement). You can style these fake tags just as you would normal HTML tags, as long as they’re accepted as a tag name: underscores and hyphens in the tag name work, but periods don’t. I didn’t look up the exact rules here, but I’d expect you can probably find more restrictions.

On my HTML day page, I’d already mentioned <s> and <u> as deprecated tags (they aren’t, see footnote)4, and I just applied a little text-decoration: none to them to remove their strikethrough and underline respectively. I also thought it’d be funny to round out the alphabet here, with the fictitious <r>, <t>, and <v> tags. Of these, I think the <v> element is most interesting: it represents a little graffiti tag (pun not intended) that has blue Comic Sans (or whatever your browser default cursive font is) angled on top of the existing text. I did this via a :before pseudo-element: I added v { position: relative } and v:before { position: absolute; left: 0 } in order to get the pseudo-element to display directly on top of the <v>’s content. Then, by setting the :before’s content property, I was able to add the extra graffiti text. Finally, I added a little extra styling to rotate the text as if it’d really been tagged onto the underlying content: I didn’t expect transforms to work on pseudo-elements properly, but transform: rotate(25deg) did the trick. In retrospect, it might have been nice to add some drop shadows to make it seem like the ‘paint’ was dripping, but an effect to explore for later.

Conclusion

I came into HTML Day intending to hack together a funny page and move on, but I’ve been able to learn more about how Web standards have evolved and a bit more about the history of HTML. As time went on, I can see the decisions to shift responsibility from more static technologies (HTML) into more dynamic ones (CSS, JS). I’ve always thought of these three main Web languages as all wrapped up, listed as one big slash-delimited acronym on my resume. It’s been interesting to reflect on the patterns of deprecation and how they’ve very intentionally decreased possibilities for doing the wrong thing while separating each language’s responsibility more clearly.

At first, coming into this whole deep dive, I’d thought that deprecating tags was more restrictive, since it was encouraging people not to use more varied and diverse elements. Now, I think culling out-of-scope tags and focusing on these very delineated responsibilities is more freeing. The example that cemented this for me was that having clearer semantics, not mixing in presentational tags, and not implementing non-standard behaviour can allow users to specify how they want to view their semantics: for example, bolding an <em> tag or listing all <big> text in a different font style. By promoting clean semantics and removing possibilities for self-contradiction within the spec, users can trust the standard, and by extension their browsers, more.

Besides really enjoying the history, I learned that what I’ve learned about HTML from modern web development via React et al. hasn’t even scratched the surface of what (raw) HTML has to offer. I’d previously considered myself fairly well-versed in HTML and CSS, but I’ve realized that I’m severely lacking in more of its history and its weirder corners. It’s nice going down a little rabbithole, since the standard is so sprawling and there’s so much to specify: there’s bound to be interesting edge cases.

This exploration also puts into scale how complex web browsers are, yet how basic an initial set of tags that covers most functionality can be. In everyday dev, I probably only use 10-15 tags, whereas there are 142 defined in the HTML5.2 standard and probably many more non-standard ones, like <blink>. There are books covering how to build your own fully-fledged browser, and I’ve been thinking of skimming it to see if I’d find web browser internals interesting. Once I’d learned that <blink> wasn’t implemented in modern browsers, I was considering having my HTML Day project being creating a custom fork of Chromium that automatically injected a CSS blink animation, but I figured with the time I had (and the battery, since I forgot my charger) it was something to leave for another day. It might be easier to figure out how to implement <blink> with a smaller browser like the one I’d build with browser.engineering, so I might take a look.

Writing this little summary and building a small site was very fun. HTML Day was a well-timed excuse to build something for the sake of building it, with some loose constraints that were a great forcing function for my creativity. I’m excited for the next events in August for HTML’s birthday and what I’ll learn there. Hopefully I’ll be able to make it in person this time — I saw some Exquisite Corpse-inspired and handwritten HTML shenanigans that’re really making me look forward to it.

If you didn’t take a stab at anything for HTML Day, I’d encourage you to find one of the deprecated tags in this post (or one of the supported ones in this list) and try to figure out the weirdest edge cases and quirkiest uses you can think of for it! What you learn might just <em>aze you.


  1. As far as I can tell, July 13th isn’t related to the history of HTML in any way, so I’m assuming it’s some arbitrary date picked by the organizers for people around the world to freewrite HTML. They also have an August series of events for HTML’s birthday, but it’s hard to pinpoint an exact date of HTML’s launch, at least according to a cursory Google. ↩︎

  2. Arguably a sign that you might want to use a different CA. ↩︎

  3. I’ll also note that <b> is not deprecated in HTML5 anymore, and has specific use cases as the “Bring Attention To” element↩︎

  4. While writing this post, I’ve discovered that neither are actually deprecated, which is a little embarrassing. ↩︎


‹ go back