Skip to content
HN On Hacker News ↗

CSS Feature Clips: Looping Product Demos Without Video

▲ 19 points • 10 comments • by hauju • 1d ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

100 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 17
SEGMENTS · AI 17 of 17
WORD COUNT 811
PEAK AI % 100% · §1
Analyzed
Nov 5
backend: pangram/v3.3
Segments scanned
17 windows
avg 48 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 811 words · 17 segments analyzed

Human AI-generated
§1 AI · 100%

Free technique and promptA clip is a 10-second loop of simplified UI in plain HTML and CSS. It stays sharp at any size, follows your theme, plays before any JavaScript loads, and you edit it instead of re-recording it. It works in any framework.Get the prompt$ stepshots record signup-flowUsing config: /home/ada/acme/stepshots.config.jsonRecording: Sign up (signup-flow) Created: output/signup-flow.stepshot (4 steps)Next: upload to your dashboard with stepshots upload output/signup-flow.stepshotMore examplesThese are real Stepshots flows with sample data. All three clips on this page share one stylesheet of 3.3 KB gzipped, and none of them use JavaScript.SelectHotspotHighlightBlurZoomArrowSavedSaveAcme settingsWorkspaceAcme IncAPI keyacme_7f3k92hd81acme_7f3k92hd81PlanProTool state, two overlays, and a label that flips between Saved and Save.AnalyticsAcme onboarding7d30d90dTotal Views4121,284Unique Visitors268873Completion Rate58%64%Views Over TimeNumbers swap on a click, and an SVG line draws itself.The promptPaste it into your coding agent and fill in the feature.Build a looping product demo clip for my marketing page as mock UI in plain HTML and CSS keyframes. No video, no GIF, no JavaScript. The feature to show: [describe one short flow, e.g. "user invites a teammate and the seat count goes up"] Rules: 1. Show only what the product does. Read the real UI first and copy its labels exactly. Where the product produces output, run it and copy that. Simplify, but never invent features, buttons or results. Use a fictional company such as Acme for sample data.

§2 AI · 100%

2.

§3 AI · 100%

Write the story as 3 or 4 beats on a 10-second, 0-100% timeline. Leave 3% at the start and 4% at the end for a loop fade on the clip body.

§4 AI · 100%

3.

§5 AI · 100%

Base styles are the last frame. Without keyframes every element must already look finished, so anything that leaves during the loop has a base of opacity: 0.

§6 AI · 100%

4.

§7 AI · 100%

Size everything in em so the mock scales like a video: .fc { container-type: inline-size; width: 100%; aspect-ratio: 740 / 415; } .fc-stage { position: relative; height: 100%; overflow: hidden; font-size: 2.2cqw; } The stage is about 45.45em by 25.5em. Avoid px inside the clip.

§8 AI · 100%

5.

§9 AI · 100%

Use the project's theme tokens so the clip follows light and dark. Hard-code only things that have one colour in real life, such as a terminal.

§10 AI · 100%

6.

§11 AI · 100%

Share timing through reusable classes (fc-in-30 appears at 30%) rather than one keyframe per element. Type text by stepping clip-path: inset(0 100% 0 0) to inset(0) with steps() sized to the character count.

§12 AI · 100%

7.

§13 AI · 100%

For a value that changes, stack both in one grid cell. Swap text instantly with step-end, because two labels mid-fade smear.

§14 AI · 100%

8.

§15 AI · 100%

Give the cursor its own keyframes with top/left percentages and a brief scale(0.8) per click. Its tip is the top-left corner, so aim near the target, not over its text.

§16 AI · 100%

9.

§17 AI · 100%

Add this, because looping clips would otherwise end on their reset state: @media (prefers-reduced-motion: reduce) { .fc-body, .fc-body * { animation: none !important; } .fc-cursor { display: none; } } 10. Put role="img" and an aria-label describing what happens on the clip. Use my framework's component syntax, but keep the output plain HTML and CSS. Then check it: pause all animations with document.getAnimations(), set currentTime to one frame per beat, and screenshot each. Confirm the cursor lands on its target, nothing overflows at 390px wide, both themes work, and the reduced-motion frame reads correctly.The smallest working clipNo build step or library. Because it's plain markup, it ports to React, Vue, Svelte, Astro, Rails or Dioxus by changing only the template syntax.<div class="fc" role="img" aria-label="A status changes from Draft to Published"> <div class="fc-stage"> <div class="fc-body"> <span class="swap"> <span class="draft">Draft</span> <span class="live">Published</span> </span> </div> </div> </div> <style> .fc { container-type: inline-size; width: 100%; aspect-ratio: 740 / 415; } .fc-stage { position: relative; height: 100%; overflow: hidden; font-size: 2.2cqw; } .fc-body { animation: fc-loop 10s linear infinite; } .swap { display: inline-grid; } .swap > * { grid-area: 1 / 1; } /* Base styles are the last frame: Published shows, Draft doesn't. */ .draft { opacity: 0; animation: fc-draft 10s step-end infinite; } .live { animation: fc-live 10s step-end infinite; } @keyframes fc-draft { 0% { opacity: 1; } 50%, 100% { opacity: 0; } } @keyframes fc-live { 0% { opacity: 0; } 50%, 100% { opacity: 1; } } @keyframes fc-loop { 0% { opacity: 0; } 3%, 96% { opacity: 1; } 100% { opacity: 0; } } @media (prefers-reduced-motion: reduce) { .fc-body, .fc-body * { animation: none !important; } } </style>Clip or interactive demo?A clip is a simplified mock, so it proves less than the real product. Use it to explain, and use a recording to prove.Use a CSS clip forOne idea, shown in 10 secondsFeature rows on a landing pageMotion that needs no clickUse an interactive demo forReal screens, click by clickFull flows that buyers explore at their own paceSeeing where viewers drop offNeed the real thing?Stepshots records your actual product into a clickable demo you can embed and track.Create your first demo