A neo-brutalist product page for a savings app stamps itself together on oat: thick black borders, hard offset shadows, candy-colored blocks, jars filling, stickers slapping on and marquee strips crossing, while a cursor presses the chunky Start saving button into its shadow.
Written and rendered by AI CSS Animations Oct 19, 2026
Neo-brutalism in web and app design took hold in the early 2020s: flat, saturated blocks of color, thick black borders, hard drop shadows with no blur, oversized type and stickers. It is a friendlier descendant of the raw brutalist websites of the 2010s, adding the bright colors of toys and zines to their exposed structure. Startups, creator tools and indie brands use it to look confident, playful and hand-built rather than corporate.
Make a 10-second neo-brutalist product page: a candy-colored landing page for a savings app stamps itself together with thick black borders and hard shadows, stickers slap on, marquee strips run, and a cursor presses a chunky button into its shadow.
<inputs>
If I don't give you something, use the default and don't ask.
- Product: Jarloo (fictional), a savings app that sorts round-ups into jars.
- Headline: "Save like you mean it."
- Subhead: "Round up every coffee, sort it into jars and watch them fill."
- Nav: Features · Pricing · Stories · Log in, and a "Get Jarloo" button.
- Buttons: "Start saving" and "See how it works"
- Trust line: "FREE FOREVER · PRO $4/MONTH"
- Jars: Holiday $640.00 of $1,200 · Bike $310.00 of $450 · Rainy day $1,180.00 of $2,000 · Total saved $2,130.00
- After the click: "Round-up added · +$4.20 to Holiday", so Holiday becomes $644.20 and the total $2,134.20.
- Stickers: NEW! · 0% FEES · ★ 4.9 · NO SPREADSHEETS
- Marquee: ROUND-UPS · SAVING JARS · ZERO FEES · WEEKLY STREAKS
- Length: 10 seconds.
</inputs>
<direction>
- Look: the neo-brutalist web style: flat candy-colored blocks, 4px black borders on everything, hard offset shadows with no blur, chunky display type, buttons that physically press into their shadows, stickers slapped on at angles and marquee strips crossing the page. Loud, friendly and tactile; nothing glossy.
- Palette: page oat #F4EFE3 with a dotted grid (2px dots every 32px, #111111 at 12%); ink #111111; tomato #FF5A36; butter #FFD84D; pistachio #B6E57A; periwinkle #8EA2FF; bubblegum #FF9ECF; white #FFFFFF for cards. Every block is one flat color; every hard shadow is solid ink, offset 8px right and 8px down (6px on small elements, 10px on the app panel).
- Type: Bricolage Grotesque (request its opsz and wdth axes) 800 for display: the headline at 136px, leading 0.92, tracking −0.02em, wdth 100, opsz 96; Space Grotesk 500–700 for body and buttons; Space Mono 700 for labels and amounts, uppercase where they are labels.
- Layout on the 1920 × 1080 stage:
- nav: a white bar x 120–1800, y 70–150, with the 4px border, a 12px radius and a 6px shadow; at the left a jar icon (52px: a tomato rounded body, a butter lid band, ink borders) and "Jarloo" in Bricolage Grotesque 800, 40px; the links in Space Grotesk 600, 24px, at x 800, 960, 1110 and 1260; "Get Jarloo" as a butter button 200 × 56 at the right end;
- hero, left: the headline in two lines ("Save like" / "you mean it.") on baselines 330 and 470 from x 120, the word "mean" sitting on a butter block rotated −2° with its own ink border; the subhead in Space Grotesk 500, 28px, at most 760px wide, at y 540–620; "Start saving" (tomato, 320 × 84) at x 120 and "See how it works" (white, 330 × 84) at x 470, both at y 680, labels in Space Grotesk 700, 28px, ink; the trust line in Space Mono 700, 20px, at y 820;
- app panel, right: a periwinkle block x 1080–1800, y 210–800 (10px shadow, 16px radius) holding "Your jars" in Bricolage Grotesque 800, 44px; three white jar cards (640 × 110, 6px shadows) each with a jar icon in its color, the name in Space Grotesk 700, 26px, the amount in Space Mono 700, 22px, a progress bar 600 × 26 (white, 4px border) filled in the jar's color (Holiday pistachio, Bike butter, Rainy day bubblegum) and its percent (53%, 69%, 59%); then "Total saved" with "$2,130.00" in Bricolage Grotesque 800, 64px;
- stickers: NEW! as a tomato twelve-point starburst 150px across at (960, 250), rotated −12°, beside the headline's first line; 0% FEES as a pistachio circle 150px across at (1740, 230), rotated 8°, over the panel's corner; ★ 4.9 as a butter pill 170 × 64 at (880–1050, 690–754), rotated −6°; NO SPREADSHEETS as a bubblegum rectangle 330 × 80 with zigzag ends, rotated 7°, centered at (1660, 810) over the panel's lower-right corner, clear of the total; all with 4px ink borders, 6px shadows and Space Mono 700 or Bricolage Grotesque 800 lettering;
- marquees: two strips 76px tall running past both edges of the stage at the bottom, crossing each other: an ink strip with butter text rotated −3°, centered at y 925, moving left at 140px/s, and a tomato strip with ink text rotated +2.5°, centered at y 935, moving right at 140px/s. Text in Space Mono 700, 30px, its phrases separated by six-point asterisks drawn in SVG.
- Motion, a few physical verbs:
- stamp: blocks arrive from scale 1.08 and 24px above with their shadow at 0, landing in 0.28 s on cubic-bezier(0.2, 0.9, 0.3, 1.2) (a small overshoot) as the shadow snaps out to its full offset; opacity goes from 0 to 1 within the first 0.05 s only, so nothing fades;
- press: hover lifts a button by (−2px, −2px) as its shadow grows to 10px over 0.12 s; a press drives it down to (+8px, +8px) with its shadow at 0 in 0.06 s, holds 0.1 s and springs back on a damped spring (damping ratio 0.5, about 0.35 s);
- slap: stickers come in from scale 1.5 with 18° of extra rotation and land in 0.1 s with a 4% squash for 0.05 s, then wobble ±2° once over 0.25 s;
- run: marquees move at constant speed (translate by speed × t modulo one repeat), seamless;
- bars fill over 0.6 s on cubic-bezier(0.3, 0, 0.2, 1), each fill ending in a 4px ink edge; amounts roll digit by digit like an odometer over 0.4 s.
- Cursor: a chunky arrow 44px tall, ink with a 3px white outline and a 4px hard ink shadow, moving on curved paths with easeInOutCubic and a slight 6px overshoot at each stop; each click throws a burst of three short ink strokes (10px long, 4px thick) that pop 12px outward from its tip in 0.2 s.
- Premium: strict 4px borders and hard shadows everywhere, a button that truly presses into its shadow, confident flat blocks of color, type big enough to shout, stickers with real ink edges, numbers that add up. Cheap: soft blurred shadows, gradients, thin hairline borders, random tilts on everything, pastel glassmorphism.
Banned: gradients, blurred shadows, glass or blur effects, corner radii over 16px, hairline borders, photos, emoji, real brands or payment logos, 3D, fading entrances, anything flashing more than 3 times per second.
</direction>
<structure>
- 0.0–0.8s: the oat page with its dotted grid; the nav bar stamps in, then the logo, links and Get Jarloo button pop in left to right, 50 ms apart.
- 0.8–2.0s: the headline lands word by word (each word a stamped block of type, 90 ms apart), the butter block under "mean" stamps in behind its word, the subhead slides up 20px, and the two buttons stamp in.
- 2.0–3.4s: the periwinkle app panel stamps in at the right; the jar cards stamp in 0.1 s apart; the three bars fill (2.4–3.2 s, staggered) and the total rolls up to $2,130.00.
- 3.4–4.6s: the stickers slap on: NEW! (3.5 s), 0% FEES (3.9 s), ★ 4.9 (4.2 s); the two marquee strips slide in from opposite sides and start running.
- 4.6–6.6s: the cursor enters from the lower right, passes over the jar cards (each lifts 2px as it is hovered), then moves to Start saving and hovers it, the button lifted, at 6.0 s. The 6.0 s frame is the complete page with the cursor on the lifted button.
- 6.6–7.8s: the click at 6.7 s: the button presses fully into its shadow and springs back, with the click burst; the toast "Round-up added · +$4.20 to Holiday" (a white card with a pistachio check square, 4px border, 6px shadow) stamps in at x 1120–1600, y 166–240, over the panel's top edge (6.9 s); the Holiday bar grows to 54%, its amount rolls to $644.20 and the total to $2,134.20.
- 7.8–8.6s: NO SPREADSHEETS slaps on last; the cursor drifts aside and rests.
- 8.6–10.0s: hold; only the marquees keep running.
For other lengths, stretch the cursor's tour; keep each stamp, slap and press at its own timing and at least 1 s of hold.
</structure>
<build>
- One self-contained index.html (inline CSS and JS), a 1920×1080 (16:9) stage scaled to fit the window, designed for 60fps. No image, video, texture or model files: every shape and texture is generated in code.
- window.seek(t), t in seconds, computes every visual from t alone: no CSS transitions or CSS animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. Anything cumulative is solved analytically from t or precomputed once at load at a fixed step. Past the end, seek clamps to the last frame.
- Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop.
- Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek.
- Engine: HTML/CSS: absolutely positioned elements whose transforms, sizes and opacity are set from seek, with inline SVG for the jar icons, sticker shapes, asterisks and cursor; no canvas and no other libraries (no three.js: this style is flat).
- Springs and odometers are closed-form functions of the time since each element's start; marquee offsets are (speed × t) modulo the strip's repeat width; the dotted grid is one CSS background drawn once.
</build>
<check>
Before showing me, step through one frame per second (t = 0…10): screenshot each and look at it. Fix overlaps, clipped or cramped text, and anything off-style or Banned. Check every element has a 4px ink border and a hard shadow with no blur, the pressed button's offset equals its shadow so it sits flush, the numbers add up (640 + 310 + 1,180 = 2,130, then 2,134.20 with Holiday at $644.20 and 54%), the marquees loop seamlessly, no sticker covers a headline word, an amount or the button labels, nothing important sits within 60px of an edge, and the 6.0 s and final frames are complete. Confirm seek(10) and seek(11) match, so the final frame holds.
</check> Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
A slow, ribbon-like gradient mesh flows in a skewed band behind sharp headline type, while white payment, API and chart…
Glass panels with real refraction float over vivid, striped color: their rims bend what's behind them, two buttons fuse…
A dark-mode work tool drawn in hairlines and quiet radial glows: issue rows populate, ⌘K opens a command menu, a comman…
Rounded tiles spring into a bento grid on warm paper, each acting out one feature in a small animation, then the tiles…
More like this on the motion design inspiration board: UI animation inspirationLanding page animation inspiration