<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: iDev-Games</title>
    <description>The latest articles on DEV Community by iDev-Games (@idevgames).</description>
    <link>https://dev.to/idevgames</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1050213%2Fe693562c-e79e-4cc1-8346-d542ee592839.png</url>
      <title>DEV Community: iDev-Games</title>
      <link>https://dev.to/idevgames</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idevgames"/>
    <language>en</language>
    <item>
      <title>I Built a Full RPG with Zero JavaScript Logic - Here's What I Learned</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Thu, 11 Jun 2026 13:31:56 +0000</pubDate>
      <link>https://dev.to/idevgames/i-built-a-full-rpg-with-zero-javascript-logic-heres-what-i-learned-58k7</link>
      <guid>https://dev.to/idevgames/i-built-a-full-rpg-with-zero-javascript-logic-heres-what-i-learned-58k7</guid>
      <description>&lt;p&gt;&lt;em&gt;A deep dive into State.js by building Gutter Rat: a working SPA game with combat, shops, inventory, and level-ups — all in HTML and CSS.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Here's the CodePen. The JS panel is empty.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/iDev-Games/embed/pvRbgLj?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Take a minute to play it. Buy gear, pick a fight, grind XP, level up. Then come back and I'll explain exactly how it works and what building it taught me.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is State.js?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; is a reactive state library that exposes application state as HTML data attributes and CSS custom properties. Instead of JavaScript managing the DOM, the DOM &lt;em&gt;is&lt;/em&gt; the state — and CSS subscribes to it directly.&lt;/p&gt;

&lt;p&gt;It's part of a broader browser-native stack built by &lt;a href="https://dev.to/idevgames"&gt;@iDev_Games&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trig.js&lt;/strong&gt; — scroll position to CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor.js&lt;/strong&gt; — mouse/touch position to CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keys.js&lt;/strong&gt; — keyboard input to CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Motion.js&lt;/strong&gt; — global animation clock for CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gravity.js&lt;/strong&gt; — DOM physics engine rendered in CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State.js&lt;/strong&gt; — reactive application state layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one independently useful. Together they form a complete declarative application engine that runs directly in the browser with no build step, no bundler, and no framework.&lt;/p&gt;

&lt;p&gt;The philosophy: &lt;strong&gt;your HTML is your state graph, CSS is your rendering engine, and JavaScript is only for what JavaScript is genuinely good at.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Project: Gutter Rat
&lt;/h2&gt;

&lt;p&gt;I wanted to build a demo that pushed State.js hard — not a counter, not a toggle, but something with real game logic: an SPA with multiple panels, an economy, combat with health bars, a shop that modifies stats, dynamic inventory, conditional UI, and automatic level detection.&lt;/p&gt;

&lt;p&gt;The result is Gutter Rat — a grimy street RPG in the spirit of old browser games like Hobo Wars. Scraps McBurly. The Rusty Alley. Big Vince. You know the vibe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it has:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4-panel SPA (Town, Fight, Gear, Stats) with animated transitions&lt;/li&gt;
&lt;li&gt;HP/MP/XP bars driven by CSS custom properties&lt;/li&gt;
&lt;li&gt;Gold economy with healing, drinks, scavenging, and gambling&lt;/li&gt;
&lt;li&gt;Combat system with punch, haymaker, autofire victory/defeat detection&lt;/li&gt;
&lt;li&gt;Shop that dynamically spawns items into an inventory grid&lt;/li&gt;
&lt;li&gt;Attribute training (ATK, DEF, SPD)&lt;/li&gt;
&lt;li&gt;Level-up toast that fires automatically when XP maxes out&lt;/li&gt;
&lt;li&gt;Win/loss tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zero lines of JavaScript logic. One &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag pointing at State.js.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the SPA Routing Works
&lt;/h2&gt;

&lt;p&gt;This is the most immediately useful pattern for anyone building with State.js.&lt;/p&gt;

&lt;p&gt;The entire panel-switching system runs on a single numeric attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"panel"&lt;/span&gt;
     &lt;span class="na"&gt;data-panel=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;data-panel-min=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt; &lt;span class="na"&gt;data-panel-max=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nav buttons set it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"panel"&lt;/span&gt; &lt;span class="na"&gt;data-state-value=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  🏚️ Town
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS does the routing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.panel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#app&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-panel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.panel-town&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#app&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-panel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.panel-fight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Active nav highlighting follows for free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#app&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-panel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.nav-btn&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-nav&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--amber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--amber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works better than a toggle-per-panel approach:&lt;/strong&gt; &lt;code&gt;data-state-attr&lt;/code&gt; + &lt;code&gt;data-state-value&lt;/code&gt; &lt;em&gt;sets&lt;/em&gt; a value directly — idempotent, no flipping. Clicking Town three times in a row stays on Town. Whereas &lt;code&gt;data-state-toggle&lt;/code&gt; flips a boolean, which means clicking the same panel twice would close it. For routing, you want assignment, not toggle.&lt;/p&gt;




&lt;h2&gt;
  
  
  The HUD: CSS Variables as a Render Layer
&lt;/h2&gt;

&lt;p&gt;Once you add an attribute to &lt;code&gt;data-state-watch&lt;/code&gt;, State.js exposes it as a CSS custom property automatically. HP becomes &lt;code&gt;--state-hp-percent&lt;/code&gt;. That's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bar-fill hp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.bar-fill.hp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-hp-percent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;90deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#6b1010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;#c84040&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bar animates on every HP change with zero JavaScript. The browser's CSS engine handles the interpolation. This is the pattern that makes State.js genuinely fast — you're not triggering layout recalculations through JS, you're updating a CSS variable and letting the compositor handle the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trigger Chains: Your Game Logic Layer
&lt;/h2&gt;

&lt;p&gt;This is where State.js gets powerful. A single button press can fire multiple sequential state changes via &lt;code&gt;data-state-trigger-chain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Buying a knife:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-instantiate=&lt;/span&gt;&lt;span class="s"&gt;"item-tpl"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#inv-grid"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-icon=&lt;/span&gt;&lt;span class="s"&gt;"🔪"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-label=&lt;/span&gt;&lt;span class="s"&gt;"Knife"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-bonus=&lt;/span&gt;&lt;span class="s"&gt;"+3 ATK"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-condition=&lt;/span&gt;&lt;span class="s"&gt;"gold &amp;gt;= 15"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-trigger-chain=&lt;/span&gt;&lt;span class="s"&gt;"buyKnife,addKnifeAtk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Buy
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Hidden trigger chain buttons --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"buyKnife"&lt;/span&gt;   &lt;span class="err"&gt;...&lt;/span&gt;  &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"gold"&lt;/span&gt; &lt;span class="na"&gt;data-state-decrement=&lt;/span&gt;&lt;span class="s"&gt;"15"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"addKnifeAtk"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"atk"&lt;/span&gt;  &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One click: spawns an inventory card, deducts 15 gold, adds 3 ATK. Three side effects from pure HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important note about chains:&lt;/strong&gt; each chain link fires independently. If a link has a &lt;code&gt;data-state-condition&lt;/code&gt; that fails, that link is skipped — but the rest of the chain still fires. Design your chains with this in mind. Don't put required dependencies after conditional steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dynamic Inventory with data-state-instantiate
&lt;/h2&gt;

&lt;p&gt;This was the most satisfying feature to get working. The Gear panel starts empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"inv-grid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inv-empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;No gear yet. Hit the Town market.&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a hidden template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item-tpl"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inv-slot"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"icon,label,bonus"&lt;/span&gt;
     &lt;span class="na"&gt;data-icon=&lt;/span&gt;&lt;span class="s"&gt;"🎁"&lt;/span&gt; &lt;span class="na"&gt;data-label=&lt;/span&gt;&lt;span class="s"&gt;"Item"&lt;/span&gt; &lt;span class="na"&gt;data-bonus=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;🎁&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slot-label"&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slot-bonus"&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"bonus"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each shop button uses &lt;code&gt;data-state-instantiate&lt;/code&gt; with &lt;code&gt;data-state-set-*&lt;/code&gt; overrides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state-instantiate=&lt;/span&gt;&lt;span class="s"&gt;"item-tpl"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#inv-grid"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-icon=&lt;/span&gt;&lt;span class="s"&gt;"🔪"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-label=&lt;/span&gt;&lt;span class="s"&gt;"Knife"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-set-bonus=&lt;/span&gt;&lt;span class="s"&gt;"+3 ATK"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js clones the template, applies the overrides as &lt;code&gt;data-*&lt;/code&gt; attributes on the clone, auto-initialises State.js on the clone, strips &lt;code&gt;display:none&lt;/code&gt;, and appends it to &lt;code&gt;#inv-grid&lt;/code&gt;. The &lt;code&gt;data-state-display&lt;/code&gt; elements inside each clone read from their own local scope, not the parent — so every spawned item correctly shows its own icon and stats.&lt;/p&gt;




&lt;h2&gt;
  
  
  Autofire: Reactive Logic Without Writing Logic
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;data-state-autofire="true"&lt;/code&gt; fires a trigger automatically the moment its condition flips from false to true. This is the closest thing State.js has to a computed reactive value, and it's how the level-up detection works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"autoLevelUp"&lt;/span&gt;
        &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-toggle=&lt;/span&gt;&lt;span class="s"&gt;"levelUp"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-condition=&lt;/span&gt;&lt;span class="s"&gt;"xp &amp;gt;= 100 and levelUp == false"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-autofire=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-trigger-chain=&lt;/span&gt;&lt;span class="s"&gt;"doLevelUp"&lt;/span&gt;
        &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The moment XP hits 100, this fires — no click needed, no JS event listener, no polling. The level-up toast appears and the level increments. Then the "Keep Brawling" button resets XP to 0 and toggles &lt;code&gt;levelUp&lt;/code&gt; back off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Critical gotcha with autofire:&lt;/strong&gt; if the condition is already true when the page loads, it fires immediately on init. In Gutter Rat, &lt;code&gt;enemyHp&lt;/code&gt; starts at 0, which meant &lt;code&gt;enemyHp &amp;lt;= 0&lt;/code&gt; was true on load and the victory autofire was triggering before any fight began. The fix was a &lt;code&gt;fightActive&lt;/code&gt; toggle that starts false and only flips true when you actually pick an enemy — gating the autofire with &lt;code&gt;fightActive == true and enemyHp &amp;lt;= 0&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Gotcha That Will Burn Everyone Once
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Data attribute names must be lowercase in CSS selectors and State.js class names.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is HTML's rule, not State.js's. The DOM normalises all attribute names to lowercase. But the consequence in State.js is specific: &lt;code&gt;data-state-toggles="choosingEnemy"&lt;/code&gt; generates the CSS class &lt;code&gt;state-choosingenemy&lt;/code&gt; — fully lowercase — not &lt;code&gt;state-choosingEnemy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your CSS says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#app&lt;/span&gt;&lt;span class="nc"&gt;.state-choosingEnemy&lt;/span&gt; &lt;span class="nc"&gt;.enemy-select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will never match. The correct selector is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#app&lt;/span&gt;&lt;span class="nc"&gt;.state-choosingenemy&lt;/span&gt; &lt;span class="nc"&gt;.enemy-select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This applies to every camelCase toggle name. &lt;code&gt;levelUp&lt;/code&gt; becomes &lt;code&gt;state-levelup&lt;/code&gt;. &lt;code&gt;fightActive&lt;/code&gt; becomes &lt;code&gt;state-fightactive&lt;/code&gt;. Write your CSS selectors in lowercase and you'll never hit this.&lt;/p&gt;

&lt;p&gt;The same rule applies to &lt;code&gt;data-state-watch&lt;/code&gt; attributes — keep them lowercase with hyphens. &lt;code&gt;data-enemyHp&lt;/code&gt; will work for attribute reads, but the CSS variable will be &lt;code&gt;--state-enemyhp-percent&lt;/code&gt;. Stick to lowercase throughout and it's consistent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting vs Toggling Booleans
&lt;/h2&gt;

&lt;p&gt;This one is subtle but important. &lt;code&gt;data-state-toggle="victory"&lt;/code&gt; &lt;em&gt;flips&lt;/em&gt; the boolean. If victory is false, it becomes true. If you call it again, it goes back to false.&lt;/p&gt;

&lt;p&gt;That's the wrong tool when you need to &lt;em&gt;set&lt;/em&gt; a specific value — like resetting combat state when starting a new fight. The right tool is &lt;code&gt;data-state-attr&lt;/code&gt; + &lt;code&gt;data-state-value&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"resetVictory"&lt;/span&gt;
        &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"victory"&lt;/span&gt;
        &lt;span class="na"&gt;data-state-value=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
        &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though &lt;code&gt;victory&lt;/code&gt; is in &lt;code&gt;data-state-toggles&lt;/code&gt;, you can write its underlying attribute directly. State.js picks up the change through its MutationObserver and updates the CSS class accordingly. This gives you idempotent state assignment instead of a blind flip — essential for reset operations in game loops.&lt;/p&gt;




&lt;h2&gt;
  
  
  Debugging: Use the Tools
&lt;/h2&gt;

&lt;p&gt;State.js has a console debug API that would have caught the lowercase CSS issue in seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// See all reactive state at once&lt;/span&gt;
&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspectAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Check specific element&lt;/span&gt;
&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Watch attribute changes in real time&lt;/span&gt;
&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;choosingEnemy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Logs every change to data-choosingEnemy as it happens&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When something isn't working, &lt;code&gt;State.trace('attributeName', true)&lt;/code&gt; is the first thing to run. It tells you immediately whether the attribute is changing (State.js working) vs. the CSS not responding (selector issue) vs. the condition not evaluating (logic issue). Those are three completely different problems with completely different fixes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest Assessment
&lt;/h2&gt;

&lt;p&gt;State.js draws a clean line at the boundary of declarative and algorithmic. Everything reactive — state changes, conditional UI, event-driven side effects, dynamic DOM.&lt;/p&gt;

&lt;p&gt;The hybrid approach is the optimal position for most projects: State.js handles the reactive layer, and you write the twenty lines of JS you actually need for the algorithm. You're not replacing JavaScript. You're eliminating the unnecessary JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;React solves "how do I make the UI reflect state" by pulling everything into JavaScript and rendering down to the DOM. State.js solves the same problem by treating the DOM &lt;em&gt;as&lt;/em&gt; the state store and CSS as the reactive subscriber.&lt;/p&gt;

&lt;p&gt;React's approach is powerful but it requires buying into an entire mental model, a build pipeline, JSX, hooks, a component lifecycle. The payload for "show this element when this condition is true" is enormous.&lt;/p&gt;

&lt;p&gt;With State.js the payload is one attribute. The CSS you already wrote does the rest.&lt;/p&gt;

&lt;p&gt;There's also a real and underserved audience here: designers, WordPress developers, people who are genuinely good at HTML and CSS but hit a wall the moment interactivity requires JavaScript. State.js moves that wall dramatically.&lt;/p&gt;

&lt;p&gt;The whole game state in Gutter Rat lives in one &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; opening tag. You can read the document and understand the entire data model without tracing through component trees or module imports. That inspectability is worth more than it sounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Play the game:&lt;/strong&gt; &lt;a href="https://codepen.io/iDev-Games/pen/pvRbgLj" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State.js on GitHub:&lt;/strong&gt; &lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;iDev-Games/State-JS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State.js subreddit:&lt;/strong&gt; &lt;a href="https://www.reddit.com/r/Statejs/" rel="noopener noreferrer"&gt;r/Statejs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN:&lt;/strong&gt; &lt;code&gt;https://cdn.jsdelivr.net/npm/@idevgames/state-js/src/state.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full stack — Trig.js, Cursor.js, Keys.js, Motion.js, Gravity.js, State.js — is at &lt;a href="https://github.com/iDev-Games" rel="noopener noreferrer"&gt;iDev-Games on GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: &lt;code&gt;javascript&lt;/code&gt; &lt;code&gt;css&lt;/code&gt; &lt;code&gt;html&lt;/code&gt; &lt;code&gt;gamedev&lt;/code&gt; &lt;code&gt;webdev&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Architectural Pivot: JS-Reactive Frameworks vs. CSS-Reactive Ecosystems (with Strategic JS)</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 10 Jun 2026 09:33:57 +0000</pubDate>
      <link>https://dev.to/idevgames/the-architectural-pivot-js-reactive-frameworks-vs-css-reactive-ecosystems-with-statejs-3li0</link>
      <guid>https://dev.to/idevgames/the-architectural-pivot-js-reactive-frameworks-vs-css-reactive-ecosystems-with-statejs-3li0</guid>
      <description>&lt;p&gt;For the past decade, frontend engineering has been locked inside a single, dogmatic assumption: &lt;strong&gt;if you want a reactive UI, JavaScript must control the screen.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This assumption birthed the Single Page Application (SPA) era. We gave full governance of our layouts over to heavy virtual DOM trees, reactive state proxies, and runtime JavaScript execution loops. To build a modern web app or high-fidelity game layout today, developers increasingly assemble stacks of frameworks, animation engines, state systems, and runtime tooling that collectively place growing pressure on bundle size and main-thread execution.&lt;/p&gt;

&lt;p&gt;The result? Massive JavaScript bundles, main-thread layout blocking, brittle dependency chains, and a continuous battle against worsening Core Web Vitals.&lt;/p&gt;

&lt;p&gt;But a paradigm shift is happening. By pairing native browser capabilities with a &lt;strong&gt;CSS-Reactive Framework like State.js&lt;/strong&gt; and using JavaScript strategically rather than punitively, we can invert the traditional architecture. The goal isn't to ban JavaScript—it is to alter the &lt;strong&gt;Priority of Concerns&lt;/strong&gt; to build the most performant, reactive, and premium web experiences possible.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Structural Divide
&lt;/h2&gt;

&lt;p&gt;To understand why the CSS-Reactive approach is fundamentally faster, we have to look at how data mutations translate into pixels on the user's screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Old Way: Imperative JS Re-rendering
&lt;/h3&gt;

&lt;p&gt;In a traditional JS-reactive framework, even a tiny state mutation triggers a massive computational sequence. When a value changes, the framework traps it via a proxy or setter, updates an abstract virtual DOM node, runs a diffing algorithm against the live DOM, and directly forces style recalculations by rewriting inline attributes at 60Hz or 120Hz.&lt;/p&gt;

&lt;p&gt;JavaScript is forced to do two distinct jobs simultaneously: &lt;strong&gt;governing business logic&lt;/strong&gt; and &lt;strong&gt;manually painting layout frames&lt;/strong&gt;. When the main thread gets busy parsing data or handling asset downloads, the animation thread drops frames, creating visible micro-stutter and lag.&lt;/p&gt;

&lt;h3&gt;
  
  
  The New Way: The Decoupled Telemetry Layer
&lt;/h3&gt;

&lt;p&gt;A CSS-Reactive ecosystem separates these concerns completely. Tools like &lt;strong&gt;State.js&lt;/strong&gt;, &lt;strong&gt;Trig.js&lt;/strong&gt;, and &lt;strong&gt;Cursor.js&lt;/strong&gt; act as non-intrusive environmental sensors. They observe state triggers, layout boundaries, and user input variables passively, streaming those raw mathematical metrics directly into the DOM as native CSS Custom Properties (&lt;code&gt;--state-hp&lt;/code&gt;, &lt;code&gt;--trig-percent&lt;/code&gt;, &lt;code&gt;--cursor-x&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Once the telemetry is saved to the CSS environment, &lt;strong&gt;JavaScript’s rendering job is completely finished.&lt;/strong&gt; The framework goes back to sleep, leaving the browser’s native C++ compositing pipeline to handle frame-by-frame sub-pixel interpolation on the hardware-accelerated GPU thread.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architectural Comparison: Building a Live Search &amp;amp; Scroll Reveal
&lt;/h2&gt;

&lt;p&gt;Let's look at a real-world scenario: an interactive landing page that tracks user scroll progress and includes a real-time, debounced search counter.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Monolithic SPA Stack (Next.js + GSAP + Lenis)
&lt;/h3&gt;

&lt;p&gt;To implement input stabilization, smooth scroll tracking, and reactive UI updates, a traditional enterprise build pulls in a massive army of tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// Splitting animation, state, and input normalization across multiple heavy libraries&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gsap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gsap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gsap/ScrollTrigger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Lenis&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@studio-freight/lenis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;searchQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSearchQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 1. Initialize input scroll hijacking to force smooth mousewheel behavior&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lenis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Lenis&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;lenis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ScrollTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;raf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;lenis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// 2. Heavy JS timeline parsing that thrashes getBoundingClientRect() at 60Hz&lt;/span&gt;
      &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;scrollTrigger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.card-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;top center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;scrub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Debounce handling logic mixed inside component lifecycle state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSearchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleInput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Interactive&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The CSS-Reactive Stack (State.js + Trig.js)
&lt;/h3&gt;

&lt;p&gt;Here is the exact same feature suite built using a priority-of-concerns architecture. There are no build tools, no compilation steps, and zero lines of structural JavaScript event listeners.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"searchScene"&lt;/span&gt; 
      &lt;span class="na"&gt;data-state&lt;/span&gt; 
      &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"queryCount"&lt;/span&gt;
      &lt;span class="na"&gt;data-queryCount=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
      &lt;span class="na"&gt;data-trig-section&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; 
         &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&lt;/span&gt;
         &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
         &lt;span class="na"&gt;data-state-trigger-on=&lt;/span&gt;&lt;span class="s"&gt;"input"&lt;/span&gt;
         &lt;span class="na"&gt;data-state-debounce=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;
         &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"searchScene"&lt;/span&gt;
         &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"queryCount"&lt;/span&gt;
         &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Interactive Element&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* 2. Style layer is the absolute authority on visual animations */&lt;/span&gt;
  &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* Trig.js provides passive, native viewport position data automatically */&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-scroll-percent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;-1px&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-scroll-normalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;/* THE MAGIC: A native CSS transition acts as the visual shock absorber,
       eliminating desktop mouse-wheel jitter without any scroll hijacking. */&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.2s&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.2s&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Strategic JS Blueprint: Extending the Playground
&lt;/h2&gt;

&lt;p&gt;A common misconception is that a CSS-Reactive paradigm forces a "No JavaScript" limitation. In reality, it unlocks an infinitely flexible &lt;strong&gt;Hybrid Playground&lt;/strong&gt;. Because the DOM serves as a unified data bus, your custom variables can be instantly ingested by advanced, specialized JS runtimes like &lt;strong&gt;GSAP&lt;/strong&gt; or &lt;strong&gt;Three.js (WebGL)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of forcing JavaScript to calculate mundane UI layouts, you dedicate its raw computational power exclusively to what it does best: heavy math orchestration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Powering a High-Fidelity 3D WebGL Camera via Trig.js Variables
&lt;/h3&gt;

&lt;p&gt;In this hybrid implementation, &lt;code&gt;Trig.js&lt;/code&gt; automates the passive DOM-intersection tracking, leaving your custom JavaScript completely clear to manage 3D spatial vector matrices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;load&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#webgl-scene&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#three-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Standard Three.js initialization boilerplate&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;WebGLRenderer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;antialias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PerspectiveCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Hook directly into the high-frequency hardware GSAP ticker&lt;/span&gt;
  &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Read the static CSS variables pre-compiled by Trig.js&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trigPercent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--trig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0 to 100&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trigDeg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--trig-deg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 0 to 360&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trigPercent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Normalize 0–1&lt;/span&gt;

    &lt;span class="c1"&gt;// Smoothly glide the WebGL camera coordinates based on environmental data&lt;/span&gt;
    &lt;span class="nx"&gt;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;z&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                     &lt;span class="c1"&gt;// Fly camera deep into the 3D grid on scroll&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trigDeg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Sway camera gently left/right&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;power2.out&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Corporations and Premium Agencies are Transitioning
&lt;/h2&gt;

&lt;p&gt;When technical leaders evaluate software architecture, they look past framework hype and calculate hard business metrics. The combination of State.js and native CSS primitives ticks every major corporate engineering box:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Hardened Supply Chain Security
&lt;/h3&gt;

&lt;p&gt;Modern projects pull down thousands of nested, unvetted &lt;code&gt;npm&lt;/code&gt; modules into their deployment pipelines, exposing corporations to catastrophic supply chain security vulnerabilities. State.js has &lt;strong&gt;zero framework dependencies&lt;/strong&gt;. It is an isolated, auditable file with a secure-by-default architecture that explicitly avoids dangerous evaluation syntax like &lt;code&gt;eval()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Massive Core Web Vitals Wins
&lt;/h3&gt;

&lt;p&gt;Google's indexing algorithms directly punish slow-loading sites. By offloading rendering calculations entirely onto the browser's internal layout thread, sites built with a CSS-Reactive architecture achieve great performance scores out of the box, reducing bounce rates and directly driving down customer acquisition costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Infinite Maintainability
&lt;/h3&gt;

&lt;p&gt;Framework standards change constantly; code written in React five years ago is often incompatible with the contemporary Next.js ecosystem. A CSS-Reactive stack leverages the permanent, everlasting standards of the web platform—&lt;strong&gt;HTML Data Attributes, MutationObservers, and CSS Custom Properties&lt;/strong&gt;. The code you write today will run identically in browsers a decade from now without ever requiring an infrastructure overhaul.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: A Reset of Balance
&lt;/h2&gt;

&lt;p&gt;The modern web platform has evolved past the need for monolithic SPA wrappers.&lt;/p&gt;

&lt;p&gt;By utilizing &lt;strong&gt;State.js&lt;/strong&gt; as your data broker and letting native &lt;strong&gt;CSS Transitions and Keyframes&lt;/strong&gt; handle the visual lifting, you reclaim the browser main thread. JavaScript is freed from the labor of layout tracking and restored to its most premium state: an extension layer for rich logic, 3D WebGL synthesis, and creative exploration.&lt;/p&gt;

&lt;p&gt;Stop fighting the browser. Let HTML house your state, let CSS drive your motion, and let JavaScript power your imagination.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How the State.js Ecosystem Solves the Performance vs. Experience Paradox in Modern E‑Commerce</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 03 Jun 2026 19:33:10 +0000</pubDate>
      <link>https://dev.to/idevgames/how-the-statejs-ecosystem-solves-the-performance-vs-experience-paradox-in-modern-e-commerce-em2</link>
      <guid>https://dev.to/idevgames/how-the-statejs-ecosystem-solves-the-performance-vs-experience-paradox-in-modern-e-commerce-em2</guid>
      <description>&lt;p&gt;Modern premium e‑commerce has a problem nobody talks about enough:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Luxury brands want fluid, tactile, high‑end interactions —&lt;br&gt;&lt;br&gt;
but the JS runtimes required to achieve them destroy performance.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Magnetic buttons.&lt;br&gt;&lt;br&gt;
Organic hover glows.&lt;br&gt;&lt;br&gt;
3D tilt cards.&lt;br&gt;&lt;br&gt;
Scroll‑reactive animations.&lt;br&gt;&lt;br&gt;
Cursor‑driven lighting.  &lt;/p&gt;

&lt;p&gt;These effects normally require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GSAP
&lt;/li&gt;
&lt;li&gt;Framer Motion
&lt;/li&gt;
&lt;li&gt;Locomotive Scroll
&lt;/li&gt;
&lt;li&gt;RAF loops
&lt;/li&gt;
&lt;li&gt;heavy math
&lt;/li&gt;
&lt;li&gt;layout thrashing
&lt;/li&gt;
&lt;li&gt;hydration
&lt;/li&gt;
&lt;li&gt;virtual DOM diffing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of which tank performance on mobile and mid‑range devices.&lt;/p&gt;

&lt;p&gt;But there’s another way.&lt;/p&gt;

&lt;p&gt;When you combine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt;&lt;/strong&gt; (reactive UI state)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/iDev-Games/Motion-JS" rel="noopener noreferrer"&gt;Motion.js&lt;/a&gt;&lt;/strong&gt; (time‑based interpolation)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/iDev-Games/Trig-JS" rel="noopener noreferrer"&gt;Trig.js&lt;/a&gt;&lt;/strong&gt; (scroll + viewport reactivity)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/iDev-Games/Cursor-JS" rel="noopener noreferrer"&gt;Cursor.js&lt;/a&gt;&lt;/strong&gt; (spatial tracking)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…you unlock a completely different architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Premium, tactile interactions powered by the browser’s native rendering engine — not a JavaScript animation runtime.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the &lt;strong&gt;Performance vs. Experience Paradox&lt;/strong&gt;, solved.&lt;/p&gt;


&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;1. The Magnetic Checkout Button (Zero JS Animation)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Luxury brands love this effect:&lt;br&gt;&lt;br&gt;
A button that &lt;em&gt;pulls&lt;/em&gt; toward your cursor like a magnet, then snaps back with a soft, premium feel.&lt;/p&gt;

&lt;p&gt;With Cursor.js + CSS, it becomes trivial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.checkout-btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.checkout-btn.cursor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cursor-x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cursor-y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No RAF loops.&lt;br&gt;&lt;br&gt;
No JS math.&lt;br&gt;&lt;br&gt;
No animation engine.&lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;native CSS transforms&lt;/strong&gt; driven by &lt;strong&gt;Cursor.js variables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The browser handles the easing.&lt;br&gt;&lt;br&gt;
The compositor handles the animation.&lt;br&gt;&lt;br&gt;
You get 120fps smoothness for free.&lt;/p&gt;


&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;2. The Dynamic Angle Glow (Zero Runtime Math)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This is the “premium hover glow” effect you see on high‑end product cards.&lt;/p&gt;

&lt;p&gt;Normally, you’d compute angles in JS every frame.&lt;/p&gt;

&lt;p&gt;With Cursor.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.product-card.cursor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--cursor-deg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;60%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cursor.js gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--cursor-x&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cursor-y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cursor-deg&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…all computed natively, efficiently, and only when needed.&lt;/p&gt;

&lt;p&gt;CSS does the rest.&lt;/p&gt;

&lt;p&gt;This is how you get that “expensive” feel without a single JS animation loop.&lt;/p&gt;




&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;3. Scroll‑Reactive Luxury Effects with Trig.js&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This is where your ecosystem becomes &lt;em&gt;unfairly&lt;/em&gt; powerful.&lt;/p&gt;

&lt;p&gt;Trig.js gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scroll progress
&lt;/li&gt;
&lt;li&gt;viewport entry/exit
&lt;/li&gt;
&lt;li&gt;element-relative percentages
&lt;/li&gt;
&lt;li&gt;direction
&lt;/li&gt;
&lt;li&gt;velocity
&lt;/li&gt;
&lt;li&gt;thresholds
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All mapped directly to CSS variables.&lt;/p&gt;

&lt;p&gt;This lets you build effects like:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Luxury product reveals&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-progress&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-progress&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Parallax hero banners&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;background-position-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-scroll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Scroll‑driven color shifts&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--trig-progress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;360&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;60%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No scroll listeners.&lt;br&gt;&lt;br&gt;
No RAF loops.&lt;br&gt;&lt;br&gt;
No math in JS.&lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;Trig.js feeding CSS&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 &lt;strong&gt;Why This Works: The Performance Secret Under the Hood&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Cursor.js, Motion.js, and Trig.js aren’t animation engines.&lt;br&gt;&lt;br&gt;
They’re &lt;strong&gt;input engines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They feed the browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spatial data
&lt;/li&gt;
&lt;li&gt;time data
&lt;/li&gt;
&lt;li&gt;scroll data
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and let CSS handle the rendering.&lt;/p&gt;

&lt;p&gt;Here’s why it’s so fast:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Passive Event Listeners&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cursor.js and Trig.js listen passively, never blocking scroll or input.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Attribute Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Element boundaries are cached.&lt;br&gt;&lt;br&gt;
No repeated layout reads.&lt;br&gt;&lt;br&gt;
No thrashing.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Selective Updates&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CSS variables only update when values actually change.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. IntersectionObserver Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If an element isn’t visible, Trig.js and Cursor.js stop tracking it entirely.&lt;/p&gt;

&lt;p&gt;This is the opposite of GSAP/Framer, which run loops regardless of visibility.&lt;/p&gt;




&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;4. Motion.js: The “Premium Feel” Layer&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Motion.js gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;time
&lt;/li&gt;
&lt;li&gt;progress
&lt;/li&gt;
&lt;li&gt;easing
&lt;/li&gt;
&lt;li&gt;looping
&lt;/li&gt;
&lt;li&gt;interpolation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets you build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;floating product cards
&lt;/li&gt;
&lt;li&gt;soft hover springs
&lt;/li&gt;
&lt;li&gt;inertia‑based sliders
&lt;/li&gt;
&lt;li&gt;time‑driven transitions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…without writing a single RAF loop.&lt;/p&gt;

&lt;p&gt;CSS handles the rendering.&lt;br&gt;&lt;br&gt;
Motion.js handles the timing.&lt;br&gt;&lt;br&gt;
The browser does the rest.&lt;/p&gt;




&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;5. The Hybrid Model That Makes It All Work&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This is the architecture that ties everything together:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;JavaScript handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;validation
&lt;/li&gt;
&lt;li&gt;pricing rules
&lt;/li&gt;
&lt;li&gt;async workflows
&lt;/li&gt;
&lt;li&gt;inventory checks
&lt;/li&gt;
&lt;li&gt;checkout logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;State.js handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UI state
&lt;/li&gt;
&lt;li&gt;layout state
&lt;/li&gt;
&lt;li&gt;toggles
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;reactive text
&lt;/li&gt;
&lt;li&gt;reactive CSS variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Motion.js handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;time
&lt;/li&gt;
&lt;li&gt;interpolation
&lt;/li&gt;
&lt;li&gt;easing
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cursor.js handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;spatial input
&lt;/li&gt;
&lt;li&gt;angles
&lt;/li&gt;
&lt;li&gt;distances
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Trig.js handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;scroll
&lt;/li&gt;
&lt;li&gt;viewport
&lt;/li&gt;
&lt;li&gt;progress
&lt;/li&gt;
&lt;li&gt;direction
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CSS handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;rendering
&lt;/li&gt;
&lt;li&gt;transforms
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;shadows
&lt;/li&gt;
&lt;li&gt;filters
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;browser-native animation engine&lt;/strong&gt; the web should have had all along.&lt;/p&gt;




&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;The E‑Commerce Payoff&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;With this ecosystem, you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;magnetic buttons
&lt;/li&gt;
&lt;li&gt;3D tilt cards
&lt;/li&gt;
&lt;li&gt;scroll‑reactive reveals
&lt;/li&gt;
&lt;li&gt;cursor‑reactive glows
&lt;/li&gt;
&lt;li&gt;inertia‑driven sliders
&lt;/li&gt;
&lt;li&gt;premium micro‑interactions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…with &lt;strong&gt;near-zero runtime overhead&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is how you deliver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;luxury feel
&lt;/li&gt;
&lt;li&gt;instant responsiveness
&lt;/li&gt;
&lt;li&gt;perfect smoothness
&lt;/li&gt;
&lt;li&gt;minimal JS
&lt;/li&gt;
&lt;li&gt;maximum battery life
&lt;/li&gt;
&lt;li&gt;maximum accessibility
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you do it using &lt;strong&gt;the browser’s native rendering pipeline&lt;/strong&gt;, not a JS animation engine.&lt;/p&gt;




&lt;h1&gt;
  
  
  🟢 &lt;strong&gt;Final Thought&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The State.js ecosystem isn’t “another frontend framework.”&lt;/p&gt;

&lt;p&gt;It’s a &lt;strong&gt;new way to build premium, tactile, high‑performance web experiences&lt;/strong&gt; using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;declarative UI
&lt;/li&gt;
&lt;li&gt;native CSS
&lt;/li&gt;
&lt;li&gt;minimal JS
&lt;/li&gt;
&lt;li&gt;browser‑native rendering
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how you break out of the Performance vs. Experience Paradox — and build e‑commerce that feels &lt;em&gt;alive&lt;/em&gt; without sacrificing speed.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Hybrid Architecture That Makes State.js Unstoppable</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 03 Jun 2026 18:32:19 +0000</pubDate>
      <link>https://dev.to/idevgames/the-hybrid-architecture-that-makes-statejs-unstoppable-1gnf</link>
      <guid>https://dev.to/idevgames/the-hybrid-architecture-that-makes-statejs-unstoppable-1gnf</guid>
      <description>&lt;p&gt;&lt;em&gt;(Declarative UI + Imperative Logic = The Sweet Spot)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most HTML‑first frameworks hit a hard boundary the moment your UI logic becomes procedural, multi‑step, or algorithmic. Cross‑field validation, async inventory checks, dynamic pricing rules — these are not things you should try to express inside declarative attributes.&lt;/p&gt;

&lt;p&gt;But here’s the part people miss:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; was never designed to replace JavaScript.&lt;br&gt;&lt;br&gt;
It was designed to replace DOM code.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And when you pair &lt;strong&gt;standard JavaScript&lt;/strong&gt; for the heavy logic with &lt;strong&gt;State.js&lt;/strong&gt; for the visual reactions, something magical happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No DOM manipulation
&lt;/li&gt;
&lt;li&gt;No class toggling
&lt;/li&gt;
&lt;li&gt;No template re-rendering
&lt;/li&gt;
&lt;li&gt;No hydration
&lt;/li&gt;
&lt;li&gt;No virtual DOM
&lt;/li&gt;
&lt;li&gt;No framework lifecycle overhead
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just &lt;strong&gt;pure logic → pure UI&lt;/strong&gt;, with the browser doing the rendering work natively.&lt;/p&gt;

&lt;p&gt;This hybrid model is not a workaround.&lt;br&gt;&lt;br&gt;
It’s the &lt;em&gt;ideal architecture&lt;/em&gt; for State.js.&lt;/p&gt;


&lt;h2&gt;
  
  
  🟢 &lt;strong&gt;Why This Hybrid Model Works So Well&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. True Separation of Concerns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your JavaScript does nothing but compute data.&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;querySelector&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
No &lt;code&gt;classList.add&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
No “toggle this element when that element changes.”&lt;/p&gt;

&lt;p&gt;Your HTML/CSS does nothing but react to state.&lt;/p&gt;

&lt;p&gt;This is the cleanest separation you can get on the web.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2. Zero Framework Lock‑In&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If a developer knows JavaScript, they can write the logic.&lt;/p&gt;

&lt;p&gt;If they know HTML/CSS, they can build the UI.&lt;/p&gt;

&lt;p&gt;There are no lifecycle hooks, no component trees, no hydration rules, no custom syntax to learn.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;3. Native Performance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;formEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attributes
&lt;/li&gt;
&lt;li&gt;CSS variables
&lt;/li&gt;
&lt;li&gt;text bindings
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…all using the browser’s native rendering pipeline.&lt;/p&gt;

&lt;p&gt;No diffing.&lt;br&gt;&lt;br&gt;
No reconciliation.&lt;br&gt;&lt;br&gt;
No memory churn.&lt;/p&gt;

&lt;p&gt;Just instant paint.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟢 &lt;strong&gt;A Real E‑Commerce Example (The Live Pattern)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s what a real checkout validation flow looks like using the hybrid model.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. The HTML (Clean &amp;amp; Semantic)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"checkout-form"&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-shipping-cost=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;data-valid=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zipcode"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Enter Zip Code"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-condition=&lt;/span&gt;&lt;span class="s"&gt;"valid == false"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"error-msg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Please enter a valid shipping address.
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-condition=&lt;/span&gt;&lt;span class="s"&gt;"valid == true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"success-msg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Shipping calculated! Cost: £&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"shipping-cost"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No JS logic.&lt;br&gt;&lt;br&gt;
No DOM manipulation.&lt;br&gt;&lt;br&gt;
Just declarative UI.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. The JavaScript (Pure Logic)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checkout-form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zipInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zipcode&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;zipInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/shipping?zip=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;formEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shippingCost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;formEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;formEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No DOM updates.&lt;br&gt;&lt;br&gt;
No class toggles.&lt;br&gt;&lt;br&gt;
No template re-renders.&lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;data → state → UI&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟢 &lt;strong&gt;Why This Matters for E‑Commerce&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;E‑commerce is 90% UI state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cart drawer open/close
&lt;/li&gt;
&lt;li&gt;variant switching
&lt;/li&gt;
&lt;li&gt;“free shipping” progress bars
&lt;/li&gt;
&lt;li&gt;quantity selectors
&lt;/li&gt;
&lt;li&gt;error/success messages
&lt;/li&gt;
&lt;li&gt;loading states
&lt;/li&gt;
&lt;li&gt;stock indicators
&lt;/li&gt;
&lt;li&gt;modal popups
&lt;/li&gt;
&lt;li&gt;mobile menus
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js handles all of this declaratively and instantly.&lt;/p&gt;

&lt;p&gt;The remaining 10% — the business logic — belongs in JavaScript or the backend.&lt;/p&gt;

&lt;p&gt;And that’s exactly how it should be.&lt;/p&gt;




&lt;h2&gt;
  
  
  🟢 &lt;strong&gt;The Final Architecture (The One That Actually Scales)&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;State.js handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UI state
&lt;/li&gt;
&lt;li&gt;visual state
&lt;/li&gt;
&lt;li&gt;layout state
&lt;/li&gt;
&lt;li&gt;animations
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;toggles
&lt;/li&gt;
&lt;li&gt;progress bars
&lt;/li&gt;
&lt;li&gt;variant switching
&lt;/li&gt;
&lt;li&gt;micro‑interactions
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;JavaScript handles:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;validation
&lt;/li&gt;
&lt;li&gt;pricing rules
&lt;/li&gt;
&lt;li&gt;async workflows
&lt;/li&gt;
&lt;li&gt;inventory checks
&lt;/li&gt;
&lt;li&gt;checkout logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Together:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You get a system that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simpler than React
&lt;/li&gt;
&lt;li&gt;cleaner than Alpine
&lt;/li&gt;
&lt;li&gt;more expressive than HTMX
&lt;/li&gt;
&lt;li&gt;more native than Stimulus
&lt;/li&gt;
&lt;li&gt;more flexible than Web Components
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the architecture that makes &lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; “unstoppable.”&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 State.js - Build Reactive, Interactive UIs Using Only HTML + CSS</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 03 Jun 2026 13:36:57 +0000</pubDate>
      <link>https://dev.to/idevgames/statejs-build-reactive-interactive-uis-using-only-html-css-1n85</link>
      <guid>https://dev.to/idevgames/statejs-build-reactive-interactive-uis-using-only-html-css-1n85</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State.js flips that model on its head.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It turns &lt;strong&gt;HTML data attributes&lt;/strong&gt; into a fully reactive UI engine - exposing your element’s state as &lt;strong&gt;CSS variables&lt;/strong&gt;, updating automatically, and letting you build dynamic interfaces without you writing any &lt;em&gt;JavaScript logic&lt;/em&gt; yourself.&lt;/p&gt;

&lt;p&gt;If you know HTML and CSS, you already know how to use State.js.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;✨ What State.js Actually Does (In Plain English)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; watches your HTML elements and automatically exposes their state as CSS variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data-health="75" → --state-health: 75
data-health-max="100" → --state-health-percent: 75%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you use those variables in CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.health-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-health-percent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the attribute → UI updates instantly → CSS animates it.&lt;/p&gt;

&lt;p&gt;No JS functions.&lt;br&gt;&lt;br&gt;
No components.&lt;br&gt;&lt;br&gt;
No re-renders.&lt;br&gt;&lt;br&gt;
No virtual DOM.&lt;br&gt;&lt;br&gt;
Just HTML + CSS.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;🔥 Why Developers Love It&lt;/strong&gt;
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. You don't need to write any JavaScript Logic&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dashboards
&lt;/li&gt;
&lt;li&gt;progress bars
&lt;/li&gt;
&lt;li&gt;form interactions
&lt;/li&gt;
&lt;li&gt;clicker games
&lt;/li&gt;
&lt;li&gt;idle games
&lt;/li&gt;
&lt;li&gt;RPG UIs
&lt;/li&gt;
&lt;li&gt;video players
&lt;/li&gt;
&lt;li&gt;reactive animations
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…without writing a single line of JS.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Designers Can Work Directly in the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;State.js exposes everything as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS variables
&lt;/li&gt;
&lt;li&gt;data attributes
&lt;/li&gt;
&lt;li&gt;conditional classes
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Designers don’t need to touch JS files or understand framework lifecycles.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Backend‑First Friendly&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Works perfectly with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel
&lt;/li&gt;
&lt;li&gt;Rails
&lt;/li&gt;
&lt;li&gt;WordPress
&lt;/li&gt;
&lt;li&gt;Django
&lt;/li&gt;
&lt;li&gt;Phoenix
&lt;/li&gt;
&lt;li&gt;HTMX
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No bundlers.&lt;br&gt;&lt;br&gt;
No hydration.&lt;br&gt;&lt;br&gt;
No client‑side routing.&lt;br&gt;&lt;br&gt;
Just reactive HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Game‑Dev Ready&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;State.js includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timers
&lt;/li&gt;
&lt;li&gt;computed values
&lt;/li&gt;
&lt;li&gt;sound effects
&lt;/li&gt;
&lt;li&gt;persistence
&lt;/li&gt;
&lt;li&gt;event dispatch
&lt;/li&gt;
&lt;li&gt;interval triggers
&lt;/li&gt;
&lt;li&gt;auto‑fire logic
&lt;/li&gt;
&lt;li&gt;conditional classes
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build a full idle game in pure HTML.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;⚡ What You Can Build in 30 Seconds&lt;/strong&gt;
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A clicker game:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"clicker"&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-score=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"score"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Score: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"score"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
            &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"clicker"&lt;/span&gt;
            &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"score"&lt;/span&gt;
            &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Click Me!
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;A health bar:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"75"&lt;/span&gt; &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;data-state-var=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: var(--state-hp-percent);"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;A form that tracks focus + changes:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger-on=&lt;/span&gt;&lt;span class="s"&gt;"focus"&lt;/span&gt;
       &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt; &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"focusCount"&lt;/span&gt; &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;A video progress bar:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;video&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-progress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;A toggleable UI state:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-state-toggles=&lt;/span&gt;&lt;span class="s"&gt;"active"&lt;/span&gt; &lt;span class="na"&gt;data-active=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  &lt;strong&gt;🧩 The Magic Primitives (The 80% You Need to Know)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Here are the core building blocks that let you build anything:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. &lt;code&gt;data-state&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Turns an element into a reactive state container.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. &lt;code&gt;data-state-watch="attr1,attr2"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Watches attributes and exposes them as CSS variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. &lt;code&gt;data-state-trigger&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Makes an element update state when interacted with.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. &lt;code&gt;data-state-attr="health"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Which attribute to update.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. &lt;code&gt;data-state-increment="10"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add to a value.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. &lt;code&gt;data-state-set="100"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Set a value exactly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;7. &lt;code&gt;data-state-condition="gold &amp;gt;= 50"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Only fire if condition is true.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;8. &lt;code&gt;data-state-autofire="true"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Fire automatically when condition becomes true.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;9. &lt;code&gt;data-state-text="HP {hp}/{hpmax}"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Template string interpolation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;10. &lt;code&gt;data-state-class="critical"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Conditional CSS classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;11. &lt;code&gt;data-state-interval="1000"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run triggers every N ms (timers, regen, idle loops).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;12. &lt;code&gt;data-state-sound="coin"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Play procedural sound effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;13. &lt;code&gt;data-state-persist="true"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Save + restore state from localStorage.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;14. &lt;code&gt;data-state-trigger-on="input|scroll|mouseenter|submit"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Event‑based triggers with debounce/throttle.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;15. &lt;code&gt;data-state-include="component.html"&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;HTML includes — reusable components with no build step.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;🎮 Example: A Full Idle Game in Pure HTML&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;You can literally build this with no JS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gold counter
&lt;/li&gt;
&lt;li&gt;click power
&lt;/li&gt;
&lt;li&gt;upgrades
&lt;/li&gt;
&lt;li&gt;level scaling
&lt;/li&gt;
&lt;li&gt;passive income
&lt;/li&gt;
&lt;li&gt;auto‑leveling
&lt;/li&gt;
&lt;li&gt;sound effects
&lt;/li&gt;
&lt;li&gt;persistence
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All declarative.&lt;/p&gt;

&lt;p&gt;This is why State.js is exploding in game‑dev circles.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;🎨 Example: A Fully Reactive UI Component&lt;/strong&gt;
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"player"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"health,mana,xp"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-var=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
     &lt;span class="na"&gt;data-health=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-mana=&lt;/span&gt;&lt;span class="s"&gt;"80"&lt;/span&gt;
     &lt;span class="na"&gt;data-xp=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"health"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: var(--state-health-percent)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mana"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: var(--state-mana-percent)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"xp"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: var(--state-xp-percent)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS handles the rest.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;🧠 Why This Works: The Mental Model&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;State.js is built on one simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTML holds the data.&lt;br&gt;&lt;br&gt;
CSS reacts to the data.&lt;br&gt;&lt;br&gt;
State.js keeps them in sync.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;No components.&lt;br&gt;&lt;br&gt;
No framework.&lt;br&gt;&lt;br&gt;
No build step.&lt;br&gt;&lt;br&gt;
No hydration.&lt;br&gt;&lt;br&gt;
No virtual DOM.  &lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;declarative UI&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;🚀 Want to Go Deeper?&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;README&lt;/a&gt; is your full reference manual — every primitive, every example, every advanced feature.&lt;/p&gt;

&lt;p&gt;But with what you’ve learned here, you can already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build reactive dashboards
&lt;/li&gt;
&lt;li&gt;build interactive UI
&lt;/li&gt;
&lt;li&gt;build game interfaces
&lt;/li&gt;
&lt;li&gt;build idle games
&lt;/li&gt;
&lt;li&gt;build RPG UIs
&lt;/li&gt;
&lt;li&gt;build form logic
&lt;/li&gt;
&lt;li&gt;build video players
&lt;/li&gt;
&lt;li&gt;build reusable components
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All with &lt;strong&gt;HTML + CSS only&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;View the repo &lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A New Stack for Turning HTML &amp; CSS Into an Application Layer</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Tue, 02 Jun 2026 13:44:54 +0000</pubDate>
      <link>https://dev.to/idevgames/a-new-stack-for-turning-html-css-into-an-application-layer-27b0</link>
      <guid>https://dev.to/idevgames/a-new-stack-for-turning-html-css-into-an-application-layer-27b0</guid>
      <description>&lt;p&gt;&lt;em&gt;(&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt;, &lt;a href="https://github.com/iDev-Games/Motion-JS" rel="noopener noreferrer"&gt;Motion.js&lt;/a&gt;, &lt;a href="https://github.com/iDev-Games/Gravity-JS" rel="noopener noreferrer"&gt;Gravity.js&lt;/a&gt;, &lt;a href="https://github.com/iDev-Games/Cursor-JS" rel="noopener noreferrer"&gt;Cursor.js&lt;/a&gt;, &lt;a href="https://github.com/iDev-Games/Keys-JS" rel="noopener noreferrer"&gt;Keys.js&lt;/a&gt; — a browser‑native ecosystem)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For years, frontend development has revolved around one assumption:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you want interactivity, state, animation, or physics — you need a framework.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React, Vue, Svelte, Solid… all incredible tools, but they all share the same core idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JS owns the state
&lt;/li&gt;
&lt;li&gt;JS owns the rendering
&lt;/li&gt;
&lt;li&gt;JS owns the reactivity
&lt;/li&gt;
&lt;li&gt;JS owns the lifecycle
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTML and CSS are treated as passive output layers.&lt;/p&gt;

&lt;p&gt;But what if that assumption is wrong?&lt;/p&gt;

&lt;p&gt;What if the browser already &lt;em&gt;has&lt;/em&gt; the primitives we need — and we just haven’t been using them as a unified system?&lt;/p&gt;

&lt;p&gt;That’s the question that led me to build a small ecosystem of libraries that all share one philosophy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Expose browser signals to CSS.&lt;br&gt;&lt;br&gt;
Let HTML declare behaviour.&lt;br&gt;&lt;br&gt;
Let CSS render it.&lt;br&gt;&lt;br&gt;
Use JS only as the glue.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This post introduces that ecosystem.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Why This Stack Exists&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Modern frontend development is powerful — but also heavy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundlers
&lt;/li&gt;
&lt;li&gt;Virtual DOMs
&lt;/li&gt;
&lt;li&gt;Component compilers
&lt;/li&gt;
&lt;li&gt;State libraries
&lt;/li&gt;
&lt;li&gt;Effect systems
&lt;/li&gt;
&lt;li&gt;Re-renders
&lt;/li&gt;
&lt;li&gt;Signals
&lt;/li&gt;
&lt;li&gt;Hooks
&lt;/li&gt;
&lt;li&gt;Stores
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All to build things the browser can already do.&lt;/p&gt;

&lt;p&gt;Meanwhile, CSS has quietly evolved into a &lt;em&gt;reactive rendering engine&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS variables
&lt;/li&gt;
&lt;li&gt;calc()
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;animations
&lt;/li&gt;
&lt;li&gt;container queries
&lt;/li&gt;
&lt;li&gt;view transitions
&lt;/li&gt;
&lt;li&gt;scroll-driven animations
&lt;/li&gt;
&lt;li&gt;:has()
&lt;/li&gt;
&lt;li&gt;@property
&lt;/li&gt;
&lt;li&gt;custom easing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And HTML has evolved into a &lt;em&gt;declarative configuration surface&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attributes
&lt;/li&gt;
&lt;li&gt;custom elements
&lt;/li&gt;
&lt;li&gt;dataset
&lt;/li&gt;
&lt;li&gt;templates
&lt;/li&gt;
&lt;li&gt;inert
&lt;/li&gt;
&lt;li&gt;popovers
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the question became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What if we treat HTML + CSS as the application layer,&lt;br&gt;&lt;br&gt;
and JavaScript as the runtime that feeds them state?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the foundation of this stack.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;The Stack (Browser‑Native, Declarative, Modular)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Each library does one thing, exposes one set of signals, and stays tiny.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. State.js&lt;/strong&gt; — &lt;em&gt;CSS‑Reactive State Engine&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;State.js exposes reactive state directly to CSS variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"player"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"health,score"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-var=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
     &lt;span class="na"&gt;data-health=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-health-min=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-health-max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-score=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"health-bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No re-renders.&lt;br&gt;&lt;br&gt;
No virtual DOM.&lt;br&gt;&lt;br&gt;
No diffing.&lt;br&gt;&lt;br&gt;
Just state → CSS → rendering.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;2. Motion.js&lt;/strong&gt; — &lt;em&gt;Scroll, Time &amp;amp; Viewport Signals&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Motion.js exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scroll progress
&lt;/li&gt;
&lt;li&gt;element visibility
&lt;/li&gt;
&lt;li&gt;time
&lt;/li&gt;
&lt;li&gt;easing
&lt;/li&gt;
&lt;li&gt;playback
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…as CSS variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-motion&lt;/span&gt; &lt;span class="na"&gt;data-motion-var=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;data-motion-duration=&lt;/span&gt;&lt;span class="s"&gt;"2000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- CSS animates based on scroll/time --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;3. Gravity.js&lt;/strong&gt; — &lt;em&gt;Physics Exposed to CSS&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Gravity.js simulates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gravity
&lt;/li&gt;
&lt;li&gt;velocity
&lt;/li&gt;
&lt;li&gt;friction
&lt;/li&gt;
&lt;li&gt;forces
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and uses CSS transform to simulate physics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-gravity&lt;/span&gt; &lt;span class="na"&gt;data-gravity-type=&lt;/span&gt;&lt;span class="s"&gt;"static"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- CSS animates based on physics --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets designers build physical-feeling interfaces without writing physics code.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Cursor.js&lt;/strong&gt; — &lt;em&gt;Cursor State as CSS Variables&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Cursor.js exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x/y position
&lt;/li&gt;
&lt;li&gt;velocity
&lt;/li&gt;
&lt;li&gt;direction
&lt;/li&gt;
&lt;li&gt;hover state
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…to CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-cursor&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- CSS reacts to cursor movement --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;5. Keys.js&lt;/strong&gt; — &lt;em&gt;Keyboard State as CSS Variables&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Keys.js exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;key pressed
&lt;/li&gt;
&lt;li&gt;key held
&lt;/li&gt;
&lt;li&gt;key released
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…to CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-keys&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- CSS reacts to keyboard input --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  &lt;strong&gt;Why This Works&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Because CSS is already a reactive rendering engine.&lt;/p&gt;

&lt;p&gt;When you expose state to CSS variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS handles the rendering
&lt;/li&gt;
&lt;li&gt;CSS handles the animation
&lt;/li&gt;
&lt;li&gt;CSS handles the interpolation
&lt;/li&gt;
&lt;li&gt;CSS handles the transitions
&lt;/li&gt;
&lt;li&gt;CSS handles the layout
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the state updater
&lt;/li&gt;
&lt;li&gt;the signal provider
&lt;/li&gt;
&lt;li&gt;the glue
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not the renderer.&lt;/p&gt;

&lt;p&gt;This flips the traditional model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional&lt;/th&gt;
&lt;th&gt;This Stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JS renders&lt;/td&gt;
&lt;td&gt;CSS renders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS animates&lt;/td&gt;
&lt;td&gt;CSS animates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS manages state&lt;/td&gt;
&lt;td&gt;JS exposes state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML is passive&lt;/td&gt;
&lt;td&gt;HTML is declarative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS is styling&lt;/td&gt;
&lt;td&gt;CSS is reactive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Why Not Just Use React?&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;React is incredible — but it’s a &lt;strong&gt;UI framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This stack is a &lt;strong&gt;browser-native runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;React owns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rendering
&lt;/li&gt;
&lt;li&gt;state
&lt;/li&gt;
&lt;li&gt;components
&lt;/li&gt;
&lt;li&gt;lifecycle
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stack owns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signals
&lt;/li&gt;
&lt;li&gt;state exposure
&lt;/li&gt;
&lt;li&gt;declarative behaviour
&lt;/li&gt;
&lt;li&gt;CSS-driven rendering
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They’re not competitors.&lt;br&gt;&lt;br&gt;
They’re different layers.&lt;/p&gt;

&lt;p&gt;You could even use them &lt;em&gt;together&lt;/em&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;What This Enables&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This stack makes it trivial to build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;physical-feeling UI
&lt;/li&gt;
&lt;li&gt;scroll-reactive UI
&lt;/li&gt;
&lt;li&gt;cursor-reactive UI
&lt;/li&gt;
&lt;li&gt;keyboard-reactive UI
&lt;/li&gt;
&lt;li&gt;time-based UI
&lt;/li&gt;
&lt;li&gt;stateful UI
&lt;/li&gt;
&lt;li&gt;animated UI
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…without writing application logic.&lt;/p&gt;

&lt;p&gt;It also opens the door to something bigger:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A new authoring medium where designers can build interactive systems without touching JS.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Figma-like tools that export real interactions
&lt;/li&gt;
&lt;li&gt;CSS-driven physics
&lt;/li&gt;
&lt;li&gt;declarative behaviour graphs
&lt;/li&gt;
&lt;li&gt;HTML as the app layer
&lt;/li&gt;
&lt;li&gt;CSS as the rendering engine
&lt;/li&gt;
&lt;li&gt;JS as the runtime
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the direction the web has been moving toward for years.&lt;/p&gt;

&lt;p&gt;This stack just pushes it further.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Where This Goes Next&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This isn’t a framework.&lt;br&gt;&lt;br&gt;
It’s not a React competitor.&lt;br&gt;&lt;br&gt;
It’s not a “React killer.”&lt;/p&gt;

&lt;p&gt;It’s a &lt;strong&gt;new layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A browser-native layer.&lt;/p&gt;

&lt;p&gt;A declarative layer.&lt;/p&gt;

&lt;p&gt;A layer that asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much interactivity can we get from HTML + CSS before we need application code?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the answer so far is:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;More than people think.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;If You Want to Explore the Stack&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Here are the individual libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;&lt;strong&gt;State.js&lt;/strong&gt;&lt;/a&gt; — CSS-reactive state
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Motion-JS" rel="noopener noreferrer"&gt;&lt;strong&gt;Motion.js&lt;/strong&gt;&lt;/a&gt; — scroll/time signals
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Gravity-JS" rel="noopener noreferrer"&gt;&lt;strong&gt;Gravity.js&lt;/strong&gt;&lt;/a&gt; — physics signals
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Cursor-JS" rel="noopener noreferrer"&gt;&lt;strong&gt;Cursor.js&lt;/strong&gt;&lt;/a&gt; — cursor signals
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Keys-JS" rel="noopener noreferrer"&gt;&lt;strong&gt;Keys.js&lt;/strong&gt;&lt;/a&gt; — keyboard signals
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one is tiny, focused, and works independently.&lt;/p&gt;

&lt;p&gt;But together, they form something new.&lt;/p&gt;

&lt;p&gt;A stack.&lt;br&gt;&lt;br&gt;
A philosophy.&lt;br&gt;&lt;br&gt;
A new way of thinking about the browser.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>beginners</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Scale Misconception: Why State.js Scales Endlessly (Where Traditional SPAs Fail)</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Mon, 01 Jun 2026 14:22:07 +0000</pubDate>
      <link>https://dev.to/idevgames/the-scale-misconception-why-statejs-scales-endlessly-where-traditional-spas-fail-2k8k</link>
      <guid>https://dev.to/idevgames/the-scale-misconception-why-statejs-scales-endlessly-where-traditional-spas-fail-2k8k</guid>
      <description>&lt;p&gt;For years, frontend developers have been told the same thing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to build a large-scale application, you need a large-scale JavaScript framework.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The assumption is everywhere. If your application is expected to grow, you're expected to adopt a complex client-side architecture built around React, Vue, Angular, or another framework that manages application state entirely within the browser.&lt;/p&gt;

&lt;p&gt;The industry has largely accepted this as fact.&lt;/p&gt;

&lt;p&gt;But what if we've misunderstood what "scaling" actually means?&lt;/p&gt;

&lt;p&gt;Because in practice, many large Single Page Applications (SPAs) don't scale by becoming simpler, faster, or easier to maintain. They scale by accumulating more client-side state, larger JavaScript bundles, more hydration overhead, and increasingly complex frontend architectures.&lt;/p&gt;

&lt;p&gt;State.js takes a fundamentally different approach.&lt;/p&gt;

&lt;p&gt;Instead of treating the browser as an application server, State.js acts as a lightweight visual orchestration layer for the DOM. Business logic remains on the backend where it belongs, while State.js handles reactive visual state directly within HTML and CSS.&lt;/p&gt;

&lt;p&gt;The result is an architecture that can scale from a simple landing page to a massive enterprise platform without requiring an ever-growing client-side application layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modern Misunderstanding of Frontend Scalability
&lt;/h2&gt;

&lt;p&gt;When developers talk about scalability, they're often referring to frontend frameworks and state management solutions.&lt;/p&gt;

&lt;p&gt;Questions usually sound like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can React handle a million users?&lt;/li&gt;
&lt;li&gt;Will Vue scale with a growing codebase?&lt;/li&gt;
&lt;li&gt;Should enterprise applications use Angular?&lt;/li&gt;
&lt;li&gt;Which frontend framework scales best?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is that these questions focus on tooling instead of architecture.&lt;/p&gt;

&lt;p&gt;A frontend framework doesn't determine whether an application scales.&lt;/p&gt;

&lt;p&gt;Architectural boundaries do.&lt;/p&gt;

&lt;p&gt;Most applications struggle to scale because responsibilities become blurred. Business logic, security concerns, application data, visual state, and rendering behavior become tightly coupled inside the browser.&lt;/p&gt;

&lt;p&gt;As complexity increases, the frontend grows into a second application that mirrors the backend.&lt;/p&gt;

&lt;p&gt;That's where scalability problems begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proper Separation of Concerns: Security and Logic
&lt;/h2&gt;

&lt;p&gt;To understand why State.js scales differently, it's important to separate two completely different categories of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business-Critical Data
&lt;/h3&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication&lt;/li&gt;
&lt;li&gt;Financial transactions&lt;/li&gt;
&lt;li&gt;Permission validation&lt;/li&gt;
&lt;li&gt;Database operations&lt;/li&gt;
&lt;li&gt;API integrations&lt;/li&gt;
&lt;li&gt;Business rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This data is sensitive, authoritative, and security-critical.&lt;/p&gt;

&lt;p&gt;It belongs on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual State
&lt;/h3&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether a menu is open&lt;/li&gt;
&lt;li&gt;Which tab is active&lt;/li&gt;
&lt;li&gt;Animation progress&lt;/li&gt;
&lt;li&gt;Component visibility&lt;/li&gt;
&lt;li&gt;Theme preferences&lt;/li&gt;
&lt;li&gt;Interactive UI behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This state exists purely to control presentation.&lt;/p&gt;

&lt;p&gt;It belongs in the frontend.&lt;/p&gt;

&lt;p&gt;The distinction seems obvious, yet modern SPA architectures frequently blur these responsibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SPA Mistake
&lt;/h2&gt;

&lt;p&gt;Traditional Single Page Applications often require developers to rebuild large portions of their backend architecture in JavaScript.&lt;/p&gt;

&lt;p&gt;The process usually looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch raw JSON from APIs&lt;/li&gt;
&lt;li&gt;Store it in a frontend state manager&lt;/li&gt;
&lt;li&gt;Validate and transform the data&lt;/li&gt;
&lt;li&gt;Synchronize state across components&lt;/li&gt;
&lt;li&gt;Reconstruct UI from that state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The frontend effectively becomes a second application layer.&lt;/p&gt;

&lt;p&gt;As systems grow, developers end up managing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large client-side state trees&lt;/li&gt;
&lt;li&gt;Complex dependency chains&lt;/li&gt;
&lt;li&gt;Hydration issues&lt;/li&gt;
&lt;li&gt;State synchronization problems&lt;/li&gt;
&lt;li&gt;Security considerations&lt;/li&gt;
&lt;li&gt;Performance bottlenecks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The browser becomes responsible for work that the server is already capable of handling.&lt;/p&gt;

&lt;p&gt;This duplication introduces complexity that often gets mistaken for scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State.js Approach
&lt;/h2&gt;

&lt;p&gt;State.js follows a much simpler principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The backend remains the source of truth.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you're using Laravel, WordPress, Ruby on Rails, Node.js, Django, or another backend framework, your server handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Business rules&lt;/li&gt;
&lt;li&gt;Database interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server renders the HTML.&lt;/p&gt;

&lt;p&gt;State.js then operates directly at the DOM layer, managing visual behavior without attempting to duplicate backend responsibilities.&lt;/p&gt;

&lt;p&gt;Instead of building and maintaining massive JavaScript object trees, State.js connects state directly to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML attributes&lt;/li&gt;
&lt;li&gt;CSS custom properties&lt;/li&gt;
&lt;li&gt;DOM elements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a clear separation between application logic and presentation logic.&lt;/p&gt;

&lt;p&gt;Security stays on the server.&lt;/p&gt;

&lt;p&gt;Interactivity stays in the browser.&lt;/p&gt;

&lt;p&gt;Each layer performs the task it was designed to handle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Architecture Scales Better
&lt;/h2&gt;

&lt;p&gt;The biggest scalability gains don't come from adding more frontend infrastructure.&lt;/p&gt;

&lt;p&gt;They come from reducing unnecessary complexity.&lt;/p&gt;

&lt;p&gt;State.js achieves this through architectural simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Business Logic Duplication
&lt;/h3&gt;

&lt;p&gt;The backend remains responsible for data and business rules.&lt;/p&gt;

&lt;p&gt;You don't need to recreate validation systems, permission layers, or database structures inside the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller JavaScript Footprint
&lt;/h3&gt;

&lt;p&gt;Because State.js focuses exclusively on visual state, applications avoid shipping unnecessary client-side infrastructure.&lt;/p&gt;

&lt;p&gt;Smaller bundles mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster page loads&lt;/li&gt;
&lt;li&gt;Better mobile performance&lt;/li&gt;
&lt;li&gt;Lower memory consumption&lt;/li&gt;
&lt;li&gt;Improved user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reduced Cognitive Overhead
&lt;/h3&gt;

&lt;p&gt;Developers can reason about systems more easily when responsibilities are clearly separated.&lt;/p&gt;

&lt;p&gt;The backend handles business logic.&lt;/p&gt;

&lt;p&gt;State.js handles presentation state.&lt;/p&gt;

&lt;p&gt;There is no ambiguity about where functionality belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling Everywhere HTML Exists
&lt;/h2&gt;

&lt;p&gt;One of the most overlooked benefits of State.js is its portability.&lt;/p&gt;

&lt;p&gt;Because it operates directly on native HTML and the DOM, it works virtually anywhere HTML is generated.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel applications&lt;/li&gt;
&lt;li&gt;WordPress websites&lt;/li&gt;
&lt;li&gt;Ruby on Rails platforms&lt;/li&gt;
&lt;li&gt;Node.js servers&lt;/li&gt;
&lt;li&gt;PHP applications&lt;/li&gt;
&lt;li&gt;Enterprise CMS systems&lt;/li&gt;
&lt;li&gt;Static site generators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex build pipelines&lt;/li&gt;
&lt;li&gt;Framework migrations&lt;/li&gt;
&lt;li&gt;Hydration layers&lt;/li&gt;
&lt;li&gt;Frontend rewrites&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You simply integrate State.js into existing HTML output.&lt;/p&gt;

&lt;p&gt;This makes it particularly attractive for organizations with large legacy systems that need modern interactivity without rebuilding their entire frontend stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Scalable E-Commerce Example
&lt;/h2&gt;

&lt;p&gt;Consider a shopping cart.&lt;/p&gt;

&lt;p&gt;Many SPA architectures maintain the entire cart structure in browser memory, synchronizing changes between components and APIs.&lt;/p&gt;

&lt;p&gt;With State.js, the server remains responsible for cart management.&lt;/p&gt;

&lt;p&gt;The frontend simply reflects the current state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"cart-manager"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-items=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-total=&lt;/span&gt;&lt;span class="s"&gt;"149.99"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-view=&lt;/span&gt;&lt;span class="s"&gt;"summary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cart-badge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        var(--state-items)
    &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cart-overlay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user adds an item:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A background request updates the server&lt;/li&gt;
&lt;li&gt;The server calculates the new state&lt;/li&gt;
&lt;li&gt;Updated attributes are returned&lt;/li&gt;
&lt;li&gt;State.js updates the DOM&lt;/li&gt;
&lt;li&gt;CSS handles the visual transition&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The browser focuses on rendering.&lt;/p&gt;

&lt;p&gt;The server focuses on business logic.&lt;/p&gt;

&lt;p&gt;Each system performs the work it does best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why State.js Scales Endlessly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zero Long-Term State Accumulation
&lt;/h3&gt;

&lt;p&gt;Many frontend architectures maintain increasingly large state trees as applications grow.&lt;/p&gt;

&lt;p&gt;State.js binds directly to DOM elements instead.&lt;/p&gt;

&lt;p&gt;When elements are removed, browsers naturally garbage-collect associated state.&lt;/p&gt;

&lt;p&gt;This minimizes long-term memory growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Hydration Overhead
&lt;/h3&gt;

&lt;p&gt;Hydration is one of the largest performance costs in modern frontend applications.&lt;/p&gt;

&lt;p&gt;The browser must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download JavaScript&lt;/li&gt;
&lt;li&gt;Parse JavaScript&lt;/li&gt;
&lt;li&gt;Execute JavaScript&lt;/li&gt;
&lt;li&gt;Reconstruct application state&lt;/li&gt;
&lt;li&gt;Attach event handlers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js avoids this process by operating directly on rendered HTML.&lt;/p&gt;

&lt;p&gt;Interactive behavior becomes available immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Works with Monoliths and Micro-Frontends
&lt;/h3&gt;

&lt;p&gt;Whether your architecture consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One large backend&lt;/li&gt;
&lt;li&gt;Multiple services&lt;/li&gt;
&lt;li&gt;Distributed micro-frontends&lt;/li&gt;
&lt;li&gt;Hybrid systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js remains consistent.&lt;/p&gt;

&lt;p&gt;Any HTML-producing service can emit compatible state attributes without interfering with others.&lt;/p&gt;

&lt;p&gt;This flexibility allows organizations to evolve their architecture without rewriting frontend state management systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Benefits of Server-First Architecture
&lt;/h2&gt;

&lt;p&gt;Security is rarely discussed in frontend scalability conversations.&lt;/p&gt;

&lt;p&gt;It should be.&lt;/p&gt;

&lt;p&gt;Every piece of business logic moved into the browser becomes more exposed and more difficult to control.&lt;/p&gt;

&lt;p&gt;By keeping critical operations on the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication remains protected&lt;/li&gt;
&lt;li&gt;Authorization remains centralized&lt;/li&gt;
&lt;li&gt;Validation remains consistent&lt;/li&gt;
&lt;li&gt;Sensitive logic remains private&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js doesn't attempt to solve security in the frontend.&lt;/p&gt;

&lt;p&gt;Instead, it avoids creating the problem in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop Over-Engineering Frontend Scale
&lt;/h2&gt;

&lt;p&gt;Many organizations assume frontend scalability requires more abstraction layers, more state managers, and larger frameworks.&lt;/p&gt;

&lt;p&gt;Often the opposite is true.&lt;/p&gt;

&lt;p&gt;Applications become difficult to scale because too much responsibility has been pushed into the browser.&lt;/p&gt;

&lt;p&gt;State.js takes a different path.&lt;/p&gt;

&lt;p&gt;By keeping business logic on the backend and limiting frontend responsibilities to visual state orchestration, it eliminates much of the complexity that causes large applications to become difficult to maintain.&lt;/p&gt;

&lt;p&gt;The result is a simpler architecture, a smaller JavaScript footprint, better performance, stronger security boundaries, and a frontend that can grow without accumulating unnecessary complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The biggest misconception in modern web development is that large applications require massive client-side frameworks to scale.&lt;/p&gt;

&lt;p&gt;In reality, many SPA architectures introduce complexity by duplicating backend responsibilities in the browser.&lt;/p&gt;

&lt;p&gt;State.js rejects that model.&lt;/p&gt;

&lt;p&gt;Instead of acting as a client-side application platform, it serves as a lightweight visual orchestration layer that works directly with the DOM, CSS custom properties, and native HTML.&lt;/p&gt;

&lt;p&gt;Business logic remains secure on the server.&lt;/p&gt;

&lt;p&gt;Visual state remains fast in the browser.&lt;/p&gt;

&lt;p&gt;And because those responsibilities remain clearly separated, State.js can scale from a simple marketing site to a large enterprise application without requiring the architectural overhead that often makes traditional SPAs difficult to maintain.&lt;/p&gt;

&lt;p&gt;Sometimes the path to better scalability isn't adding more JavaScript.&lt;/p&gt;

&lt;p&gt;It's using less of it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>⭐ State.js + Keys.js Tutorial - Build Interactive UI with Pure HTML &amp; CSS</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Fri, 29 May 2026 20:30:10 +0000</pubDate>
      <link>https://dev.to/idevgames/statejs-keysjs-tutorial-build-interactive-ui-with-pure-html-css-53h</link>
      <guid>https://dev.to/idevgames/statejs-keysjs-tutorial-build-interactive-ui-with-pure-html-css-53h</guid>
      <description>&lt;p&gt;State.js gives you &lt;strong&gt;reactive state&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Keys.js gives you &lt;strong&gt;reactive keyboard input&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Together, they let you build interactive UI, controls, and even simple games using &lt;strong&gt;only HTML attributes&lt;/strong&gt;, with no JavaScript logic.&lt;/p&gt;

&lt;p&gt;This tutorial teaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how Keys.js tracks keyboard state
&lt;/li&gt;
&lt;li&gt;how State.js reacts to it
&lt;/li&gt;
&lt;li&gt;how to bind keys to state
&lt;/li&gt;
&lt;li&gt;how to build interactive UI
&lt;/li&gt;
&lt;li&gt;how to animate with CSS
&lt;/li&gt;
&lt;li&gt;how to build a small “move the box” demo
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s go.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ 1. What Keys.js Actually Does
&lt;/h2&gt;

&lt;p&gt;Keys.js listens to keyboard events and exposes them as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CSS variables&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML attributes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;classes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-keys&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keys.js automatically creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;--keys-a&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1 or &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;--keys-space&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1 or &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;--keys-last&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And adds classes like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.keys-a&lt;/span&gt;
&lt;span class="nc"&gt;.keys-space&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more: &lt;strong&gt;Keys.js basics&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 2. What State.js Does With That
&lt;/h2&gt;

&lt;p&gt;State.js can react to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS variables
&lt;/li&gt;
&lt;li&gt;attributes
&lt;/li&gt;
&lt;li&gt;events
&lt;/li&gt;
&lt;li&gt;conditions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when Keys.js updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;--keys-left&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js can use that to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;update state
&lt;/li&gt;
&lt;li&gt;change classes
&lt;/li&gt;
&lt;li&gt;animate with CSS
&lt;/li&gt;
&lt;li&gt;move elements
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;reactive input pipeline&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Keyboard → Keys.js → CSS variables → State.js → UI&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⭐ 3. Basic Setup
&lt;/h2&gt;

&lt;p&gt;Include both libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/@idevgames/state-js/src/state.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/@idevgames/keys-js/src/keys.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the Keys.js root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-keys&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the entire page reacts to keyboard input.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 4. Detecting Key Presses with CSS
&lt;/h2&gt;

&lt;p&gt;Let’s show when the user presses the spacebar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"indicator"&lt;/span&gt;
     &lt;span class="na"&gt;data-keys&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"active: keys.space"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Press SPACE
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-keys&lt;/code&gt; → enable Keys.js
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;keys.space&lt;/code&gt; → true when space is pressed
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-state-class="active: keys.space"&lt;/code&gt; → add &lt;code&gt;.active&lt;/code&gt; when pressed
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CSS:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.indicator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="m"&gt;0.2s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.indicator.active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4caf50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;reactive UI element&lt;/strong&gt; driven by keyboard input.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 5. Using Keys to Change State
&lt;/h2&gt;

&lt;p&gt;Let’s increment a counter when the user presses &lt;strong&gt;ArrowUp&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"keys.arrowup =&amp;gt; count += 1"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Count: {count}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What happens:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keys.js fires a &lt;code&gt;keys.arrowup&lt;/code&gt; event
&lt;/li&gt;
&lt;li&gt;State.js runs &lt;code&gt;count += 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;UI updates automatically
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the State.js event system in action.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;State.js event system&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 6. Using Keys to Move an Element (No JS Logic)
&lt;/h2&gt;

&lt;p&gt;Let’s build a simple “move the box” demo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;HTML&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"player"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-x=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-y=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"
       keys.arrowleft =&amp;gt; x -= 5;
       keys.arrowright =&amp;gt; x += 5;
       keys.arrowup =&amp;gt; y -= 5;
       keys.arrowdown =&amp;gt; y += 5
     "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;CSS&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;dodgerblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What’s happening:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keys.js detects arrow keys
&lt;/li&gt;
&lt;li&gt;State.js updates &lt;code&gt;data-x&lt;/code&gt; and &lt;code&gt;data-y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CSS moves the element using transforms
&lt;/li&gt;
&lt;li&gt;No JavaScript logic
&lt;/li&gt;
&lt;li&gt;No game loop
&lt;/li&gt;
&lt;li&gt;No re-renders
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;DOM-native movement&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 7. Smooth Movement (Holding Keys)
&lt;/h2&gt;

&lt;p&gt;Keys.js exposes “held down” state as CSS variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;--keys-arrowleft&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use autofire to move continuously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"player"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-x=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-y=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-autofire=&lt;/span&gt;&lt;span class="s"&gt;"
       if keys.arrowleft then x -= 3 every 16ms;
       if keys.arrowright then x += 3 every 16ms;
       if keys.arrowup then y -= 3 every 16ms;
       if keys.arrowdown then y += 3 every 16ms
     "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates &lt;strong&gt;smooth WASD/arrow movement&lt;/strong&gt; without JS.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;State.js intervals&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 8. Using Keys to Trigger Animations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"jump: keys.space"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#box&lt;/span&gt;&lt;span class="nc"&gt;.jump&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jump&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pressing space triggers a CSS animation.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 9. Using Keys to Toggle UI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-open=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"keys.escape =&amp;gt; open = !open"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"visible: open"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Menu Content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press ESC → open/close menu.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 10. Full Example — Move a Box + Change Color + Show Key
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-keys&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"player"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-x=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-y=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
     &lt;span class="na"&gt;data-color=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;

     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"
       keys.arrowleft =&amp;gt; x -= 5;
       keys.arrowright =&amp;gt; x += 5;
       keys.arrowup =&amp;gt; y -= 5;
       keys.arrowdown =&amp;gt; y += 5;
       keys.space =&amp;gt; color = 'red'
     "&lt;/span&gt;

     &lt;span class="na"&gt;data-state-style=&lt;/span&gt;&lt;span class="s"&gt;"background: {color}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"info"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Last key: {keys.last}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;movement
&lt;/li&gt;
&lt;li&gt;color change
&lt;/li&gt;
&lt;li&gt;last key display
&lt;/li&gt;
&lt;li&gt;all reactive
&lt;/li&gt;
&lt;li&gt;all declarative
&lt;/li&gt;
&lt;li&gt;zero JS logic
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⭐ Why State.js + Keys.js Works So Well
&lt;/h2&gt;

&lt;p&gt;Because they follow the same philosophy:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ HTML = structure
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ CSS = behavior
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ Attributes = API
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ JS = engine, not authoring
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ Zero build step
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ Zero dependencies
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ✔ Browser-native
&lt;/h3&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>State.js Event System - The Complete Beginner’s Guide</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Fri, 29 May 2026 20:15:23 +0000</pubDate>
      <link>https://dev.to/idevgames/statejs-event-system-the-complete-beginners-guide-2a09</link>
      <guid>https://dev.to/idevgames/statejs-event-system-the-complete-beginners-guide-2a09</guid>
      <description>&lt;p&gt;State.js introduces a new way to build reactive UI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTML holds the data.&lt;br&gt;&lt;br&gt;
CSS reacts to the data.&lt;br&gt;&lt;br&gt;
Events change the data.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This tutorial explains how State.js listens to events, how you trigger state changes, and how to build interactive UI without writing JavaScript logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 1. What Is a State.js Event?
&lt;/h2&gt;

&lt;p&gt;A State.js event is simply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;DOM event&lt;/strong&gt; (click, input, mouseover, keydown, etc.)&lt;/li&gt;
&lt;li&gt;connected to a &lt;strong&gt;state mutation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;written declaratively in HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; count += 1"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Count: {count}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you click the element:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; increases
&lt;/li&gt;
&lt;li&gt;State.js updates the attribute
&lt;/li&gt;
&lt;li&gt;CSS variables update
&lt;/li&gt;
&lt;li&gt;the text updates
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without JavaScript logic.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;State.js triggers&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 2. The &lt;code&gt;data-state-on&lt;/code&gt; Attribute
&lt;/h2&gt;

&lt;p&gt;This is the core of the event system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-active=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; active = !active"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This toggles the &lt;code&gt;data-active&lt;/code&gt; attribute every time the element is clicked.&lt;/p&gt;

&lt;p&gt;State.js then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;updates CSS variables
&lt;/li&gt;
&lt;li&gt;updates any bound text
&lt;/li&gt;
&lt;li&gt;updates any reactive classes
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⭐ 3. Listening to Any DOM Event
&lt;/h2&gt;

&lt;p&gt;You can listen to &lt;em&gt;any&lt;/em&gt; event the browser supports.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Click&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="click =&amp;gt; count += 1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Input&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="input =&amp;gt; value = event.target.value"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Mouseover&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="mouseover =&amp;gt; hovered = true"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Mouseout&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="mouseout =&amp;gt; hovered = false"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Keydown&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="keydown =&amp;gt; key = event.key"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js doesn’t invent new events — it uses the browser’s native ones.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;Event expressions&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 4. Using Event Data (&lt;code&gt;event&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;State.js exposes the event object as &lt;code&gt;event&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example: capture the clicked element’s text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-last=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; last = event.target.textContent"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Last clicked: {last}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: track mouse position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-x=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-y=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"mousemove =&amp;gt; x = event.clientX; y = event.clientY"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"X: {x}, Y: {y}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⭐ 5. Updating Another Element’s State
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;data-state-target&lt;/code&gt; to update a different element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
  &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#box"&lt;/span&gt;
  &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; color = 'red'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Make Red
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"box"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-color=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"red: color == 'red'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the State.js equivalent of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React props
&lt;/li&gt;
&lt;li&gt;Vue emits
&lt;/li&gt;
&lt;li&gt;Svelte dispatch
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But simpler.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 6. Multiple Event Handlers
&lt;/h2&gt;

&lt;p&gt;You can chain multiple events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"
       click =&amp;gt; count += 1;
       mouseover =&amp;gt; hovered = true;
       mouseout =&amp;gt; hovered = false
     "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each event runs its own expression.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 7. Using Events to Add/Remove Classes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-active=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; active = !active"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"active: active"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This toggles a class with no JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 8. Using Events to Drive CSS Animations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; animate = true"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"pop: animate"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pop&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how you build interactive UI without JS logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 9. Building a Mini App with Events
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-on=&lt;/span&gt;&lt;span class="s"&gt;"click =&amp;gt; count += 1"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Clicked {count} times"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a complete app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reactive state
&lt;/li&gt;
&lt;li&gt;reactive text
&lt;/li&gt;
&lt;li&gt;event-driven logic
&lt;/li&gt;
&lt;li&gt;no JavaScript
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;State.js mental model&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 10. Why the Event System Matters
&lt;/h2&gt;

&lt;p&gt;Because it replaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React’s &lt;code&gt;onClick={() =&amp;gt; setCount(count + 1)}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vue’s &lt;code&gt;@click="count++"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Svelte’s &lt;code&gt;on:click={() =&amp;gt; count++}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;data-state-on="click =&amp;gt; count += 1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No JS.&lt;br&gt;&lt;br&gt;
No framework.&lt;br&gt;&lt;br&gt;
No re-renders.&lt;br&gt;&lt;br&gt;
No hydration.&lt;br&gt;&lt;br&gt;
No build step.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;State.js philosophy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;State.js architecture&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>⭐ State.js Basics — Learn CSS‑Driven Reactivity in 10 Minutes</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Fri, 29 May 2026 20:05:15 +0000</pubDate>
      <link>https://dev.to/idevgames/statejs-basics-learn-css-driven-reactivity-in-10-minutes-3m80</link>
      <guid>https://dev.to/idevgames/statejs-basics-learn-css-driven-reactivity-in-10-minutes-3m80</guid>
      <description>&lt;p&gt;State.js looks simple — just HTML attributes — but it introduces a &lt;strong&gt;new mental model&lt;/strong&gt; for building UI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTML holds the data.&lt;br&gt;&lt;br&gt;
CSS reacts to the data.&lt;br&gt;&lt;br&gt;
State.js keeps them in sync.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’re used to React, Vue, or Svelte, this feels strange at first.&lt;br&gt;&lt;br&gt;
If you’re used to CSS, this feels like “why didn’t CSS always work like this?”&lt;/p&gt;

&lt;p&gt;This tutorial will teach you the core ideas behind State.js so you can build reactive UI without JavaScript logic, without a framework, and without a build step.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ 1. What State.js Actually Does
&lt;/h2&gt;

&lt;p&gt;State.js turns HTML attributes into &lt;strong&gt;live CSS variables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js automatically exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;--state-count&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;data-count&lt;/code&gt; changes, the CSS variable updates instantly.&lt;/p&gt;

&lt;p&gt;This is the foundation of everything.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;Reactive attributes&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 2. Your First Reactive Element
&lt;/h2&gt;

&lt;p&gt;Let’s make a simple counter.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;HTML&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Count: {count}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What’s happening?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-state&lt;/code&gt; → activates State.js
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-count="0"&lt;/code&gt; → creates &lt;code&gt;--state-count: 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-state-text="Count: {count}"&lt;/code&gt; → binds text to the value
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js replaces &lt;code&gt;{count}&lt;/code&gt; with the live value.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 3. Updating State with Triggers
&lt;/h2&gt;

&lt;p&gt;Add a button that increments the counter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
  &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#counter"&lt;/span&gt;
  &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;
  &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  +1
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this means:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-state-trigger&lt;/code&gt; → this element performs an action
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-state-target="#counter"&lt;/code&gt; → update that element
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-state-attr="count"&lt;/code&gt; → update the &lt;code&gt;data-count&lt;/code&gt; attribute
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-state-increment="1"&lt;/code&gt; → add 1
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clicking the button updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the attribute
&lt;/li&gt;
&lt;li&gt;the CSS variable
&lt;/li&gt;
&lt;li&gt;the text
&lt;/li&gt;
&lt;li&gt;all automatically
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more: &lt;strong&gt;Triggers&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 4. Styling with CSS Variables
&lt;/h2&gt;

&lt;p&gt;Because State.js exposes attributes as CSS variables, you can style reactively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#counter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the count increases, the color changes.&lt;/p&gt;

&lt;p&gt;No JS.&lt;br&gt;&lt;br&gt;
No re-renders.&lt;br&gt;&lt;br&gt;
Just CSS reacting to state.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;CSS variable projection&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ⭐ 5. Conditions (Reactive Logic in HTML)
&lt;/h2&gt;

&lt;p&gt;Let’s change the background when the count reaches 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;
     &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"big: count &amp;gt;= 5"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Count: {count}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds the class &lt;code&gt;.big&lt;/code&gt; when the condition is true.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.big&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;gold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more: &lt;strong&gt;Conditions&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 6. Autofire (State.js “Game Loop”)
&lt;/h2&gt;

&lt;p&gt;State.js can update values on an interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-time=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-autofire=&lt;/span&gt;&lt;span class="s"&gt;"time += 1 every 100ms"&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Time: {time}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;strong&gt;reactive timer&lt;/strong&gt; with no JavaScript.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;Intervals&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 7. Two-Way Binding (Forms Without JS)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt;
       &lt;span class="na"&gt;data-state&lt;/span&gt;
       &lt;span class="na"&gt;data-value=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt;
       &lt;span class="na"&gt;data-state-bind=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt;
     &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Value: {value}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving the slider updates the text automatically.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;strong&gt;Binding&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 8. Putting It All Together — A Mini App
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-count=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;data-state-text=&lt;/span&gt;&lt;span class="s"&gt;"Count: {count}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
    &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#app"&lt;/span&gt;
    &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;
    &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    +1
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;data-state-trigger&lt;/span&gt;
    &lt;span class="na"&gt;data-state-target=&lt;/span&gt;&lt;span class="s"&gt;"#app"&lt;/span&gt;
    &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;
    &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    -1
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-class=&lt;/span&gt;&lt;span class="s"&gt;"warning: count &amp;lt; 0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Count is negative!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What you get:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;reactive text
&lt;/li&gt;
&lt;li&gt;reactive classes
&lt;/li&gt;
&lt;li&gt;reactive styling
&lt;/li&gt;
&lt;li&gt;reactive state
&lt;/li&gt;
&lt;li&gt;no JavaScript logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;State.js mental model&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ 9. Why This Matters
&lt;/h2&gt;

&lt;p&gt;State.js gives you:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Reactivity without JavaScript
&lt;/h3&gt;

&lt;p&gt;No functions.&lt;br&gt;&lt;br&gt;
No hooks.&lt;br&gt;&lt;br&gt;
No re-renders.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Components without frameworks
&lt;/h3&gt;

&lt;p&gt;Just templates + includes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ State without state management libraries
&lt;/h3&gt;

&lt;p&gt;Attributes &lt;em&gt;are&lt;/em&gt; the state.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ UI logic without JS
&lt;/h3&gt;

&lt;p&gt;CSS handles behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Zero build step
&lt;/h3&gt;

&lt;p&gt;Works in plain HTML.&lt;/p&gt;

&lt;p&gt;This is why people say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It feels like something CSS should have done.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because State.js makes the browser behave the way developers &lt;em&gt;wish&lt;/em&gt; it behaved.&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>State.js Tutorial: Creating Reusable UI Components with Pure CSS Reactivity</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 27 May 2026 21:39:19 +0000</pubDate>
      <link>https://dev.to/idevgames/statejs-tutorial-creating-reusable-ui-components-with-pure-css-reactivity-3b56</link>
      <guid>https://dev.to/idevgames/statejs-tutorial-creating-reusable-ui-components-with-pure-css-reactivity-3b56</guid>
      <description>&lt;p&gt;Modern frontend frameworks treat components as JavaScript functions, classes, or compiled files.&lt;br&gt;&lt;br&gt;
But what if components didn’t need JavaScript at all?&lt;/p&gt;

&lt;p&gt;What if components were built from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTML templates&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS for behavior and visuals&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State.js attributes for reactivity&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…with &lt;strong&gt;no JS logic, no virtual DOM, and no build step&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That’s exactly what &lt;strong&gt;State.js&lt;/strong&gt; enables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; turns HTML attributes into &lt;strong&gt;reactive CSS variables&lt;/strong&gt;, letting you build fully reactive, reusable UI components using nothing but HTML + CSS.&lt;/p&gt;

&lt;p&gt;In this article, you’ll learn how &lt;strong&gt;State.js components actually work&lt;/strong&gt;.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;What Is a Component in State.js?&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;In React, a component is a function.&lt;br&gt;&lt;br&gt;
In Vue, it’s an object.&lt;br&gt;&lt;br&gt;
In Svelte, it’s a compiled file.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;State.js&lt;/strong&gt;, a component is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A reusable HTML template that becomes reactive when included with &lt;code&gt;data-state-include&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A component is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;defined once
&lt;/li&gt;
&lt;li&gt;cloned anywhere
&lt;/li&gt;
&lt;li&gt;customized via attributes
&lt;/li&gt;
&lt;li&gt;reactive automatically
&lt;/li&gt;
&lt;li&gt;fully encapsulated
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No JavaScript logic.&lt;br&gt;&lt;br&gt;
No rendering engine.&lt;br&gt;&lt;br&gt;
No framework runtime.&lt;/p&gt;

&lt;p&gt;Just &lt;strong&gt;HTML + CSS + State.js&lt;/strong&gt;.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Example: A Reusable &lt;code&gt;&amp;lt;char-card&amp;gt;&lt;/code&gt; Component&lt;/strong&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;1. Define the component once&lt;/strong&gt;
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"char-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"char-card"&lt;/span&gt; &lt;span class="na"&gt;data-state&lt;/span&gt; &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt; &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;data-state-display=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fill"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: var(--state-hp-percent)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"hp"&lt;/span&gt; &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Damage
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the &lt;strong&gt;component definition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;State.js automatically exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--state-hp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--state-hp-max&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--state-hp-percent&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These update reactively whenever attributes change.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;2. Use the component anywhere&lt;/strong&gt;
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-include=&lt;/span&gt;&lt;span class="s"&gt;"#char-card"&lt;/span&gt;
     &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Warrior"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"18"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-include=&lt;/span&gt;&lt;span class="s"&gt;"#char-card"&lt;/span&gt;
     &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Mage"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"9"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clones the template
&lt;/li&gt;
&lt;li&gt;merges your attributes
&lt;/li&gt;
&lt;li&gt;becomes a fully reactive component
&lt;/li&gt;
&lt;li&gt;auto-binds triggers to its own state
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the State.js equivalent of &lt;strong&gt;props&lt;/strong&gt;, but simpler.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;CSS Drives the Component’s Behavior&lt;/strong&gt;
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.char-card&lt;/span&gt; &lt;span class="nc"&gt;.bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.char-card&lt;/span&gt; &lt;span class="nc"&gt;.fill&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4caf50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-hp-percent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;CSS handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;animation
&lt;/li&gt;
&lt;li&gt;interpolation
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;layout
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;state changes
&lt;/li&gt;
&lt;li&gt;variable updates
&lt;/li&gt;
&lt;li&gt;triggers
&lt;/li&gt;
&lt;li&gt;reactivity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;CSS‑reactive architecture&lt;/strong&gt;.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Updating the Component&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Inside the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-state-trigger&lt;/span&gt; &lt;span class="na"&gt;data-state-attr=&lt;/span&gt;&lt;span class="s"&gt;"hp"&lt;/span&gt; &lt;span class="na"&gt;data-state-increment=&lt;/span&gt;&lt;span class="s"&gt;"-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Damage
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When clicked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-hp&lt;/code&gt; decreases
&lt;/li&gt;
&lt;li&gt;State.js updates &lt;code&gt;--state-hp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CSS recalculates &lt;code&gt;--state-hp-percent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The bar animates automatically
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;reactivity without JavaScript logic&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Why This Works&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;State.js turns HTML attributes into &lt;strong&gt;live CSS variables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;CSS handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout
&lt;/li&gt;
&lt;li&gt;animation
&lt;/li&gt;
&lt;li&gt;transitions
&lt;/li&gt;
&lt;li&gt;transforms
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State.js handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;state
&lt;/li&gt;
&lt;li&gt;triggers
&lt;/li&gt;
&lt;li&gt;conditions
&lt;/li&gt;
&lt;li&gt;intervals
&lt;/li&gt;
&lt;li&gt;reactivity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they form a &lt;strong&gt;browser‑native component system&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Why This Is a Big Deal&lt;/strong&gt;
&lt;/h1&gt;

&lt;h3&gt;
  
  
  ✔ Zero JavaScript logic
&lt;/h3&gt;

&lt;p&gt;Your component logic lives in HTML + CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Zero framework runtime
&lt;/h3&gt;

&lt;p&gt;No virtual DOM.&lt;br&gt;&lt;br&gt;
No hydration.&lt;br&gt;&lt;br&gt;
No re-renders.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✔ Zero build step
&lt;/h3&gt;

&lt;p&gt;Works in plain HTML files.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✔ Fully portable components
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;&amp;lt;char-card&amp;gt;&lt;/code&gt; works anywhere HTML works.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✔ Native browser performance
&lt;/h3&gt;

&lt;p&gt;CSS is GPU‑accelerated and instant.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✔ Auto‑binding triggers
&lt;/h3&gt;

&lt;p&gt;Buttons inside the template automatically bind to the nearest &lt;code&gt;[data-state]&lt;/code&gt; parent.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Component API Design&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;You can define your own “props” using attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-include=&lt;/span&gt;&lt;span class="s"&gt;"#char-card"&lt;/span&gt;
     &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Rogue"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"12"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"14"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or add more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-state-include=&lt;/span&gt;&lt;span class="s"&gt;"#char-card"&lt;/span&gt;
     &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Cleric"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp=&lt;/span&gt;&lt;span class="s"&gt;"14"&lt;/span&gt;
     &lt;span class="na"&gt;data-hp-max=&lt;/span&gt;&lt;span class="s"&gt;"16"&lt;/span&gt;
     &lt;span class="na"&gt;data-color=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;
     &lt;span class="na"&gt;data-low=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State.js exposes them all as CSS variables.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; lets you build components using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTML for structure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS for behavior&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State.js for reactivity&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a new category of UI architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CSS‑Reactive Components&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Components powered by HTML templates, CSS variables, and declarative reactivity — not JavaScript logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want lightweight, portable, framework‑free UI, this pattern is a game changer.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>CSS Reactive Frameworks: Why the Future of UI Flows Through CSS Instead of JavaScript</title>
      <dc:creator>iDev-Games</dc:creator>
      <pubDate>Wed, 27 May 2026 11:54:22 +0000</pubDate>
      <link>https://dev.to/idevgames/css-reactive-frameworks-why-the-future-of-ui-flows-through-css-instead-of-javascript-4179</link>
      <guid>https://dev.to/idevgames/css-reactive-frameworks-why-the-future-of-ui-flows-through-css-instead-of-javascript-4179</guid>
      <description>&lt;p&gt;Modern frontend development has a contradiction at its core.&lt;/p&gt;

&lt;p&gt;We tell developers that rich interactivity requires layers of abstraction:&lt;br&gt;
virtual DOMs, hydration pipelines, reactive hooks, compiler stages, bundlers, state containers, and increasingly complex rendering architectures.&lt;/p&gt;

&lt;p&gt;Then someone ships a fully interactive, real-time simulation from a single local HTML file with almost no custom JavaScript — and it runs flawlessly at 60 FPS.&lt;/p&gt;

&lt;p&gt;That contradiction is the “No-JS” paradox.&lt;/p&gt;

&lt;p&gt;And it exposes something the industry has slowly forgotten:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The browser is already a reactive engine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Frameworks didn’t invent reactivity. Browsers had it from the beginning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt; simply stops fighting the browser’s architecture and starts working with it instead.&lt;/p&gt;


&lt;h1&gt;
  
  
  We Built an Entire Industry Around Re-Rendering
&lt;/h1&gt;

&lt;p&gt;For the last decade, frontend engineering has been dominated by one assumption:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Application state belongs exclusively to JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This belief shaped the modern web stack.&lt;/p&gt;

&lt;p&gt;Need to update text? Trigger a render cycle.&lt;br&gt;&lt;br&gt;
Need to animate UI? Route it through component state.&lt;br&gt;&lt;br&gt;
Need interactivity? Build a synchronization layer between memory and the DOM.&lt;/p&gt;

&lt;p&gt;The result is an ecosystem where developers routinely ship megabytes of tooling just to keep application data synchronized with elements the browser already knows how to update natively.&lt;/p&gt;

&lt;p&gt;Modern frameworks treat the DOM as a dumb output target — something to be diffed, patched, reconciled, hydrated, and rebuilt.&lt;/p&gt;

&lt;p&gt;But the DOM was never dumb.&lt;/p&gt;

&lt;p&gt;The browser’s rendering engine is one of the most optimized reactive systems ever created.&lt;/p&gt;

&lt;p&gt;It already performs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependency resolution&lt;/li&gt;
&lt;li&gt;style recalculation&lt;/li&gt;
&lt;li&gt;layout propagation&lt;/li&gt;
&lt;li&gt;compositing&lt;/li&gt;
&lt;li&gt;animation timing&lt;/li&gt;
&lt;li&gt;GPU acceleration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The web platform solved reactivity years ago.&lt;/p&gt;

&lt;p&gt;Most frameworks simply rebuilt it in JavaScript.&lt;/p&gt;


&lt;h1&gt;
  
  
  The Core Idea Behind CSS Reactive Frameworks
&lt;/h1&gt;

&lt;p&gt;State.js introduces a different model.&lt;/p&gt;

&lt;p&gt;Instead of routing UI updates through JavaScript rendering logic, it exposes application state directly to CSS through native browser variables.&lt;/p&gt;

&lt;p&gt;Your markup becomes the source of truth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"colony"&lt;/span&gt;
  &lt;span class="na"&gt;data-state&lt;/span&gt;
  &lt;span class="na"&gt;data-state-watch=&lt;/span&gt;&lt;span class="s"&gt;"spores,bio,mut,haz"&lt;/span&gt;
  &lt;span class="na"&gt;data-spores=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;
  &lt;span class="na"&gt;data-bio=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
  &lt;span class="na"&gt;data-mut=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
  &lt;span class="na"&gt;data-haz=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When attributes change, State.js maps them directly into CSS custom properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;--state-spores&lt;/span&gt;
&lt;span class="nt"&gt;--state-bio&lt;/span&gt;
&lt;span class="nt"&gt;--state-mut&lt;/span&gt;
&lt;span class="nt"&gt;--state-haz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that point, JavaScript’s job is effectively finished.&lt;/p&gt;

&lt;p&gt;The browser takes over.&lt;/p&gt;

&lt;p&gt;CSS becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the rendering layer&lt;/li&gt;
&lt;li&gt;the calculation layer&lt;/li&gt;
&lt;li&gt;the reactive layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s the paradigm shift.&lt;/p&gt;




&lt;h1&gt;
  
  
  The DOM Is Already a Database
&lt;/h1&gt;

&lt;p&gt;Traditional frameworks separate state from presentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript owns the data&lt;/li&gt;
&lt;li&gt;The framework owns synchronization&lt;/li&gt;
&lt;li&gt;The DOM becomes a visual projection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in a CSS reactive architecture, the DOM &lt;em&gt;is&lt;/em&gt; the state container.&lt;/p&gt;

&lt;p&gt;That changes everything.&lt;/p&gt;

&lt;p&gt;Instead of hidden memory trees buried inside framework internals, state becomes visible, inspectable, and native.&lt;/p&gt;

&lt;p&gt;Open DevTools and the entire application state is sitting directly inside the markup.&lt;/p&gt;

&lt;p&gt;You can literally edit gameplay values live in the Elements panel and watch the interface react instantly.&lt;/p&gt;

&lt;p&gt;No React DevTools.&lt;br&gt;&lt;br&gt;
No framework inspectors.&lt;br&gt;&lt;br&gt;
No hidden proxy objects.&lt;br&gt;&lt;br&gt;
No hydration debugging.&lt;/p&gt;

&lt;p&gt;The browser already gives you the tooling.&lt;/p&gt;


&lt;h1&gt;
  
  
  Why CSS Reactive Systems Feel Faster
&lt;/h1&gt;

&lt;p&gt;One of the biggest performance gains comes from removing render bottlenecks entirely.&lt;/p&gt;

&lt;p&gt;In traditional frontend frameworks, a state update typically triggers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JavaScript execution&lt;/li&gt;
&lt;li&gt;Dependency tracking&lt;/li&gt;
&lt;li&gt;Component reconciliation&lt;/li&gt;
&lt;li&gt;Virtual DOM diffing&lt;/li&gt;
&lt;li&gt;DOM patching&lt;/li&gt;
&lt;li&gt;Layout recalculation&lt;/li&gt;
&lt;li&gt;Paint/composite&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In a CSS reactive system, most of this disappears.&lt;/p&gt;

&lt;p&gt;The state changes once.&lt;/p&gt;

&lt;p&gt;The browser updates CSS variables.&lt;/p&gt;

&lt;p&gt;Everything downstream becomes native browser work.&lt;/p&gt;

&lt;p&gt;That matters because browsers optimize CSS and compositing at an extremely low level — often directly on GPU compositor threads.&lt;/p&gt;

&lt;p&gt;Animations stay smooth because the browser is doing what it was originally designed to do instead of waiting for JavaScript reconciliation loops every frame.&lt;/p&gt;


&lt;h1&gt;
  
  
  CSS Is More Powerful Than We Pretend
&lt;/h1&gt;

&lt;p&gt;Modern CSS is no longer just decorative styling.&lt;/p&gt;

&lt;p&gt;It already contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;variables&lt;/li&gt;
&lt;li&gt;math&lt;/li&gt;
&lt;li&gt;conditional logic&lt;/li&gt;
&lt;li&gt;timelines&lt;/li&gt;
&lt;li&gt;interpolation&lt;/li&gt;
&lt;li&gt;transform pipelines&lt;/li&gt;
&lt;li&gt;scroll-driven animation&lt;/li&gt;
&lt;li&gt;responsive calculations&lt;/li&gt;
&lt;li&gt;hardware acceleration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yet most developers still treat CSS like a passive skin layered on top of JavaScript applications.&lt;/p&gt;

&lt;p&gt;CSS reactive architecture flips that relationship.&lt;/p&gt;

&lt;p&gt;Instead of JavaScript commanding the interface every frame, CSS passively responds to changing data.&lt;/p&gt;

&lt;p&gt;A progress bar doesn’t need imperative width calculations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.progress-fill&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--state-spores-percent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A camera shake effect doesn’t need animation libraries.&lt;/p&gt;

&lt;p&gt;A HUD doesn’t need rerendering.&lt;/p&gt;

&lt;p&gt;A dashboard doesn’t need component invalidation.&lt;/p&gt;

&lt;p&gt;The browser already knows how to propagate visual dependencies.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Modular Micro-Library Ecosystem
&lt;/h1&gt;

&lt;p&gt;What makes this philosophy especially interesting is that it encourages modularity instead of ecosystem lock-in.&lt;/p&gt;

&lt;p&gt;Instead of one massive framework controlling everything, browser behavior can be split into focused micro-libraries that extend native capabilities.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Trig.js" rel="noopener noreferrer"&gt;Trig.js&lt;/a&gt; feeds scroll positions directly into CSS variables for cinematic scroll-driven interfaces&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Motion-JS" rel="noopener noreferrer"&gt;Motion.js&lt;/a&gt; acts as a global timing engine for timeline-driven CSS animation systems&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Keys-JS" rel="noopener noreferrer"&gt;Keys.js&lt;/a&gt; maps keyboard input directly into declarative state mutations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/iDev-Games/Cursor-JS" rel="noopener noreferrer"&gt;Cursor.js&lt;/a&gt; introduces reactive pointer tracking without heavy event plumbing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of adopting an all-or-nothing framework ecosystem, developers compose exactly the behavior layer they need.&lt;/p&gt;

&lt;p&gt;That’s much closer to how the web was originally intended to work.&lt;/p&gt;




&lt;h1&gt;
  
  
  This Isn’t “Anti-JavaScript”
&lt;/h1&gt;

&lt;p&gt;This is an important distinction.&lt;/p&gt;

&lt;p&gt;CSS reactive architecture is not about eliminating JavaScript.&lt;/p&gt;

&lt;p&gt;It’s about redefining JavaScript’s role.&lt;/p&gt;

&lt;p&gt;JavaScript becomes a lightweight state mutator instead of a full rendering runtime.&lt;/p&gt;

&lt;p&gt;In this model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript changes data&lt;/li&gt;
&lt;li&gt;CSS handles presentation&lt;/li&gt;
&lt;li&gt;The browser manages propagation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system becomes simpler because responsibilities become clearer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why This Matters Beyond Performance
&lt;/h1&gt;

&lt;p&gt;The biggest advantage may not even be speed.&lt;/p&gt;

&lt;p&gt;It may be accessibility.&lt;/p&gt;

&lt;p&gt;Modern frontend development has become increasingly hostile to newcomers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex build chains&lt;/li&gt;
&lt;li&gt;framework churn&lt;/li&gt;
&lt;li&gt;hydration bugs&lt;/li&gt;
&lt;li&gt;SSR edge cases&lt;/li&gt;
&lt;li&gt;compiler-specific syntax&lt;/li&gt;
&lt;li&gt;dependency fatigue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building simple interactive websites now often requires knowledge of infrastructure that didn’t even exist a few years ago.&lt;/p&gt;

&lt;p&gt;CSS reactive systems reduce that complexity dramatically because the application remains fundamentally HTML-first.&lt;/p&gt;

&lt;p&gt;The app &lt;em&gt;is&lt;/em&gt; the document.&lt;/p&gt;

&lt;p&gt;That makes the platform easier to reason about, easier to debug, and significantly easier to teach.&lt;/p&gt;




&lt;h1&gt;
  
  
  Returning to the Browser Instead of Escaping It
&lt;/h1&gt;

&lt;p&gt;For years, frontend engineering focused on abstracting developers away from the browser.&lt;/p&gt;

&lt;p&gt;But the browser itself kept evolving.&lt;/p&gt;

&lt;p&gt;Native CSS now supports features that previously required entire JavaScript ecosystems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scroll timelines&lt;/li&gt;
&lt;li&gt;container queries&lt;/li&gt;
&lt;li&gt;view transitions&lt;/li&gt;
&lt;li&gt;hardware compositing&lt;/li&gt;
&lt;li&gt;declarative animation pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The platform is catching up to the abstractions.&lt;/p&gt;

&lt;p&gt;And in many cases, surpassing them.&lt;/p&gt;

&lt;p&gt;CSS reactive frameworks like State.js represent a larger philosophical shift:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of rebuilding the browser in JavaScript, what if we simply embraced the browser as the runtime?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The “No-JS” paradox feels impossible only because the industry spent years assuming that interactivity must flow through JavaScript rendering systems.&lt;/p&gt;

&lt;p&gt;But the browser was reactive long before modern frameworks arrived.&lt;/p&gt;

&lt;p&gt;State.js demonstrates that when state flows directly through CSS and the DOM becomes the source of truth, applications become simpler, faster, and dramatically more transparent.&lt;/p&gt;

&lt;p&gt;It’s not about abandoning modern web development.&lt;/p&gt;

&lt;p&gt;It’s about removing unnecessary layers between your data and the screen.&lt;/p&gt;

&lt;p&gt;And perhaps more importantly:&lt;/p&gt;

&lt;p&gt;It makes building for the web feel immediate, creative, and fun again.&lt;/p&gt;




&lt;h1&gt;
  
  
  Explore the Project
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/iDev-Games/State-JS" rel="noopener noreferrer"&gt;State.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iDev-Games/Trig.js" rel="noopener noreferrer"&gt;Trig.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iDev-Games/Motion-JS" rel="noopener noreferrer"&gt;Motion.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iDev-Games/Keys-JS" rel="noopener noreferrer"&gt;Keys.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
