When Tim Berners-Lee invented HTML his idea was to share documents – scientific papers to be precise. This document shape is still with us after all this time. That's why we have elements like <article>, <aside>, <header>, <footer>, <p> and so on.
This works great for articles and blogs, but the web has changed. Today the majority of what we build are applications, not documents, and the metaphors of documents don’t always fit application interfaces. Carousels, badges, counters, avatars, alerts – none of these map neatly to <article>, <header>, or <p>. Instead, we’ve been shoehorning them into non-semantic catch-alls: <div> and <span>.
<div>s are the duct tape of web development. They:
- Hide the true structure of the UI.
- Depend on fragile, bloated class names for meaning.
- Make code unreadable – it takes mental effort to decode what a Tailwind block is actually doing.
- Encourage short-term hacks instead of long-term maintainable patterns.
The irony is that React developers already know this. They write <Panel>, <Button>, <Logo>, <Nav> every day in JSX. Those are semantic! But paradoxically, the same community often declares that semantic HTML is "dead."
It most definitely isn't. In fact, semantic HTML is more important than ever.
The truth is, HTML and CSS in 2025 are more powerful than many developers realize. Features like CSS nesting, attribute selectors, and custom elements give us expressive, declarative tools that work everywhere without JavaScript or build systems. Put together, these practices feel futuristic – like coding in the year 3000! – even though most of them have been around for years.
That’s why I call this approach HTML3000.
At its core, HTML3000 is about leaning into semantics and writing HTML that describes what an element is, not just how it looks. The key principles are:
-
Use custom HTML tags extensively. No
<div>or<span>. If you feel you need these tags, take a step back and figure out what you actually mean. -
Favor context and nesting over class soup. Remember what the “C” in CSS stands for.
-
Use attributes instead of classes as CSS hooks. Double down on declarative patterns.
-
Start with reusable patterns and componentize later.
-
JavaScript comes last. Focus on structure and styling before behavior.
The goal isn’t to throw out modern tooling. HTML3000 plays nicely with ERB, Hotwire, Stimulus, HTMX, React, Vue, Phoenix LiveView, and more. It’s “just HTML” but written differently.
TL;DR: No.
Custom tags have been allowed since HTML5 was released in January of 2008. You can go ahead and type <my-tag> on your code and it will behave like a <span>.
Any custom tag is by definition not strictly standard HTML – it's custom after all! – but their default behaviour is standardized.
Javascript is only needed if you're implementing interactive behaviours, as usual. Complex elements with all bells and whistles can always be created as web components, but that's not what we're talking about here.
Rest assured these are two separate features: custom HTML tags don't need any Javascript to work. You can simply add them to your code and apply CSS defitions as you would for any other HTML tag.
That's how we're getting rid of <span> and <div> in favour of fully semantic tags to describe applications UIs.
- Readable code – you know what’s on the page without tracing through CSS classes.
- Maintainability – meaningful tags are easier to refactor and extend.
- Consistency – naming things pushes you to think in component patterns instead of ad hoc markup.
- Freedom from bloat – less dependence on utility libraries to patch over missing semantics.
Using semantic, declarative markup makes code easier to read, reason about and maintain. Instead of wading through endless utility classes you see the actual structure of your UI. Consistency emerges naturally and you’re nudged toward building standardized, reusable components.
Is this a design system? Nope! But any serious application needs consistent UX, and HTML3000 encourages you to think in components from the start.
You don’t need to rewrite everything overnight. Even small steps like replacing anonymous <div>s with meaningful custom tags can dramatically improve readability. You can go further by experimenting with attribute selectors or phasing out class-heavy patterns where they don’t serve you.
- CSS Classes Considered Harmful – the article that sparked much of this thinking.
- Why Semantic HTML Still Matters – a reminder of the foundations we’ve drifted from.
- Just use a button - Don't use a
<div>to do a<button>'s job. - PicoCSS – a CSS framework that embraces semantic, class-less markup.
HTML3000 isn’t a framework, library, or package you install. It’s a set of practices that rediscover the expressive power of HTML and CSS – tools that already run everywhere. It’s about writing code for the web that’s semantic, declarative, and future-proof.
If the early web was about documents and the last decade was about JavaScript-driven UIs, perhaps the next step is recognizing that the simplest building blocks – HTML and CSS – already take us surprisingly far.
HTML3000 isn’t just a practice. It’s a promise: no more meaningless markup. Because the future of the web shouldn’t be meaningless.