Alex Vipond
SHIFT + D

In place of "HTML Considered Harmful"

If I were in the clickbait game, I'd reduce this post down to "HTML Considered Harmful."

But that's boring and imprecise. In place of that, I've cooked you some more nutritious food for thought 🥗

HTML is good at some things

Syntactically, HTML is extremely good at some of the things UI engineers need.

It's good at declaring some of the UI's tree structure:

<form ...>
  <div>
    <label ...>...</label>
    <input ... />
  </div>
  <div>
    <label ...>...</label>
    <select>
      <option ...>...</option>
      <option ...>...</option>
    </select>
  </div>
  <button ...>...</button>
</form>

It's good at initializing some state and custom behavior for some UI controls:

<input
  type="text"
  name="firstName"
  autocomplete="given-name"
  autocapitalize="words"
  placeholder="First Name"
  value="Alex"
  disabled
/>

It's even somewhat good at defining reusable chunks of markup:

<template id="my-component">
  <div>
    <h1>...</h1>
    <p>...</p>
  </div>
</template>

But UI engineers need a lot more. We need:

  • variables & memory
  • iterables & for loops
  • conditional rendering
  • transitions for elements entering and leaving the DOM
  • to actually reuse markup—not just declare it as reusable
  • to pass initial states and customization options that are not just JS primitives
  • reactive state
  • to imperatively change reactive state
  • data structures & algorithms that solve problems like fuzzy searching, overlapping gridcell selection, spring physics, virtualization, etc., and are tailored to app-specific performance and UX requirements
  • to organize all of the above by logical concern

HTML is not enough, will never be enough, should never be enough

Without a massive syntactic expansion, HTML is not cut out for these jobs. At the same time, JS can syntactically do all of HTML's jobs.

Declare tree structure:

form({ ... }, [
  div([
    label({ ... }, [...]),
    input({ type: 'text', ... })
  ]),
  div([
    label({ ... }, [...]),
    select({ ... }, [
      option('...'),
      option('...')
    ])
  ]),
  button({ ... }, [...])
])

Initialize state and customize behavior:

input({
  type: 'text',
  name: 'firstName',
  autocomplete: 'given-name',
  autocapitalize: 'words',
  placeholder: 'First Name',
  value: 'Alex',
  disabled: true
})

Define reusable chunks of markup:

const render = template({ id: 'my-component' }, [
  h1([...]),
  p([...])
])

JS as a language meets all the other requirements of UI engineers.

We are wasting time on HTML implementations

Open UI process:

  1. research
  2. specs and test suites
  3. HTML implementations

Steps 1 and 2 represent some of the most important work happening on the web right now. Step 3 is a waste of time.

Under HTML's constraints, form controls and other UI components have always been half a solution, if not less, and that's what they will continue to be.

Break up HTML's monopoly on early parsing and execution. Add new Content Type header values that tell the browser to forget about HTML and just use Vue/Svelte/Solid-esque template parsing, modularized to make partial execution possible, compiled to a DOM optimized for patching. Build Vapor mode into the browser, you cowards.

TK progressive enhancement?

Devtools that show us the actual DOM, not serialized HTML.

built-in reactivity

stronger ecosystem of education around higher-order functions and composition. We are building directed acyclic graphs, you must be this tall to ride.

Further reading

surma open web thing?

ON THIS PAGE

In place of "HTML Considered Harmful"HTML is good at some thingsHTML is not enough, will never be enough, should never be enoughWe are wasting time on HTML implementationsFurther reading