content (DOM text)
declarationsince 0.9.0experimentalrequires runtimeOn elements, a content value that reads state also becomes the element’s DOM text: a real text node, never HTML. The native declaration is kept as written.
On this page · 10 sections+−
Syntax
content: var(<state>) | when(<condition>, <a>, <b>) | previous(<state>) | direction(<state>);registry syntax: content: var(--state) | when(condition, a, b) | previous(--state) | direction(--state)
Parameters
- valueone scalar that reads staterequired
- Must contain
var(),when(),previous()ordirection(), and nourl(),image-set(), gradient orattr(). Other values stay plain CSS.
Effect
No value. The element’s text node is set with Text.data: selectable, copyable and in the accessibility tree as ordinary text.
Example
cart.cssreactive
/* <span class="count">0</span> <span class="unit">items</span> */.cart { --items: state(0); }.cart .add:on(click) { --items: increment(1); }.cart .count { content: var(--items); }.cart .unit { content: when(--items == 1, "item", "items"); }state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →
Correct and incorrect usage
correctGenerated content stays native
badge.cssreactive
.cart { --items: state(0); }.cart .badge::after { content: var(--items); }A pseudo-element is not DOM text, so this is native generated content: it shows a number from a state but is not part of the document.
incorrectAn element with child elements
card.cssreactive
/* <div class="card"><h2>…</h2><p>…</p></div> */.card { --title: state("Hello"); }.card { content: var(--title); }This compiles, but the binding never empties an element with children: at run time it gives a diagnostic and leaves the markup. Target the h2 instead.
Behavior
- Experimental.
- When it applies. All of these must hold: the rule targets elements (no selector in its list has a pseudo-element); the value reads state through
var(),when(),previous()ordirection(); it contains no image orattr(); and the stylesheet is trusted. Every othercontentdeclaration is plain CSS and is left alone:::before { content: var(--n) },content: "x"andcontent: url(a.png)keep their native meaning. - The native declaration is kept. Reactive CSS adds a text binding next to it. On elements, strings and numbers in
contentrender nothing in Chromium and WebKit, so what you see is the DOM text. - Text only. It writes one Text node, never markup, and only into an element that is empty or holds exactly one text node. An element with child elements is never emptied; a diagnostic is given instead.
- Yields and restores. If something else changes the text, the binding yields. When no declaration applies, the original HTML text comes back, so the markup is the fallback before the script runs.
- Accessibility. Unlike generated content in
::beforeor::after, the text is part of the document: assistive technology reads it as ordinary text, and it can be selected, copied and found with in-page search. - A value that resolves to an image at run time (a
var()holdingurl()) is left to the browser.
Supported contexts
- Elements that are empty or hold one text node.
- Trusted stylesheets only.
Limitations
- Not a template language and not a general replacement for
textContent: one value per element. - Firefox is not verified: how it renders
contentstrings on elements has not been tested.
Examples
- Counter · API examples, runs the real runtime
- Form mirror · API examples, runs the real runtime
Related
Experimental · syntax may change between minor versions