Code
CSS
Colors
Color formats, opacity, gradients, and CSS custom properties.
Typography
Font stacks, sizing, weight, line-height, spacing, and truncation.
Sizing
Width, height, min/max, units, aspect-ratio, and clamp().
Box Model
Content, padding, border, margin, box-sizing, and margin collapse.
Flexbox
One-dimensional layout — direction, alignment, wrap, grow/shrink.
Grid
Two-dimensional layout — columns, rows, areas, auto-fill, and dense.
Responsive Design
Media queries, mobile-first, container queries, and fluid techniques.
Animation
@keyframes, timing functions, fill-mode, staggered sequences and more.
Generative Art with CSS
Pure CSS as a generative-art engine — layered gradients, blend modes, keyframe motion, and noise.
Generative Art with CSS
Pure CSS as a generative-art engine — layers, repetition, transforms, blend modes, and animation. No canvas, no JS rendering loop.
1. Layered Gradients — the CSS "shader"
Stack unlimited radial-gradient or linear-gradient layers on a single element. Each layer is like a brush stroke — overlap them to produce atmospheric, painterly fields.
.art {
background:
radial-gradient(circle at 20% 30%, #ff6b6b, transparent 60%),
radial-gradient(circle at 80% 70%, #4ecdc4, transparent 60%),
radial-gradient(circle at 50% 50%, #ffe66d, transparent 60%),
#1a1a1a;
}2. CSS Variables as "Random Seeds"
Inject randomness with JS once, then let CSS own the rendering. Math.random() sets a custom property; var() drives every visual decision. This gives generative variation without a rendering engine.
/* JS — runs once on load */
document.documentElement.style.setProperty('--x', Math.random() * 100 + '%');
document.documentElement.style.setProperty('--y', Math.random() * 100 + '%');
/* CSS — consumes the variables */
.blob {
width: 100vw;
height: 100vh;
background: radial-gradient(circle at var(--x) var(--y), #ff0080, #000);
}3. Pseudo-elements as Instances
::before and ::after create two extra shape layers with zero extra HTML. With mix-blend-mode: screen and filter: blur() they interact like light sources.
.art::before,
.art::after {
content: "";
position: absolute;
inset: -20%;
background: radial-gradient(circle, #ff0080, transparent 60%);
mix-blend-mode: screen;
animation: move 20s infinite alternate ease-in-out;
filter: blur(80px);
}
.art::after {
background: radial-gradient(circle, #00e5ff, transparent 60%);
animation-duration: 25s;
}
@keyframes move {
0% { transform: translate(-20%, -10%) scale(1); }
100% { transform: translate(20%, 10%) scale(1.4); }
}4. Conic Gradient + Rotation
conic-gradient maps colour around a full 360° sweep — great for colour wheels, mandala-like forms, and spinning spectrum effects. Add filter: blur() contrast() to sharpen edges into hard bands.
.spinner {
width: 160px;
height: 160px;
border-radius: 50%;
background: conic-gradient(
from 0deg,
#ff0080, #ffce00, #00e5ff,
#7c3aed, #ff0080
);
animation: spin 6s linear infinite;
filter: blur(2px) contrast(120%);
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}5. Hue-Rotate Aurora
Animate filter: hue-rotate() over stacked radial gradients to cycle all colours on the spectrum over time — a simple one-liner that produces a living, breathing aurora borealis effect.
.aurora {
background:
radial-gradient(ellipse at 30% 60%, #a855f7, transparent 55%),
radial-gradient(ellipse at 70% 40%, #06b6d4, transparent 55%),
radial-gradient(ellipse at 50% 80%, #10b981, transparent 55%),
#0a0a0a;
animation: hue-drift 12s linear infinite;
}
@keyframes hue-drift {
from { filter: hue-rotate(0deg) saturate(180%) blur(40px); }
to { filter: hue-rotate(360deg) saturate(180%) blur(40px); }
}6. Box-Shadow Particle Field
A single element can fake hundreds of particles via box-shadow — each shadow entry is an independent "copy" of the element positioned anywhere on the canvas. Generate a large shadow list with JS for thousands of particles.
/* Generate with JS for scale */
const shadows = Array.from({ length: 200 }, () => {
const x = Math.random() * 100;
const y = Math.random() * 100;
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
return `${x}vw ${y}vh 4px 2px rgb(${r},${g},255)`;
}).join(',');
el.style.boxShadow = shadows;
@keyframes fall {
from { transform: translateY(0); }
to { transform: translateY(100vh); }
}7. CSS Noise (Repeating Gradients)
Two repeating-linear-gradient layers at 90° form a grid. Animate a tiny translate jitter and layer with mix-blend-mode: difference for a gritty, analog-video texture.
.noise {
background:
repeating-linear-gradient(90deg, #000 0 1px, #111 1px 3px),
repeating-linear-gradient(0deg, #000 0 1px, #111 1px 3px);
mix-blend-mode: difference;
animation: jitter 0.18s steps(1) infinite;
}
@keyframes jitter {
0% { transform: translate(0, 0); }
25% { transform: translate(1px, -1px); }
50% { transform: translate(-1px, 1px); }
75% { transform: translate(1px, 1px); }
}8. Plasma Field — Stacked Conic Rotations
Layer three oversized conic-gradient divs rotating at different speeds with mix-blend-mode: screen. The colour interference between counter-rotating layers produces an organic plasma effect.
.plasma-a {
background: conic-gradient(from 0deg, #ff0080, #ffce00, transparent 50%);
animation: spin-a 8s linear infinite;
filter: blur(30px);
mix-blend-mode: screen;
}
.plasma-b {
background: conic-gradient(from 180deg, #00e5ff, #7c3aed, transparent 50%);
animation: spin-b 12s linear infinite; /* counter-rotate */
}
.plasma-c {
background: conic-gradient(from 90deg, #10b981, #f59e0b, transparent 50%);
animation: spin-a 18s linear infinite;
}9. Moiré Interference Pattern
Two identical fine-line grids rotated slightly against each other produce moiré fringes — classic optical interference. Animate the rotation and watch the fringes ripple and breathe.
.lines-a, .lines-b {
position: absolute;
inset: 0;
}
.lines-a {
background: repeating-linear-gradient(
0deg, #000 0 1px, transparent 1px 6px
);
animation: rotate-a 3s ease-in-out infinite alternate;
}
.lines-b {
background: repeating-linear-gradient(
90deg, #000 0 1px, transparent 1px 6px
);
mix-blend-mode: multiply;
animation: rotate-b 3s ease-in-out infinite alternate;
}