Animations

Pre-built animations for common UI patterns: entrance effects, loading indicators, and attention-getters. Each animation is stored as a CSS custom property so you can use it via a utility class or reference it directly in custom CSS. All animations respect prefers-reduced-motion automatically.

Entrance Animations

One-shot animations for elements appearing on screen. Useful for HTMX fragment swaps, modal reveals, and page load sequences. Click any card to replay its animation:

.animate-fade-in

Click to replay

.animate-slide-up

Click to replay

.animate-slide-down

Click to replay

.animate-scale-in

Click to replay

.animate-fade-out

Click to replay

Infinite Animations

Looping animations for loading states and attention-getters:

.animate-spin
.animate-pulse

Usage

<!-- Class-based -->
<div class="animate-fade-in">I fade in on mount</div>
<div class="animate-slide-up">I slide up on mount</div>

<!-- Loading spinner -->
<div class="animate-spin">...</div>

<!-- Skeleton placeholder -->
<div class="animate-pulse i-bg-surface rounded-md h-md"></div>

<!-- Variable in custom CSS -->
.my-modal { animation: var(--animate-scale-in); }

<!-- Disable animation -->
<div class="animate-none">No animation</div>

Reduced Motion

When prefers-reduced-motion: reduce is active, entrance animations collapse to an instant opacity change (no movement), and infinite animations are disabled entirely. This happens automatically through the config layer.

Animation Variables

--animate-fade-in - opacity 0 to 1
--animate-fade-out - opacity 1 to 0
--animate-slide-up - fade in from below
--animate-slide-down - fade in from above
--animate-scale-in - fade in with slight scale-up
--animate-spin - continuous rotation
--animate-pulse - opacity breathing effect

Entrance animations use both fill mode so elements stay in their end state. Slide distances use --size-sm from the mathematical scale, not arbitrary pixel values.