← All posts

HTML Is Enough

· 3 min read
htmlcssopinion

HTML Is Enough

Fun fact: you can build a website with only HTML and CSS.

And no, this isn't some "JavaScript is dead" nonsense.

HTML is actually pretty damn capable. Not in the abstract — concretely, with zero JavaScript.

Form validation, no JS

That's real validation. Wrong email format, empty field, age under 18 — the browser blocks submission and shows a native error message. No library, no onChange handler, no state.

Want custom styling on invalid fields instead of the browser's default popup? Try the inputs above — empty or wrong-format fields get a red border, valid ones turn green. All of it CSS.

A modal, no JS

Are you sure?

<dialog> gives you a real modal — top layer, backdrop, focus trap, Esc to close — built into the element. Opening it takes zero JavaScript: the popovertarget attribute on the button does it, and clicking outside, pressing Esc, or hitting Cancel closes it. Try it.

A dropdown menu, no JS

Options
  • Edit
  • Duplicate
  • Delete

<details>/<summary> is a fully functional disclosure widget — the one above is live. Click to expand, click to collapse. The CSS inlines the styling so it doesn't look like a <details> element at all, and most users will never know.

Now the part everyone skips: where this actually stops being enough

I'm not going to pretend HTML/CSS covers everything, because it doesn't, and pretending otherwise is exactly the kind of vague-take nonsense that makes this genre of post useless. Concretely, you need JavaScript (and maybe a framework) when:

  • Cross-field validation — "confirm password must match password," "end date must be after start date." :invalid and required can't see across fields.
  • Async validation — checking if a username is taken while the user types. That's a network call, full stop.
  • Client-side state that outlives a page load — a shopping cart, a multi-step wizard, anything that needs to persist without hitting the server every time.
  • Real-time UI updates — live search filtering a list as you type, a chat interface, anything where the DOM needs to react to data changing without a full page reload.

That's the actual line. Below it, native HTML. Above it, JavaScript — and only once you're stacking multiple things from that list across a large enough app does a framework start paying for itself over vanilla JS.

Which is why this still bugs me:

Someone needs a contact form with an email field and a submit button, and the stack becomes React, a router, a form library, a validation library, a UI library, state management, 400 npm packages, and a node_modules folder the size of a black hole.

For a form that native required and type="email" already solve.

Come on.

I'm not saying frameworks are bad. React earns its place the moment you're doing real client-side state, real-time updates, or a UI complex enough that manually wiring up DOM updates becomes its own maintenance burden. That's a real threshold, not a vibe.

I almost always reach for HTML first, then CSS, then JavaScript. Only when the problem actually hits one of the things on that list above do I reach for Svelte or Vue.

The browser already gives us a lot.