Declarative HTML Components
A markup-first component model: leveled modules that compile to, and polyfill on, the web platform.
Status of this document
An unofficial editor's draft for discussion at Stage 0. It is not a standard and does not represent the position of the W3C, the WHATWG, or any browser vendor.
This document specifies the component-authoring proposal in the HTML Next collection. Its modules form an authoring layer above the platform today, with the explicit aim that proven features are adopted into the platform through the normal standards process. Everything normative here currently constrains conforming tooling; that boundary would move if a module graduates.
Abstract
Declarative HTML Components proposes a reliable, reactive component-authoring model for HTML. The platform gained a rendering engine, a networking stack, and a component mechanism, but never an application authoring model, so for fifteen years the primitives authors need most (reusable typed components, control flow, data sources, reactivity) were reinvented, incompatibly, in one JavaScript framework after another. This proposal expresses those primitives as markup, so the web gains a standard component layer that degrades to plain HTML and outlives any single framework.
In plain terms: you write components, control flow, and reactivity as HTML, and run the same file in the browser or compile it to React, Vue, or Svelte, with no build step and no eval().
<!-- You write a component as markup -->
<x-button variant="solid">Save</x-button>
<!-- It becomes a real native button — no wrapper, no shadow root -->
<button data-component="x-button" data-variant="solid">Save</button>You author a component once, as literal browser-parseable HTML with an inert typed contract. A conforming implementation lowers it into idiomatic Vanilla DOM, React, Vue, and Svelte, or interprets the same source directly in Chromium, Firefox, and WebKit. One semantics, many backends.
Introduction & goals
The missing layer
The web platform kept advancing: fetch, Grid, ES modules, even Custom Elements and Shadow DOM. Yet HTML's own vocabulary for building applications barely grew. The primitives an app author reaches for every day were never added to markup, so the same wheel was reinvented, again and again and incompatibly, in userland. Ask HTML, natively, for any of these and the answer is still "load a framework":
| Application need | Native HTML answer | What everyone does |
|---|---|---|
| Reusable typed component with a documented API | None (Custom Elements are untyped, imperative) | React/Vue/Svelte component |
| Conditional & repeated markup | None | v-if, {#each}, .map() |
| Declarative reactivity | None | hooks, refs, runes, signals |
| Bind a control to state | None | controlled inputs, v-model |
| Declare a data dependency | None | fetch-in-effect, loaders, resources |
Every cell in the right column is an incompatible language. Web Components addressed packaging and skipped the language problem: a place to put a component but no declarative way to write one.
The component model
A markup-first authoring language realized by two kinds of conforming implementation that must produce observably equivalent output:
An ahead-of-time compiler lowers HTML Next to idiomatic Vanilla DOM, React, Vue, Svelte, CSS, contracts, and docs: a multi-target converter in the spirit of Mitosis.
A browser runtime reads the same source, lowers it against the live DOM without Custom Elements or dynamic code, and subscribes to its declared dependency graph.
The proposal is both an authoring layer you can use today, through the converter and polyfill, and a set of platform features meant to graduate into HTML itself, feature by feature, the way Declarative Shadow DOM and invoker commands went from userland shim to shipped native syntax.
The proposal is purely additive markup. You add one feature to an ordinary HTML file, one tag at a time, and everything else stays exactly as it was. A plain HTML file already satisfies the language, so adoption requires no file-format rewrite.
How the proposal versions
There is no single umbrella version, no big-bang HTML Next 1.0. The project versions the way the platform itself does today, on three borrowed axes:
CSS stopped shipping monolithic versions after 2.1; it is developed as independent modules, each at its own Level (Selectors 4, Color 5, Grid 2). Declarative HTML Components uses the same model: Components, Templating, Reactivity, and Types advance by Level on their own evidence.
HTML is a Living Standard; new features incubate as proposals (WICG explainers), and JavaScript proposals move through TC39 stages 0 to 4. This proposal is at Stage 0 today; maturity is a stage, not a number announced in advance.
The precedent is CSS's dated Snapshot: a snapshot is a named, dated set of modules each pinned at a specific Level (e.g. Components L1, Templating L1, Reactivity L1, Types L1). It records what the proposal contains on that date without forcing every module into one release train.
The worked example is Web Components. The shipping modules (components, templating, reactivity, scoping) provide a practical component authoring model today. The parts a compiler cannot supply, including native-element extension and deeper Shadow DOM integration, belong in later upstream platform proposals.
What declarative components need
A complete component-authoring model needs reactivity, style scoping, and reliable native semantics. This proposal addresses each as a module that can advance on its own evidence. Components lower to real native elements today; reactivity and style scoping advance independently; deeper platform integration remains upstream standards work.
Reactivity
Why it's broken
- HTML has no declarative reactivity, so every framework invented its own (VDOM diffing, proxies, compilers, signals), and they don't interoperate.
- Reactivity is expressed in framework-specific JavaScript, not markup: it can't be inspected, typed once, or ported.
- Most runtime approaches need dynamic code (
new Function) or ship a diffing engine to every user.
This proposal's answer
- Reactivity is a declarative dependency graph in markup:
<state>,<computed>,<data>, and:/bind:bindings over a small pure expression language. - The graph is statically analyzable: dependencies are read off the parsed expression, not discovered at runtime.
- One semantics, many backends: it lowers to React state, Vue refs, Svelte runes, or a signal-based browser runtime. No
eval, CSP-clean.
Web Components
Why it's broken
- No portable way to extend a native element: customized built-ins (
is=) are formally opposed by WebKit, soextends HTMLButtonElementhas no cross-browser path.2 - The autonomous alternative, an
<x-button>host, forfeits the native button's form submission, role, and focus, rebuilt by hand. - Form participation dies at the shadow boundary; it needs
ElementInternals, which stabilized cross-browser only in 2023.6 - Imperative ceremony, string-only props with no inspectable contract, and cross-boundary styling friction round it out.1
Polyfill today, platform change upstream
- HTML Next needs custom elements not at all: templating and native lowering emit a real
<button>, so native semantics stay the browser's. - The component is typed markup with a declarative contract and compiles to idiomatic React, Vue, and Svelte: portable, not a walled garden.
- What a compiler cannot fix (WebKit's refusal of customized built-ins, form association across a boundary) is platform work for a later module Level and an upstream proposal.
- Its likely shape: templating that opts into an extension of Declarative Shadow DOM, closing the styling and form gaps DSD left open.
Shadow DOM & scoping
Why it's broken
- Shadow DOM gives all-or-nothing encapsulation. Styling across the boundary is painful (
::part,::slotted); global theming and shared styles fight it. - Declarative Shadow DOM and its SSR story arrived years late and remain awkward.
- Forms, focus, and accessibility relationships behave surprisingly across the boundary.
- Most authors want scoping, not isolation, and are forced to take both.
This proposal's answer
- A component's styles are scoped to it by default: its
<style>affects only its own markup, not the whole page, and with no shadow boundary, the scoping the browser already offers with CSS@scope. Encapsulation without isolation. - Degrades to plain CSS in the light DOM: theming, cascade, and shared design tokens keep working.
- Real isolation becomes an opt-in target capability, never the mandatory tax Shadow DOM makes it today.
- A later Level takes the isolation case further with an extension of Declarative Shadow DOM that fixes DSD's styling and form-participation gaps instead of inheriting them.
The record: Web Components in practice
Whether Web Components failed by design or only because they were never fully leveraged does not matter to an author choosing a component model today. In their shipped form they did not become the web's component layer, and the clearest evidence is the ecosystem's own behavior.
Champions retreated The flagship "components will replace frameworks" project was wound down.
Google's Polymer entered maintenance mode in 2018 and was superseded by Lit (a thin rendering helper) because raw custom-element ergonomics were not enough on their own.8
Framework authors opted out The people who build component models did not build them on this one.
The creator of Svelte set out in 2019 why he does not use Web Components: Shadow DOM forces CSS into JavaScript; the property/attribute split forces boilerplate; slotted content renders eagerly; the registry is one global namespace; and the DOM is "an awkward interface for building interactive applications."1 React, Vue, Svelte, and Solid each built their own model instead.
The extension mechanism is blocked There is no cross-browser way to extend a native element.
Customized built-in elements ship in Chromium and Firefox, but WebKit's formal standards position is to oppose them and not implement them.23 The only spec-sanctioned route to reusing native semantics has no portable path.
Interop lagged a decade The largest UI library could not talk to them properly until 2024.
For most of the feature's life React could not pass an object or array to a custom element, nor listen to its events; the gap was tracked on Custom Elements Everywhere. Full support arrived only in React 19, December 2024, more than a decade after custom elements were proposed.45
Architecture
Three kinds of element
The proposal keeps three layers distinct: authoring syntax, generated output, and the runtime or compiler that connects them.
Conforming implementations
Declarative HTML Components is a language specification: an implementation is a converter or a polyfill. Its governing conformance contract is observable equivalence: the same native DOM, state, events, accessibility, and errors for the same source.
The Next Web Working Group publishes the proposal and this site. The html-next implementation repository contains the current polyfill and converter. As more proposals gain implementations, each will have its own package over shared infrastructure.
Progressive enhancement runs the other way from a hypermedia library: in htmx the server round-trip is the baseline and script enhances it; in HTML Next the rendered HTML is the baseline and the browser enhances it. A server-rendered page delivers its initial content as ordinary HTML that displays, is accessible, and is indexable with no JavaScript.
How far past that first render a no-JavaScript page reaches depends on the kind of reactivity:
- State that maps to a native primitive (a toggle to
<details>orpopover, selection to:checked, validity to constraint validation, relational reactivity to:has()) lowers to HTML and CSS and keeps working with no script. - Genuinely dynamic reactivity (data fetches, values computed over live input, lists over changing data) needs the runtime, or a server-round-trip fallback that is still open.
So the guarantee is a no-JS render, and a no-JS application exactly as far as the reactivity has a native lowering.
Conformance & module levels
Keywords follow RFC 2119, scoped to HTML Next tooling. A tool must emit an explicit unsupported-feature diagnostic, never silent literal fallback, for any construct above its level.
| Module | Level 1: normative today | Direction |
|---|---|---|
| Components | Typed native-root components; default, named, fallback, and scoped slots; explicit polymorphic roots. Shipping | L2 external imports and dynamic composition |
| Targets | Vanilla, React, Vue, Svelte, CSS, docs. Shipping | L2 SSR, static/email |
| Browser runtime | One-shot lowering, no Custom Elements, no eval. Shipping | L2 reactive updates |
| Templating | None yet | L1 $each, $if, $match, <value> |
| Reactivity | None yet | L1 state, computed, data |
| Forms | Native ownership, validation, submission, and submitter overrides. | L2 expanded methods and composable submission scopes |
| Types | string, boolean, number, enum. | L3 URLs, colors, refs, content models |
| Isolation | None yet | Upstream Declarative-Shadow-DOM extension; native-element extension upstream |
Specification modules
Each capability is an independently-levelled module. Overview and Examples are reading guides, so they are listed separately above rather than presented as modules.
Adoption
A spec convinces no one; four things do, in order.
Author one component; compile it to the framework you already ship, and polyfill it in the browser with no build. Adoption risk is one file, not a rewrite.
Each fix is a grievance a developer already has: reactivity lock-in, Custom Element ceremony, Shadow DOM pain.
No new mental-model tax: it reads like markup, survives the parser, and works under CSP. A component invocation even degrades to its inline children before any runtime runs.
One jaw-drop demo (one file → five targets + live browser) and a name that promises the next HTML.
Governance & the working group
The Next Web Working Group exists today as a GitHub organization. The path to a recognized standards venue, cheapest rung first:
- The org is the specs and the site. Publishes standards; ships no tooling.
- A separate implementation repository,
html-next, organized into proposal-specific packages as implementations are added. - An explicit stage process, proposal → incubation → Level N, modeled on TC39 stages and WHATWG workstreams.
- A Community Group listing for legitimacy without W3C membership.
- Upstream the wins. A mature module's endgame is a proposal into WHATWG/CSSWG/TC39.
Open questions
Genuine design questions, not yet settled:
| Area | Question |
|---|---|
| Imports | Component-definition and registry-scoping syntax; untrusted-import trust model. |
| Data | Request, caching, cancellation, concurrency, and stale-response semantics. |
| Rendering | SSR serialization, hydration ownership, no-runtime fallback, static/email targets. |
| Expressions | and/or/not vs. &&/||/!; missing-data value; object/list literals; safe navigation. |
| Reactive scheduling | Browser scheduling, teardown, and dynamic-index dependency breadth. |
| Parser contexts | SVG, MathML, table, and select insertion modes. |
| Extension | How consumers extend the element and type vocabulary; capability negotiation. |
Shopify Liquid (constrained template language, filter pipelines), Squarespace JSON-T (data-context-first templating), Vue & Svelte (markup-first components, scoped styles, browser-safe binding syntax), Mitosis (one source → many framework targets), and XSLT (declarative tree transformation) are inputs and evidence; none is adopted as the default answer.
References
Informative. Retrieved September 2026; standards positions and browser versions as published.
- Rich Harris. "Why I don't use web components." DEV, 20 June 2019. dev.to/richharris/why-i-don-t-use-web-components-2cia
- WebKit. Standards position on customized built-in elements: oppose. Issue #97, 2022. github.com/WebKit/standards-positions/issues/97
- WebKit Bugzilla 182671. "Implementation (or not) of customized builtins." bugs.webkit.org/show_bug.cgi?id=182671
- Custom Elements Everywhere. Framework interoperability tests. custom-elements-everywhere.com
- React 19. Full custom-elements support, December 2024. react.dev/blog/2024/12/05/react-19
- WebKit. "ElementInternals and Form-Associated Custom Elements" (Safari 16.4, 2023). webkit.org/blog/13711
- WebKit. "Declarative Shadow DOM" (Safari 16.4; Firefox 123, 2024). webkit.org/blog/13851
- Lit. "Lit for Polymer users": Polymer superseded by Lit; in maintenance since 2018. lit.dev/articles/lit-for-polymer-users