(State.js, Motion.js, Gravity.js, Cursor.js, Keys.js — a browser‑native ecosystem)
For years, frontend development has revolved around one assumption:
If you want interactivity, state, animation, or physics — you need a framework.
React, Vue, Svelte, Solid… all incredible tools, but they all share the same core idea:
- JS owns the state
- JS owns the rendering
- JS owns the reactivity
- JS owns the lifecycle
HTML and CSS are treated as passive output layers.
But what if that assumption is wrong?
What if the browser already has the primitives we need — and we just haven’t been using them as a unified system?
That’s the question that led me to build a small ecosystem of libraries that all share one philosophy:
Expose browser signals to CSS.
Let HTML declare behaviour.
Let CSS render it.
Use JS only as the glue.
This post introduces that ecosystem.
Why This Stack Exists
Modern frontend development is powerful — but also heavy.
- Bundlers
- Virtual DOMs
- Component compilers
- State libraries
- Effect systems
- Re-renders
- Signals
- Hooks
- Stores
All to build things the browser can already do.
Meanwhile, CSS has quietly evolved into a reactive rendering engine:
- CSS variables
- calc()
- transitions
- animations
- container queries
- view transitions
- scroll-driven animations
- :has()
- @property
- custom easing
And HTML has evolved into a declarative configuration surface:
- attributes
- custom elements
- dataset
- templates
- inert
- popovers
So the question became:
What if we treat HTML + CSS as the application layer,
and JavaScript as the runtime that feeds them state?
That’s the foundation of this stack.
The Stack (Browser‑Native, Declarative, Modular)
Each library does one thing, exposes one set of signals, and stays tiny.
1. State.js — CSS‑Reactive State Engine
State.js exposes reactive state directly to CSS variables.
<div id="player"
data-state
data-state-watch="health,score"
data-state-var="true"
data-health="100"
data-health-min="0"
data-health-max="100"
data-score="0">
<div class="health-bar"></div>
</div>
No re-renders.
No virtual DOM.
No diffing.
Just state → CSS → rendering.
2. Motion.js — Scroll, Time & Viewport Signals
Motion.js exposes:
- scroll progress
- element visibility
- time
- easing
- playback
…as CSS variables.
<div data-motion data-motion-var="true" data-motion-duration="2000">
<!-- CSS animates based on scroll/time -->
</div>
3. Gravity.js — Physics Exposed to CSS
Gravity.js simulates:
- gravity
- velocity
- friction
- forces
…and exposes them as CSS variables.
<div data-gravity data-gravity-type="static">
<!-- CSS animates based on physics -->
</div>
This lets designers build physical-feeling interfaces without writing physics code.
4. Cursor.js — Cursor State as CSS Variables
Cursor.js exposes:
- x/y position
- velocity
- direction
- hover state
…to CSS.
<div data-cursor>
<!-- CSS reacts to cursor movement -->
</div>
5. Keys.js — Keyboard State as CSS Variables
Keys.js exposes:
- key pressed
- key held
- key released
…to CSS.
<div data-keys>
<!-- CSS reacts to keyboard input -->
</div>
Why This Works
Because CSS is already a reactive rendering engine.
When you expose state to CSS variables:
- CSS handles the rendering
- CSS handles the animation
- CSS handles the interpolation
- CSS handles the transitions
- CSS handles the layout
JavaScript becomes:
- the state updater
- the signal provider
- the glue
Not the renderer.
This flips the traditional model:
| Traditional | This Stack |
|---|---|
| JS renders | CSS renders |
| JS animates | CSS animates |
| JS manages state | JS exposes state |
| HTML is passive | HTML is declarative |
| CSS is styling | CSS is reactive |
Why Not Just Use React?
React is incredible — but it’s a UI framework.
This stack is a browser-native runtime.
React owns:
- rendering
- state
- components
- lifecycle
This stack owns:
- signals
- state exposure
- declarative behaviour
- CSS-driven rendering
They’re not competitors.
They’re different layers.
You could even use them together.
What This Enables
This stack makes it trivial to build:
- physical-feeling UI
- scroll-reactive UI
- cursor-reactive UI
- keyboard-reactive UI
- time-based UI
- stateful UI
- animated UI
…without writing application logic.
It also opens the door to something bigger:
A new authoring medium where designers can build interactive systems without touching JS.
Think:
- Figma-like tools that export real interactions
- CSS-driven physics
- declarative behaviour graphs
- HTML as the app layer
- CSS as the rendering engine
- JS as the runtime
This is the direction the web has been moving toward for years.
This stack just pushes it further.
Where This Goes Next
This isn’t a framework.
It’s not a React competitor.
It’s not a “React killer.”
It’s a new layer.
A browser-native layer.
A declarative layer.
A layer that asks:
How much interactivity can we get from HTML + CSS before we need application code?
And the answer so far is:
More than people think.
If You Want to Explore the Stack
Here are the individual libraries:
- State.js — CSS-reactive state
- Motion.js — scroll/time signals
- Gravity.js — physics signals
- Cursor.js — cursor signals
- Keys.js — keyboard signals
Each one is tiny, focused, and works independently.
But together, they form something new.
A stack.
A philosophy.
A new way of thinking about the browser.
Top comments (0)