Most frontend tools make you learn a framework, write components, manage state, and fight a build pipeline… just to update a number on the screen.
State.js flips that model on its head.
It turns HTML data attributes into a fully reactive UI engine - exposing your element’s state as CSS variables, updating automatically, and letting you build dynamic interfaces without you writing any JavaScript logic yourself.
If you know HTML and CSS, you already know how to use State.js.
✨ What State.js Actually Does (In Plain English)
State.js watches your HTML elements and automatically exposes their state as CSS variables:
data-health="75" → --state-health: 75
data-health-max="100" → --state-health-percent: 75%
Then you use those variables in CSS:
.health-bar {
width: var(--state-health-percent);
}
Change the attribute → UI updates instantly → CSS animates it.
No JS functions.
No components.
No re-renders.
No virtual DOM.
Just HTML + CSS.
🔥 Why Developers Love It
1. You don't need to write any JavaScript Logic
You can build:
- dashboards
- progress bars
- form interactions
- clicker games
- idle games
- RPG UIs
- video players
- reactive animations
…without writing a single line of JS.
2. Designers Can Work Directly in the Code
State.js exposes everything as:
- CSS variables
- data attributes
- conditional classes
Designers don’t need to touch JS files or understand framework lifecycles.
3. Backend‑First Friendly
Works perfectly with:
- Laravel
- Rails
- WordPress
- Django
- Phoenix
- HTMX
No bundlers.
No hydration.
No client‑side routing.
Just reactive HTML.
4. Game‑Dev Ready
State.js includes:
- timers
- computed values
- sound effects
- persistence
- event dispatch
- interval triggers
- auto‑fire logic
- conditional classes
You can build a full idle game in pure HTML.
⚡ What You Can Build in 30 Seconds
A clicker game:
<div id="clicker" data-state data-score="0" data-state-watch="score">
<h1>Score: <span data-state-display="score"></span></h1>
<button data-state-trigger
data-state-bind="clicker"
data-state-attr="score"
data-state-increment="1">
Click Me!
</button>
</div>
A health bar:
<div data-state data-hp="75" data-hp-max="100" data-state-var="true">
<div class="bar" style="width: var(--state-hp-percent);"></div>
</div>
A form that tracks focus + changes:
<input data-state-trigger data-state-trigger-on="focus"
data-state-bind="form" data-state-attr="focusCount" data-state-increment="1">
A video progress bar:
video::after {
width: var(--state-progress);
}
A toggleable UI state:
<div data-state data-state-toggles="active" data-active="false"></div>
🧩 The Magic Primitives (The 80% You Need to Know)
Here are the core building blocks that let you build anything:
1. data-state
Turns an element into a reactive state container.
2. data-state-watch="attr1,attr2"
Watches attributes and exposes them as CSS variables.
3. data-state-trigger
Makes an element update state when interacted with.
4. data-state-attr="health"
Which attribute to update.
5. data-state-increment="10"
Add to a value.
6. data-state-set="100"
Set a value exactly.
7. data-state-condition="gold >= 50"
Only fire if condition is true.
8. data-state-autofire="true"
Fire automatically when condition becomes true.
9. data-state-text="HP {hp}/{hpmax}"
Template string interpolation.
10. data-state-class="critical"
Conditional CSS classes.
11. data-state-interval="1000"
Run triggers every N ms (timers, regen, idle loops).
12. data-state-sound="coin"
Play procedural sound effects.
13. data-state-persist="true"
Save + restore state from localStorage.
14. data-state-trigger-on="input|scroll|mouseenter|submit"
Event‑based triggers with debounce/throttle.
15. data-state-include="component.html"
HTML includes — reusable components with no build step.
🎮 Example: A Full Idle Game in Pure HTML
You can literally build this with no JS:
- gold counter
- click power
- upgrades
- level scaling
- passive income
- auto‑leveling
- sound effects
- persistence
All declarative.
This is why State.js is exploding in game‑dev circles.
🎨 Example: A Fully Reactive UI Component
<div id="player"
data-state
data-state-watch="health,mana,xp"
data-state-var="true"
data-health="100"
data-mana="80"
data-xp="450">
<div class="health" style="width: var(--state-health-percent)"></div>
<div class="mana" style="width: var(--state-mana-percent)"></div>
<div class="xp" style="width: var(--state-xp-percent)"></div>
</div>
CSS handles the rest.
🧠 Why This Works: The Mental Model
State.js is built on one simple idea:
HTML holds the data.
CSS reacts to the data.
State.js keeps them in sync.
That’s it.
No components.
No framework.
No build step.
No hydration.
No virtual DOM.
Just declarative UI.
🚀 Want to Go Deeper?
The README is your full reference manual — every primitive, every example, every advanced feature.
But with what you’ve learned here, you can already:
- build reactive dashboards
- build interactive UI
- build game interfaces
- build idle games
- build RPG UIs
- build form logic
- build video players
- build reusable components
All with HTML + CSS only.
View the repo here




















