— wyss.cx / sparkles-kit / v0.1
A small kit for sparkles, holo edges, and rainbow UI.
One CSS file. No JavaScript required. No framework lock-in. The whole page you're scrolling through demos every primitive — the background blobs, the drifting sparkles, the holo cards below. Each section has the markup ready to paste.
Install
Two options. Pick whichever matches your project. Both ship the same classes.
option a — vanilla
Copy sparkles-kit.css into your project
and link it. Works with any framework or none.
<link rel="stylesheet" href="/sparkles-kit.css" />option b — vite / astro / next
Drop into src/styles/ and import once
from your root layout.
import './sparkles-kit.css';Sparkles + aurora
The blobs drifting behind everything and the dots twinkling across the page are this primitive. Drop the markup once into your root layout — both layers fix to the viewport.
<div class="sk-aurora-layer" aria-hidden="true">
<div class="sk-blob sk-blob-peach"></div>
<div class="sk-blob sk-blob-amber"></div>
<div class="sk-blob sk-blob-mint"></div>
<div class="sk-blob sk-blob-indigo"></div>
<div class="sk-blob sk-blob-violet"></div>
<div class="sk-blob sk-blob-rose"></div>
</div>
<div class="sk-aurora-veil" aria-hidden="true"></div>
<div class="sk-sparkle-layer" aria-hidden="true">
<span class="sk-sparkle sk-sparkle-ambient"
style="left:12%; top:33%; width:2px; height:2px;
--sk-c:#C5759A; --sk-base-opacity:0.6;
--sk-drift-x:30px; --sk-drift-y:-20px;"></span>
<!-- repeat for each sparkle -->
</div>Pill buttons
Three variants. .sk-pill is the warm-peach default;
.sk-pill-ghost is transparent with a hairline border;
.sk-pill-holo wraps a rotating rainbow ring that blooms on hover.
<button class="sk-pill">primary</button>
<button class="sk-pill sk-pill-ghost">ghost</button>
<button class="sk-pill sk-pill-holo">holo on hover</button>Holo card
A rotating 1px conic-gradient border around a glass surface.
Add .sk-holo-glow for an outer bloom that
intensifies on hover.
/ sk-holo-card
Quiet by default
Edge gradient at 32% until you hover. No layout shift. Background also deepens by one shade on hover.
/ + sk-holo-glow
With outer bloom
Same card, plus a heavily-blurred conic gradient bleeding outward. Hover lifts the bloom from 22% to 40%.
<div class="sk-holo-card">…content…</div>
<div class="sk-holo-card sk-holo-glow">…content with outer bloom…</div>Holo hover panel
Lighter than the card — no border ring, just a soft conic gradient that blooms behind the panel on hover.
001 / discover
Sparkles
Drifting, pulsing dots in six aurora hues.
002 / wrap
Holo edges
Conic-gradient borders rotating via @property.
003 / press
Pill buttons
Three variants. Holo glow only on demand.
<div class="sk-holo-panel">…content…</div>Prism tile
Holographic-foil background — layered diagonal aurora stripe
(animated), white caustic glints, soft conic edge ring.
Three flavors: .sk-prism-tile still,
.sk-prism-sweep sweeps on hover,
.sk-prism-festival turns up the saturation and
crosses a second dispersion stripe. JS-free.
/ sk-prism-tile
Still
Ambient iridescent foil. Slow background-position animation drifts the rainbow stripe across the surface.
/ + sk-prism-sweep
Sweep on hover
Same base, plus a second iridescent stripe that sweeps from left to right when the cursor enters. Hover me.
/ + sk-prism-festival
Festival energy.
Two crossing dispersion stripes, white caustic glints, full saturation. The Pink-Floyd-prism-meets-holo-foil flavor. Use sparingly — it commands the page.
<div class="sk-prism-tile">…still ambient…</div>
<div class="sk-prism-tile sk-prism-sweep">…sweep on hover…</div>
<div class="sk-prism-tile sk-prism-festival">…festival energy…</div>Putty blob
Inspired by glittery "smart putty". The shape morphs slowly
via animated border-radius; specular + shadow
inserts give it volume; a glitter sub-layer twinkles. Two flavors:
emerald (default) and aurora (cycles the palette through a
registered @property hue angle). Hover for a wobble.
<div class="sk-putty-blob"></div>
<div class="sk-putty-blob sk-putty-aurora"></div>Antigravity tile
Floating glass in the Linear-look idiom — backdrop-blur frosted
glass, animated specular hairline ring, aurora underglow welling
up from below, drifting particles inside. Bobs ~3px at rest;
hover lifts 8px and intensifies the underglow + edge highlight.
Add .sk-antigrav-grid for a subtle 24px dotted grid
behind the particles.
/ sk-antigrav-tile
Suspended.
Bottom-up aurora wash + drifting particles. Backdrop-blur means whatever sits behind the tile (the aurora layer here) softens through the glass.
/ + sk-antigrav-grid
With dotted grid.
Same tile plus a faint 24px dot pattern layered behind the particles. The Linear-look move that adds structure without shouting.
Bento layout — three tiles of varying weight, the kind of grid you see all over linear.app and vercel.com.
001 / hero
Wide tile, more weight.
The big tile carries the headline; the smaller ones support.
002
Support.
003
Detail.
<div class="sk-antigrav-tile">…content…</div>
<div class="sk-antigrav-tile sk-antigrav-grid">…with dotted grid…</div>Grid background
Fixed dotted (default) or lined grid overlay. Sits between the
aurora veil and the sparkles in the z-stack so blobs glow
through it. Drop in once per layout — same shape as
.sk-aurora-layer and .sk-sparkle-layer.
<!-- once per page in your root layout -->
<div class="sk-grid-bg" aria-hidden="true"></div>
<!-- or 1px lines instead of dots -->
<div class="sk-grid-bg sk-grid-lined" aria-hidden="true"></div>Color spill
Tile-sized aurora accent blob. Different from .sk-blob
(which is fullscreen) — use these for localized
accents behind hero text, beside cards, at section transitions.
Six color modifiers; add .sk-spill-drift for slow
movement.
<div class="sk-color-spill sk-spill-violet"
style="position: absolute; top: 80px; left: 40%;"></div>
<!-- or with slow drift animation -->
<div class="sk-color-spill sk-spill-mint sk-spill-drift"></div>Slider + toggle
Cross-browser styled native inputs. The slider track paints the full aurora; the toggle swaps to a gradient when checked.
/ sk-slider
/ sk-toggle
<input type="range" class="sk-slider" min="0" max="100" value="62" />
<label class="sk-toggle">
<input type="checkbox" />
<span class="sk-toggle-track"><span class="sk-toggle-thumb"></span></span>
</label>Aurora-line headline
A cream headline with a slowly-rotating conic-gradient
duplicate clipped to the text. Pass the same string twice —
once as content, once via data-text.
<h1 class="sk-aurora-line" data-text="hello, holo.">
hello, holo.
</h1>Aurora-ring avatar
Instagram-story-style ring around a circular photo well. Falls back to initials if no image is set.
<div class="sk-avatar">
<div class="sk-avatar-ring"></div>
<div class="sk-avatar-photo">nw</div>
</div>Aurora text
Static aurora-gradient text utility. Complements the
slowly-rotating .sk-aurora-line shimmer. For
big stat numbers, hero accents, or any single static rainbow
tint on text.
<h1 class="sk-aurora-text">infinity.</h1>Liquid tile
Holographic-foil flow — pastel pink/blue/violet/peach/mint
radial blobs drift across the tile via animated
background-position. Plus a glossy specular on
top for the "wet plastic" sheen. The Pinterest-aesthetic
iridescent vibe. Two flavors: pastel (default, light substrate
with dark text) and dark (uses the kit's aurora tokens).
/ sk-liquid-tile
Iridescent.
The colors flow on a 28-second cycle. No two frames look the same — the tile feels alive without being noisy.
/ + sk-liquid-dark
Same flow, dark mode.
For UIs that stay on the dark substrate. Uses the kit's aurora palette tokens, so it retones with the kit theme.
<div class="sk-liquid-tile">…content…</div>
<div class="sk-liquid-tile sk-liquid-dark">…content…</div>Spotlight tile
Cursor-tracked radial highlight (Vercel/Linear pricing-card
flavor). Hover the tiles — the glow follows your pointer.
Needs sparkles-kit.js.
/ sk-spotlight-tile
Hover to spotlight.
Move your cursor — the glow follows. Border warms up in the section accent color.
/ same primitive
One per pricing card.
Cheap visual, big payoff. The standard Linear-look tile.
<div class="sk-spotlight-tile" data-sk-spotlight>
…content…
</div>Tilt tile
3D perspective tilt toward the cursor (Stripe pricing-card
flavor). data-sk-tilt-max caps the tilt in
degrees (default 8). Needs sparkles-kit.js.
/ sk-tilt-tile
Lean toward me.
Rotates ±8° on each axis. Springs back flat on
pointerleave.
/ data-sk-tilt-max="14"
Steeper tilt.
±14°. Past 16° starts reading as rubbery rather than 3D.
<div class="sk-tilt-tile" data-sk-tilt>…</div>
<div class="sk-tilt-tile" data-sk-tilt data-sk-tilt-max="14">…</div>Stat tile
Big number + small label + optional trend arrow. Composes
.sk-aurora-text for the value gradient.
<div class="sk-stat-tile">
<div class="sk-stat-label">monthly active</div>
<div class="sk-stat-value sk-aurora-text">12,400</div>
<div class="sk-stat-trend sk-stat-trend-up">↑ 18.4% week-on-week</div>
</div>Bento layouts
Predefined grid recipes — .sk-bento-3,
.sk-bento-feature (2×2 hero + 4 cells), etc.
Auto-collapses to 1 column on mobile.
001 / hero
Bento + spotlight stack.
The hero spans 2×2; supporting tiles fill the rest.
<div class="sk-bento sk-bento-feature">
<div class="sk-bento-hero sk-spotlight-tile" data-sk-spotlight>
…hero content…
</div>
<div class="sk-stat-tile">…</div>
<div class="sk-stat-tile">…</div>
<div class="sk-stat-tile">…</div>
<div class="sk-stat-tile">…</div>
</div>Tabs
Pill-style tabs. Active tab gets a tinted background using
the live --sk-section-rgb, so the highlight
shifts as the page accent shifts.
<div class="sk-tabs" role="tablist">
<button class="sk-tab is-active" role="tab" aria-selected="true">overview</button>
<button class="sk-tab" role="tab">details</button>
<button class="sk-tab" role="tab">history</button>
</div>Form inputs
Text input + textarea with aurora focus rings. Click in and watch the border + glow shift to the section accent.
<input type="text" class="sk-input" placeholder="…" />
<textarea class="sk-textarea" placeholder="…"></textarea>Progress
Aurora-filled progress bar. Determinate (set width) or indeterminate (the fill slides infinitely).
<div class="sk-progress">
<div class="sk-progress-fill" style="width: 68%"></div>
</div>
<div class="sk-progress sk-progress-indeterminate">
<div class="sk-progress-fill"></div>
</div>Skeleton loader
Loading placeholder with an aurora shimmer wave. Set width + height inline to match the content underneath.
<div class="sk-skeleton" style="width: 60%; height: 22px"></div>
<div class="sk-skeleton" style="height: 14px"></div>Status dot
Tiny colored dot for online/busy/away/offline. The first two pulse; the others stay still.
<span class="sk-status-dot sk-status-online"></span>
<span class="sk-status-dot sk-status-busy"></span>
<span class="sk-status-dot sk-status-away"></span>
<span class="sk-status-dot sk-status-offline"></span>Tooltip
CSS-only tooltip via data-tooltip. Glassy frosted
pill above the element, fades in on hover or focus.
<button class="sk-tooltip" data-tooltip="opens the command palette">⌘K</button>Modal scaffold
Backdrop-blurred overlay + a sized container. Compose with
.sk-antigrav-tile or .sk-holo-card
for the panel visual.
/ sk-modal . sk-antigrav-tile
Floating dialog.
The backdrop blurs the page behind. The panel is just an antigrav tile — same primitive, different mounting.
<div class="sk-modal-backdrop" data-sk-modal>
<div class="sk-modal sk-antigrav-tile">
…content…
<button class="sk-pill sk-pill-ghost">close</button>
</div>
</div>Command palette · ⌘K
Press ⌘K (or Ctrl+K) anywhere on
this page — a working palette pops up over the content.
Type to filter, ↑↓ to navigate, ↵
to confirm, Esc to close.
- Open project ⌘O
- Find in files ⌘F
- Toggle terminal ⌃`
- Switch theme ⌘T
<!-- once per page; sparkles-kit.js wires up ⌘K, ↑↓, ↵, Esc -->
<div class="sk-modal-backdrop" data-sk-cmdk-root hidden>
<div class="sk-cmdk">
<input class="sk-cmdk-input" data-sk-cmdk-input
placeholder="search commands…" />
<ul class="sk-cmdk-list" data-sk-cmdk-list>
<li class="sk-cmdk-item">
<span>Open project</span>
<kbd class="sk-kbd">⌘O</kbd>
</li>
…
</ul>
</div>
</div>Marquee
Smooth horizontal scroll for a "trusted by" / "features" row. Edge-faded both sides via mask. Hover pauses the animation. Duplicate items inside the track for a seamless loop.
<div class="sk-marquee">
<div class="sk-marquee-track">
<span>item 1</span><span>item 2</span><span>item 3</span>
<!-- duplicate for seamless loop -->
<span>item 1</span><span>item 2</span><span>item 3</span>
</div>
</div>Divider
Section divider — neutral hairline, or aurora-tinted.
<hr class="sk-divider" />
<hr class="sk-divider sk-divider-aurora" />Noise overlay
Subtle SVG-grain layer that tints the whole viewport via
mix-blend-mode: overlay. Adds a faint cinematic
texture so the dark base doesn't look flat.
<div class="sk-noise-overlay" aria-hidden="true"></div>Custom cursor
Soft halo that follows the OS pointer with a slight lag.
Grows on hover over interactive elements (buttons, links,
etc.). On wyss.cx the existing brand cursor stays in
charge — we don't mount .sk-cursor here; the
snippet shows what to put in your own layout.
<!-- once per page in your root layout -->
<div class="sk-cursor" aria-hidden="true"></div>
<!-- + the JS layer to animate it -->
<script src="/sparkles-kit.js" defer></script>Magnetic buttons
Buttons that subtly pull toward your cursor on hover. Linear,
Vercel, Stripe all use this for primary CTAs. Strength
defaults to 0.3; override per-element with
data-sk-magnetic-strength.
<button class="sk-pill sk-magnetic" data-sk-magnetic>default</button>
<button class="sk-pill sk-magnetic" data-sk-magnetic
data-sk-magnetic-strength="0.55">stronger pull</button>Click ripple
Material-style wave that expands from the click point. JS
appends a <span class="sk-ripple-wave">
at the click coordinates; CSS animates the expand+fade,
then the script removes the element.
<button class="sk-pill sk-ripple" data-sk-ripple>click me</button>
<!-- composes with magnetic + any pill variant -->
<button class="sk-pill sk-pill-holo sk-ripple sk-magnetic"
data-sk-ripple data-sk-magnetic>both effects</button>Flip card
3D card-flip on hover (default) or click-toggle (CSS-only via
:has() + a hidden checkbox). The inner container
has transform-style: preserve-3d; each face has
backface-visibility: hidden. Pure CSS — zero JS.
/ sk-flip-card · hover
Hover to flip.
Cursor enters → card spins. Cursor leaves → spins back.
/ back face
What's behind?
Anything you want — different content, image, form, link.
<!-- hover-flip (default) -->
<div class="sk-flip-card" style="height: 240px;">
<div class="sk-flip-card-inner">
<div class="sk-flip-card-face sk-flip-card-front">…front…</div>
<div class="sk-flip-card-face sk-flip-card-back">…back…</div>
</div>
</div>
<!-- click-to-toggle — wrap in <label> with hidden checkbox -->
<label class="sk-flip-card sk-flip-card-toggle" style="height: 240px;">
<input type="checkbox" hidden />
<div class="sk-flip-card-inner">
<div class="sk-flip-card-face sk-flip-card-front">…</div>
<div class="sk-flip-card-face sk-flip-card-back">…</div>
</div>
</label>Reveal + stagger on scroll
Scroll-driven entrance via animation-timeline: view().
Element fades + slides up as it enters the viewport — animation
progress is bound to scroll position, not time. Zero JS. In
browsers without scroll-timeline support, the element jumps
straight to its end state (graceful fallback).
/ sk-reveal
I appeared as you scrolled.
Scroll up + back down to see it again. The whole tile is one
.sk-reveal.
Stagger — six chips, each enters slightly after the previous as you scroll past:
<div class="sk-reveal">…fades + slides up as it scrolls in…</div>
<ul class="sk-stagger-children">
<li>first</li>
<li>second <!-- enters slightly after #1 --></li>
<li>third <!-- slightly after #2 --></li>
</ul>
<!-- For >12 children, set --i inline: -->
<div class="sk-stagger-children">
<div style="--i: 12">thirteenth</div>
</div>Customizing
Every visual is behind a --sk-* custom property.
Override on :root (or any ancestor) to retheme
the entire kit. Six aurora hues, the surfaces, and one
section accent.
:root {
--sk-peach: #D97757;
--sk-rose: #C5759A;
--sk-violet: #8E7FB8;
--sk-indigo: #6B8DC9;
--sk-mint: #7FB69E;
--sk-amber: #D9B377;
--sk-bg-base: #0A0A0A;
--sk-bg-elevated: #141413;
--sk-text-primary: #F5F1EB;
--sk-text-secondary: #8B8884;
--sk-section-rgb: 217, 119, 87;
}