A Better Way to Write HTML for Modern Apps
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>.
Why <div>s Are Harmful
<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.
HTML in 2025: Underused and Undervalued
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.
The Principles
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.
Examples
Fixing the Tailwind website example
See the Pen HTML3000: Fixing the Now Playing Tailwind example by Fabio Neves (@fzero) on CodePen.
A javascript-free badge component
See the Pen HTML3000: Badge example by Fabio Neves (@fzero) on CodePen.
What You Gain Without <div>s
- 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.
Why This Matters
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.
Adopting HTML3000 Incrementally
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.
Further Reading
- 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.
Looking Ahead
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.