
An animated website background spends one of three resources: bytes for a video loop, paint for a CSS gradient that redraws itself, or GPU time for a shader or a particle field. Pick the one whose cost you can cap, write the cap down as a number, and the background stays behind the page instead of in front of it.
Slow backgrounds tend to be ones that were liked and never measured. A 24 second loop shipped to a phone, a full-screen gradient that repaints sixty times a second, a particle field that compares every pair of dots on every frame: each one looks fine on the laptop it was built on. The values below decide whether it still looks fine on a mid-range phone on a train.
If you want a loop that is already cut for a hero, Thanor's animated backgrounds page has looping video backgrounds you can copy by URL into Claude, Cursor, Lovable or Bolt, or download. The rest of this guide covers how to use one, or build your own, without paying for it in load time.
What each kind of animated background costs#
Five techniques cover nearly every moving background on the web, and each one fails in a different place.
| Technique | What moves | Where the cost lands | Budget to hold |
|---|---|---|---|
| Video loop | decoded frames from a file | download size, then the hardware decoder | about 2.5 MB desktop, 1 MB phone, 6 to 10 s |
| CSS gradient | a gradient layer | paint on every frame, unless the layer moves with transform | 0 KB, one composited layer |
| WebGL shader | every pixel, computed each frame | GPU time per pixel | pixel ratio capped at 1.5, 30 to 60 fps |
| Canvas particles | dozens to thousands of dots | JavaScript each frame, plus pair checks for linked lines | about one particle per 12,000 px² |
| Lottie | vector shapes from an After Effects file | JSON size and the player's work per frame | short, few layers |
The video row looks heaviest and is often the lightest to run. Once the file has arrived, phones and laptops decode H.264 in dedicated hardware, so the loop costs the main thread almost nothing. Its whole cost is paid up front in bytes, and an encoder setting controls that.
A shader is the reverse: a few kilobytes of code, and a cost that never stops. At a pixel ratio of 2, a 1440 by 900 viewport is 2880 by 1800 pixels, about 5.2 million per frame, or roughly 311 million pixel computations a second at 60 fps. On a 120 Hz screen requestAnimationFrame can fire twice as often, since its rate generally matches the display, as MDN notes, and the bill doubles with it.
The particle row hides a quadratic. The classic linked-dots effect draws a line between any two particles that are close, which means checking every pair: 150 particles is 11,175 checks per frame. That nested loop is in particles.js, whose last release dates from 2015, and its work grows with the square of the count.
Video loops give the most picture for the least code#
A looping film is the only technique in that table that can show a real place, a material or a character. A hotel can open on a film of its own terrace, as long as the booking dates still sit in that first screen. That is why so many designs in the Thanor library are built on films, set full-bleed behind the type or behind a subject that stands in front of the headline.
A corgi courier sprints through sunflower fields in a 24 second full-bleed loop behind the "Field day" headline.
Open the prompt →A pink clay ribbon loops on lilac behind a giant black "BRISK", motion that never competes with the word.
Open the prompt →A rainbow lorikeet perches in front of its own huge headline, the film doing the work a gradient usually does.
Open the prompt →These films show where the budget really goes. The ribbon film behind Brisk is a 7.5 second loop at 1920 by 1080 in H.264, and the file weighs about 2.1 MB. The run behind Zoomies lasts 24 seconds at 1600 by 900 and weighs about 11.7 MB, because a long tracking shot brings new picture into every second. Loop length is the budget, more than resolution: a camera that holds still while the subject moves for 6 to 10 seconds compresses to a fraction of a long camera move.
Three attributes make any of these autoplay on an iPhone, and one file property makes it unconditional. WebKit's video policy for iOS lets a video autoplay without a tap when it is muted or when its file has no audio track, and plays it inline only with playsinline. Strip the audio track at export and no framework can break the rule by dropping an attribute.
Encoding, the phone cut and the markup are covered step by step in the video background guide.
Gradients and shaders: motion with nothing to download#
A gradient background downloads nothing, which makes it the right choice when the page has no picture to show. Its trap is paint. Per web.dev, changing any property other than transform or opacity triggers paint, and backgrounds are named in that rule. The common recipe, an oversized gradient whose background-position is animated, repaints the whole element every frame.
Move the layer instead of repainting it:
.hero { position: relative; overflow: clip; isolation: isolate; background: #0E0B1A; }
.hero::before {
content: ""; position: absolute; inset: -15%; z-index: -1;
background:
radial-gradient(40% 50% at 30% 40%, #7C5CFF 0%, transparent 70%),
radial-gradient(35% 45% at 70% 65%, #FF6A88 0%, transparent 70%);
animation: drift 24s cubic-bezier(0.45, 0, 0.55, 1) infinite alternate;
}
@keyframes drift { to { transform: translate3d(8%, -6%, 0) rotate(6deg); } }
@media (prefers-reduced-motion: reduce) { .hero::before { animation: none; } }The gradient is painted once and the compositor slides it. The -15% inset is overscan that keeps the edges out of sight while the layer moves, and it costs memory: a layer is stored at device pixels, four bytes each, so a 1440 by 900 hero at a pixel ratio of 2 is about 20.7 MB of texture, and the overscan raises that to about 35 MB. Keep it as small as the motion allows.
Shaders earn their GPU time when the motion has to look organic, like ink, liquid light or a field that answers the pointer. Cap the resolution, cap the frame rate and pause off screen, and the per-frame cost becomes a number you chose. The fragment shader, the banding fix and the particle math are in the gradient and shader guide, and the Three.js examples cover full 3D scenes.
Backgrounds that move only when the visitor does#
The cheapest animated background is one that holds still until someone interacts with it. A character that turns toward the cursor, or eyes that follow it, costs almost nothing while the visitor reads, and every movement it makes answers something the visitor did.
A ginger kitten on teal chases the red laser dot that you steer with your cursor.
Open the prompt →Free. A small diver stands in front of a huge white word in a cavern, and its eyes follow your cursor.
Open the prompt →Vesperion is free with an account and shows the idea at its plainest: the scene is a cavern and a word, and the motion that matters is the creature's attention. Three values make this kind of background feel alive rather than mechanical:
- Lag: follow the pointer with easing, for example moving
8%of the remaining distance each frame, so the gaze arrives a beat after the cursor. - Range: cap the turn, say
±25°for a head and a few pixels for pupils, so the character never looks broken at the edge of the screen. - Rest: after
2swithout input, ease back to a neutral pose over about600ms.
The work per frame is a little arithmetic and one transform, and the loop can stop once the pose has settled. Touch screens have no pointer to follow, so decide what happens there: hold a pose, follow the last tap, or play a short idle loop. A brief that leaves this out gets a character that freezes mid-glance on every phone.
Budgets that keep a moving background fast#
Six rules keep any of these techniques from costing the page its first impression. Each is a value or a switch, so each can go straight into a brief.
- The poster is the first paint. For a
<video>, Largest Contentful Paint uses the poster's load time or the first frame's presentation time, whichever is earlier, and a good LCP is 2.5 seconds or less. Ship a poster of about 60 to 120 KB cut from the first frame. - Pause off screen. Browsers pause
requestAnimationFramein background tabs, but not in a canvas the visitor has scrolled past. AnIntersectionObserverthat stops the loop when the hero leaves the viewport removes most of a shader's cost on a long page. iOS already pauses autoplaying video that scrolls out of view. - Cap density. Render a shader at a pixel ratio of at most
1.5, or at half resolution for soft gradients, and hold ambient motion to30 fps, which halves the work and rarely shows in a slow drift. - Honor reduced motion. Under
prefers-reduced-motion: reduce, show the poster or a still frame. The query has worked across browsers since 2020, per MDN. - Give it a pause button. WCAG's Pause, Stop, Hide criterion, Level A, requires a way to pause moving content that starts on its own, lasts more than five seconds and sits beside other content. A looping hero meets all three conditions.
- Measure text against the brightest frame. Body text needs
4.5:1and large text3:1. Over a white frame, white type needs a black scrim of at least54%for body text and42%for large text.
The scrim figures are the WCAG contrast formula applied to the worst frame. A gradient scrim that reaches that opacity only in the band behind the type, like the one in the hero section values, keeps the rest of the picture bright.
How to brief an AI model for an animated background#
A model asked for "an animated background" returns the drifting blob gradient it has seen most often. Given a specification, it builds the specification, and an adjective like "subtle" leaves every number for the model to guess. Every brief for a moving background has to carry these lines:
- Source: the clip URL, or the gradient colors in hex with the interpolation space.
- Fit:
object-fit: cover, plus anobject-positionthat keeps the subject in frame on a phone. - Phone behavior: a separate portrait cut, or a still poster below
768px. - Overlay: the scrim as a value, never as "a dark overlay".
- Motion budget: period, easing, frame-rate cap, pause off screen.
- Accessibility: the reduced-motion fallback and a visible pause control.
- What stays still: the headline and the buttons.
A fragment of such a brief for a video background reads like this:
Hero background: <video> autoplay muted loop playsinline, no controls,
src = <clip URL>, poster = its first frame. object-fit: cover;
object-position: 50% 40%. Below 768px, use the 720x1280 portrait cut.
Scrim: linear-gradient(to top, rgba(8,10,14,0.72) 0%, rgba(8,10,14,0) 62%).
Pause toggle bottom right, 40px, aria-label "Pause background video".
prefers-reduced-motion: render the poster only.
Headline and button render static; nothing else on the first screen moves.Paste a clip URL from the backgrounds page where the brief says <clip URL>. For the motion on everything around the hero, see website animation effects, and the case for leaving the ambient layer empty on most pages is in the animated page inventory.
Mistakes that make a moving background feel cheap#
- Two moving layers. A drifting gradient behind a looping video behind animated type is three clocks the eye cannot follow. Let one thing move.
- Motion with no subject. A blob that wanders for no reason reads as a screensaver. A film with a subject reads as a place.
- The desktop file on a phone. A 16:9 film on a 390 by 844 screen with
object-fit: covershows the middle 26% of its width, and the phone still downloads all of it. - No poster. Low Power Mode on iPhone has been reported to block autoplay even for muted video (WebKit bug 216887), and the poster is all those visitors see.
- Type set before the footage was chosen. The brightest frame decides the scrim, so pick the clip first and set the type second.
- Body text over motion. Keep paragraphs off the moving area and let only the headline sit on it.
Where to get a loop that already works#
Thanor's animated backgrounds page is a public library of looping videos made for the first screen of a site: landscapes, abstract light, characters and objects, with Dark and Light filters. You can copy any clip's URL straight into Claude, Cursor, Lovable or Bolt as the hero background, or download the file and host it yourself. The clips without a crown are free with an account, and the crowned ones come with a paid plan.
Every clip on that page is an H.264 MP4 with no audio track, which is exactly the file property WebKit's autoplay rule rewards. Download one, cut a portrait version with the commands in the video background guide, and set the palette around it with the dark mode values if the clip is a night scene. Prompt libraries have started selling loops too: WebThemez ships looping backgrounds next to its prompts.
Open the backgrounds page, filter by Dark, and paste one clip's URL into the brief above. It is the shortest path from a still hero to a moving one that stays inside the budget.
Questions this raises
How do I add an animated background to my website?
Use a muted looping video with the autoplay, muted, loop and playsinline attributes plus a poster image, or a CSS gradient on a pseudo-element that moves with transform. Put it in its own layer behind the content, add a scrim so text keeps at least 4.5:1 contrast, show a still frame under prefers-reduced-motion, and add a pause button to any loop longer than five seconds.
Do animated backgrounds slow down a website?
They can, each in its own way. A video costs download size, so keep a desktop loop near 2.5 MB and a phone cut near 1 MB. A gradient that animates background-position repaints every frame, so move it with transform instead. A WebGL shader costs GPU time per pixel, so cap the pixel ratio at 1.5, hold 30 fps and pause it when it leaves the screen.
What is the best file format for an animated website background?
An MP4 with H.264 video and no audio track plays in every browser and can autoplay on iPhone without a tap. Put an AV1 version first in the source list, with the codecs parameter in its type so browsers that cannot decode it skip it. Keep the loop between 6 and 10 seconds and cut a poster image from its first frame.
Where can I find free animated backgrounds for a website?
Thanor's animated backgrounds page at thanor.ai/animated-backgrounds has looping video backgrounds for hero sections, filtered by Dark, Light, Landscapes, Abstract, Characters and Objects. The clips without a crown are free with an account, and every clip can be copied by URL into Claude, Cursor, Lovable or Bolt, or downloaded and hosted on your own site.
Can I make an animated background with only CSS?
Yes. Layer two or three radial gradients on a pseudo-element, give it a small overscan with a negative inset, and animate its transform over 20 to 30 seconds with an ease-in-out curve, which keeps the work on the compositor. Animating background-position or a registered custom property also works, but both repaint the element on every frame.
Part of
Inspiration, with the prompt
Examples of the looks and effects people search for, from 3D scenes to scroll animation, each one shown working and paired with the specification that builds it.
