Ready-made CSS animations for interactive UIs with State.js. Perfect for dashboards, web apps, games, and more. Just copy and paste!
A complete progress indicator that automatically changes color and animations based on value. Perfect for health bars in games, download progress, storage meters, or any value-based UI.
<!-- Health bar container -->
<div id="healthDemo"
data-state
data-state-watch="health"
data-health="100"
data-health-min="0"
data-health-max="100">
<div class="health-bar">
<div class="health-fill"></div>
</div>
<div>Health: <span data-state-display="health">100</span></div>
<!-- Slider that auto-updates the health -->
<input type="range"
data-state
data-state-bind="healthDemo"
data-state-attr="health"
min="0" max="100" value="100">
</div>
<style>
.health-bar {
width: 100%;
height: 40px;
background: #333;
border-radius: 20px;
overflow: hidden;
}
.health-fill {
height: 100%;
background: linear-gradient(90deg, #ff0000 0%, #ffff00 50%, #00ff00 100%);
width: var(--state-health-percent);
transition: width 0.3s ease-out;
}
</style>
What happens automatically:
Dynamic counter that celebrates milestones automatically. Great for scores, points, views, likes, download counts, or any numeric metric.
<!-- Score container -->
<div id="scoreDemo"
data-state
data-state-watch="score"
data-score="0"
data-score-min="0"
data-score-max="1000">
<div class="score-display">
Score: <span data-state-display="score">0</span>
</div>
<!-- Slider to test different scores -->
<input type="range"
data-state
data-state-bind="scoreDemo"
data-state-attr="score"
min="0" max="1000" step="10" value="0">
</div>
<style>
.score-display {
font-size: 48px;
font-family: 'Bebas Neue', sans-serif;
}
</style>
What happens automatically:
Visual effects for active/inactive states using boolean toggles. Perfect for power-ups in games, feature flags, premium status, active subscriptions, or any on/off state.
<!-- Player with power-up states -->
<div id="powerDemo"
data-state
data-state-toggles="powered,invincible,shielded,stunned"
data-powered="false"
data-invincible="false"
data-shielded="false"
data-stunned="false">
PLAYER
</div>
<!-- Buttons that toggle power-ups -->
<button data-state
data-state-trigger
data-state-bind="powerDemo"
data-state-toggle="powered">
Toggle Powered
</button>
<button data-state
data-state-trigger
data-state-bind="powerDemo"
data-state-toggle="invincible">
Toggle Invincible
</button>
Available power-up classes:
.state-powered - Golden glow pulse.state-invincible - Shimmer effect.state-shielded - Blue pulse shield.state-stunned - Dizzy rotationCelebrate tier changes, level ups, or rank promotions with a bright flash animation. Great for games, achievement systems, subscription tiers, or user rankings.
<!-- Level display -->
<div id="levelDemo"
data-state
data-state-toggles="level-up"
data-level-up="false">
Level 5
</div>
<!-- Button to trigger animation -->
<button data-state
data-state-trigger
data-state-bind="levelDemo"
data-state-toggle="level-up">
Trigger Level Up
</button>
Visual effects for different status states. Perfect for game effects (poisoned, frozen, burning, healing), system states (processing, syncing, error), or any conditional visual feedback.
<!-- Player with status effects -->
<div id="statusDemo"
data-state
data-state-toggles="poisoned,frozen,burning,healing,cursed,blessed"
data-poisoned="false"
data-frozen="false"
data-burning="false"
data-healing="false"
data-cursed="false"
data-blessed="false">
PLAYER
</div>
<!-- Buttons to toggle status effects -->
<button data-state
data-state-trigger
data-state-bind="statusDemo"
data-state-toggle="poisoned">
Poisoned
</button>
<button data-state
data-state-trigger
data-state-bind="statusDemo"
data-state-toggle="frozen">
Frozen
</button>
Available status effects:
.state-poisoned - Green hue pulse.state-frozen - Blue tint with shake.state-burning - Orange flicker.state-healing - Green sparkle.state-cursed - Dark pulsing.state-blessed - Golden glowFeedback animations for success, error, warning messages.
<!-- Notification element -->
<div id="notificationDemo"
data-state
data-state-toggles="success,error,warning"
data-success="false"
data-error="false"
data-warning="false">
NOTIFICATION
</div>
<!-- Buttons to trigger animations -->
<button data-state
data-state-trigger
data-state-bind="notificationDemo"
data-state-toggle="success">
Success
</button>
<button data-state
data-state-trigger
data-state-bind="notificationDemo"
data-state-toggle="error">
Error
</button>
Available notification classes:
.state-success - Bounce in.state-error - Shake animation.state-warning - Shake warning.state-notification - Slide inReady-to-use interactive components built with State.js alone. These examples demonstrate game mechanics, but the same patterns work for any interactive UI. Copy, paste, and customize!
<div id="player"
data-state-watch="health"
data-state-var="true"
data-health="100"
data-health-min="0"
data-health-max="100">
<!-- Health Display -->
<div>Health: <span data-state-display="health">100</span> / 100</div>
<!-- Health Bar -->
<div class="health-bar-container">
<div class="health-bar" style="width: var(--state-health-percent);"></div>
</div>
<!-- Controls -->
<button data-state data-state-trigger data-state-bind="player"
data-state-attr="health" data-state-value="50">Take Damage</button>
<button data-state data-state-trigger data-state-bind="player"
data-state-attr="health" data-state-value="100">Heal</button>
</div>
<style>
.health-bar-container {
background: #444;
height: 30px;
border-radius: 15px;
overflow: hidden;
}
.health-bar {
background: linear-gradient(90deg, red 0%, yellow 50%, green 100%);
height: 100%;
transition: width 0.3s;
}
/* Auto-regeneration animation */
.state-regenerating .health-bar {
animation: regen-pulse 2s infinite;
}
@keyframes regen-pulse {
0%, 100% { filter: brightness(1); }
50% { filter: brightness(1.5); }
}
</style>
<div id="clicker"
data-state
data-state-watch="score"
data-state-var="true"
data-score="0"
data-score-max="100">
<!-- Display -->
<div class="score-display"><span data-state-display="score">0</span></div>
<!-- Progress Bar -->
<div class="progress-bar" style="width: var(--state-score-percent);"></div>
<!-- Increment Buttons -->
<button data-state data-state-trigger data-state-bind="clicker"
data-state-attr="score" data-state-increment="1">+1</button>
<button data-state data-state-trigger data-state-bind="clicker"
data-state-attr="score" data-state-increment="5">+5</button>
<button data-state data-state-trigger data-state-bind="clicker"
data-state-attr="score" data-state-increment="10">+10</button>
<!-- Reset Button -->
<button data-state data-state-trigger data-state-bind="clicker"
data-state-attr="score" data-state-value="0">Reset</button>
</div>
<style>
/* Milestone celebrations using CSS alone */
#clicker[data-score="20"],
#clicker[data-score="30"],
#clicker[data-score="40"] {
animation: milestone-pulse 0.5s ease-out;
}
#clicker[data-score="50"] {
animation: milestone-burst 0.8s ease-out;
}
#clicker[data-score="100"] {
animation: victory-flash 1s ease-out;
}
@keyframes milestone-pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes milestone-burst {
0% { transform: scale(1); filter: brightness(1); }
50% { transform: scale(1.1); filter: brightness(1.5); }
100% { transform: scale(1); filter: brightness(1); }
}
@keyframes victory-flash {
0%, 100% { filter: brightness(1); }
20%, 60% { filter: brightness(2) hue-rotate(90deg); }
40%, 80% { filter: brightness(0.5); }
}
</style>
<div id="inventory"
data-state-toggles="sword,shield,potion,key"
data-sword="false"
data-shield="false"
data-potion="false"
data-key="false">
<div class="item" id="sword-slot">
<div class="icon">โ๏ธ</div>
<div>Sword: <span data-state-display="sword">false</span></div>
</div>
<div class="item" id="shield-slot">
<div class="icon">๐ก๏ธ</div>
<div>Shield: <span data-state-display="shield">false</span></div>
</div>
<!-- Buttons to collect items -->
<button data-state data-state-trigger data-state-bind="inventory"
data-state-toggle="sword">Toggle Sword</button>
<button data-state data-state-trigger data-state-bind="inventory"
data-state-toggle="shield">Toggle Shield</button>
</div>
<style>
.item {
background: #333;
padding: 15px;
border-radius: 8px;
transition: all 0.3s;
}
/* Highlight collected items */
.state-sword #sword-slot,
.state-shield #shield-slot,
.state-potion #potion-slot,
.state-key #key-slot {
background: #700c0c;
transform: scale(1.05);
box-shadow: 0 0 20px rgba(112, 12, 12, 0.6);
}
</style>
<div id="gameMenu"
data-state-toggles="menuOpen,settingsOpen,creditsOpen"
data-menuOpen="false"
data-settingsOpen="false"
data-creditsOpen="false">
<button data-state data-state-trigger data-state-bind="gameMenu"
data-state-toggle="menuOpen">Toggle Menu</button>
<div id="mainMenu">
<h3>Main Menu</h3>
<button>New Game</button>
<button>Continue</button>
<button data-state data-state-trigger data-state-bind="gameMenu"
data-state-toggle="settingsOpen">Settings</button>
<button data-state data-state-trigger data-state-bind="gameMenu"
data-state-toggle="creditsOpen">Credits</button>
</div>
<div id="settingsMenu">
<h3>Settings</h3>
<!-- Settings content -->
<button data-state data-state-trigger data-state-bind="gameMenu"
data-state-toggle="settingsOpen">Back</button>
</div>
</div>
<style>
#mainMenu, #settingsMenu, #creditsMenu {
display: none;
opacity: 0;
transform: translateY(-20px);
transition: all 0.3s;
}
/* Show menu when menuOpen is true */
.state-menuOpen #mainMenu {
display: block;
animation: menu-slide-in 0.3s forwards;
}
.state-settingsOpen #settingsMenu {
display: block;
animation: menu-slide-in 0.3s forwards;
}
.state-creditsOpen #creditsMenu {
display: block;
animation: menu-slide-in 0.3s forwards;
}
@keyframes menu-slide-in {
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
<div id="dialogue"
data-state-toggles="dialogueActive,choice1,choice2"
data-dialogueActive="false"
data-choice1="false"
data-choice2="false">
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="dialogueActive">Talk to NPC</button>
<div id="dialogueBox">
<div class="npc-name">NPC:</div>
<div class="dialogue-text">
"Welcome, traveler! How can I help you?"
</div>
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="choice1">Ask about quest</button>
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="choice2">Ask about town</button>
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="dialogueActive">Goodbye</button>
</div>
<div id="response1">
<div class="dialogue-text">"Ah yes, the ancient ruins..."</div>
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="choice1">Back</button>
</div>
<div id="response2">
<div class="dialogue-text">"This town has stood for centuries..."</div>
<button data-state data-state-trigger data-state-bind="dialogue"
data-state-toggle="choice2">Back</button>
</div>
</div>
<style>
#dialogueBox, #response1, #response2 {
display: none;
opacity: 0;
}
/* Show dialogue box when active */
.state-dialogueActive #dialogueBox {
display: block;
animation: dialogue-fade-in 0.3s forwards;
}
/* Show responses when choices selected */
.state-choice1 #response1,
.state-choice2 #response2 {
display: block;
animation: dialogue-fade-in 0.3s forwards;
}
/* Hide main dialogue when viewing responses */
.state-choice1 #dialogueBox,
.state-choice2 #dialogueBox {
display: none;
}
@keyframes dialogue-fade-in {
to { opacity: 1; }
}
.dialogue-text {
background: #1a1a1a;
padding: 20px;
border-radius: 10px;
margin: 10px 0;
border-left: 4px solid #700c0c;
}
</style>
<div id="enemy"
data-state-toggles="idle,attacking,stunned,defeated"
data-state-watch="enemyHealth"
data-state-var="true"
data-idle="true"
data-attacking="false"
data-stunned="false"
data-defeated="false"
data-enemyHealth="100"
data-enemyHealth-min="0"
data-enemyHealth-max="100">
<div class="enemy-sprite">๐พ</div>
<div class="health-bar-container">
<div class="health-bar" style="width: var(--state-enemyHealth-percent);"></div>
</div>
<button data-state data-state-trigger data-state-bind="enemy"
data-state-attr="enemyHealth" data-state-value="50">Attack</button>
<button data-state data-state-trigger data-state-bind="enemy"
data-state-toggle="stunned">Stun</button>
</div>
<style>
.enemy-sprite {
font-size: 64px;
transition: all 0.3s;
}
/* Idle state - gentle bounce */
.state-idle .enemy-sprite {
animation: enemy-idle 2s ease-in-out infinite;
}
/* Attacking state - shake */
.state-attacking .enemy-sprite {
animation: enemy-attack 0.5s linear infinite;
}
/* Stunned state - dizzy */
.state-stunned .enemy-sprite {
animation: stunned-dizzy 0.3s linear infinite;
}
/* Defeated state */
[data-enemyHealth="0"] .enemy-sprite {
animation: death 2s ease-out forwards;
}
@keyframes enemy-idle {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes enemy-attack {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px); }
75% { transform: translateX(10px); }
}
</style>
<script src="state.js"></script> <link rel="stylesheet" href="state-animations.css">
<div data-state data-state-watch="health" data-health="100">
<!-- Your game UI -->
</div>
/* Use CSS variables */
.health-bar {
width: var(--state-health-percent);
}
/* Or add animation classes */
element.classList.add('state-powered');