GODRICH
#css-animation#button#loader#transition#scroll#dashboard#ui#design-trends

CSS Art Animation — 9 Objects From Pure Shapes

CSS art animation draws everyday objects — a washer, a house, a car — with a few colored boxes and makes them move, not a single image file involved.

Auto-plays · click a tile to jump to its section · all nine in one zip

The order is not by popularity — it follows the materials an object needs before it can move. First, a round window becomes the face of a machine (01), then a roof and chimney raise a whole house (02), wheels and lights bring a car toward you (03), a silhouette crossing letters gives you a character (04), a landscape inside a device adds depth (05), a sun and grids dress the stage (06, 07, 08), and finally a trunk becomes an entire world (09). People looking for css drawing animation examples often expect SVG files or sprites, but every scene here is rectangles, circles, and triangles inside the stage, so there are zero external files. The same through-line continues in CSS scene animation and canvas scene effects.

01Washer drum spin

A front-load washer drawn as a cream body, a round porthole, and a control panel, with water and a sock tumbling inside — a component for appliance landing pages.

Washer drum spin
Open in a new tab

01 · Washer drum spin — Measured area 3.349% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

rotateanimation-play-statescaleY

The drum is one group spinning as a whole

.ws__drum {
  position: absolute; inset: 0;
  animation-name: wsSpin; animation-duration: $duration;
  animation-timing-function: linear; animation-iteration-count: infinite;
}
.ws.is-pause .ws__drum { animation-play-state: paused; }

@keyframes wsSpin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes wsBlink {
  0%, 42% { transform: scaleY(1); }
  46%, 50% { transform: scaleY(.1); }
  54%, 100% { transform: scaleY(1); }
}

Two layers of water plus a sock and a shirt live inside the single .ws__drum group, so the spin is one declaration, and pausing uses animation-play-state instead of removing the animation. The cat sits outside the group and blinks once at the 46% mark of the 2-second loop; press the button and the drum's computed animation-play-state flips from running to paused while the panel LED dims from 1 to 0.25.

02House with window glow

A striped-roof house that turns to dusk with one switch, built for real-estate and home-service onboarding screens.

House with window glow
Open in a new tab

02 · House with window glow — Measured area 22.172% · moving frames 22/23Original by GODRICH · SCSS and React ship in the zip · See the password

repeating-linear-gradientanimation-delaytransition

Day and night share one overlay's opacity

.hs__skynight {
  position: absolute; inset: 0; opacity: 0;
  background: linear-gradient(180deg, $night-top 0%, $night-bottom 100%);
  animation-name: hsCycle; animation-duration: $dur-loop;
  animation-timing-function: ease-in-out; animation-iteration-count: infinite;
}
.hs.is-night .hs__win {
  background: $stage-yellow;
  box-shadow: 0 0 12px rgba(255, 210, 63, .8);
}
@keyframes hsCycle {
  0%, 30% { opacity: 0; }
  52%, 78% { opacity: 1; }
  90%, 100% { opacity: 0; }
}

The night sky, stars, and moon live on one .hs__skynight overlay raised and lowered by opacity alone, so the manual switch runs a transition while the grid preview loops the same keyframes. Flip the switch and the window glass lights up to rgb(255, 210, 63) with a 12px bloom, three smoke puffs rise on 660ms staggered delays, and the roof stripes are not an image but a repeating gradient.

03Approaching car on the road

A car rushing toward you on a dusk road, assembled from a body, headlights, and streaming lane markers — a hero component for automotive and delivery landing pages.

Approaching car on the road
Open in a new tab

03 · Approaching car on the road — Measured area 3.342% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

scalebox-shadowsteps(1, end)

Lane markers flow down a doubled track

.ca__marks {
  position: absolute; left: 50%; top: -72px; width: 8px; height: 144px;
  margin-left: -4px;
  animation-name: caFlow; animation-duration: $duration;
  animation-timing-function: linear; animation-iteration-count: infinite;
}
// spacing is margin-bottom — never gap on an infinite track
.ca__dash {
  display: block; width: 8px; height: 12px; margin-bottom: 12px;
  border-radius: $r-xs; background: rgba(255, 247, 230, .75);
}
@keyframes caFlow {
  from { transform: translateY(0); }
  to { transform: translateY(72px); }
}

Six dashes sit on a 144px track at 24px spacing, and shifting the track 72px — exactly three periods — lands the end pose on the start pose for a seamless loop, while the approach itself is the car group's scale oscillation. Indicators blink with a steps(1, end) cut and the high beam grows the glow to matrix(1.7, 0, 0, 1.7, 0, 0) — though this toggle was invisible at first, for a reason covered in the pitfall section.

04Crow walking across a wordmark

A black crow strutting across candy-gradient letters, made for brand wordmarks and 404 backdrops.

Crow walking across a wordmark
Open in a new tab

04 · Crow walking across a wordmark — Measured area 6.609% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

background-clip: texttranslateXanimation-delay

Clip the background to the letters, swing the legs

.cr__word {
  font-weight: 900; font-size: 76px; line-height: 1; letter-spacing: 2px;
  background: linear-gradient(92deg, $grad-a 0%, $grad-b 48%, $grad-c 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.cr__leg {
  transform-origin: top center;
  animation-name: crStep; animation-duration: 250ms;
  animation-timing-function: linear; animation-iteration-count: infinite;
}
@keyframes crWalk {
  from { transform: translateX(0); }
  to { transform: translateX(400px); }
}

background-clip: text clips the gradient to the letter shapes alone, and the crow is three pieces — a body ellipse, a beak triangle, and stick legs — crossing 400px in 2 seconds while the legs swing 14 degrees out of phase on a 250ms cycle. Click the crow and one feather drops 34px with a 140-degree spin; the three loose feathers on the left sway on 300ms staggered delays.

05Thermostat landscape window

A round smart thermostat whose top window holds a sun rising over mountains and a lake, with mode icons moving the sun, the dial, and the temperature together.

Thermostat landscape window
Open in a new tab

05 · Thermostat landscape window — Measured area 0.536% · moving frames 19/23Original by GODRICH · SCSS and React ship in the zip · See the password

clip-pathrotatetransition

One data attribute drives sun, dial, and readout

.th[data-mode="snow"] .th__sun { transform: translateY(16px); opacity: .45; }
.th[data-mode="sun"] .th__sun { transform: translateY(-8px); opacity: 1; }
.th[data-mode="cloud"] .th__sun { transform: translateY(4px); opacity: .7; }
.th[data-mode="flame"] .th__sun { transform: translateY(0); opacity: .85; }
.th[data-mode="snow"] .th__dial { transform: rotate(0deg); }
.th[data-mode="sun"] .th__dial { transform: rotate(90deg); }
.th__sun { transition: transform $duration $easing, opacity $duration $easing; }

The icon buttons only swap a data-mode attribute and attribute selectors carry every drawing rule, so the script touches nothing but the attribute and the number. Pressing snow while sun mode is active lowers the sun 24px and dims it, spins the dial from 90 degrees back to 0, and swaps the readout from 27° to 18°, with the mountains as two triangles and the lake reflection as a scaleX oscillation.

06Retro sun and perspective grid

A retro scene of a striped sun, palms, and a grid floor streaming toward you, for game and music event landing pages.

Retro sun and perspective grid
Open in a new tab

06 · Retro sun and perspective grid — Measured area 3.71% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

perspectiverotateXtext-shadow

Lay the grid flat, then slide the whole plane

.rt__floor {
  position: absolute; left: 0; right: 0; bottom: 0; height: 62px;
  perspective: 240px; overflow: hidden;
}
.rt__grid {
  position: absolute; left: -60%; top: -100%; width: 220%; height: 200%;
  transform: rotateX(58deg); transform-origin: top center;
  background:
    repeating-linear-gradient(90deg, rgba($grid-pink, .8) 0 2px, transparent 2px 44px),
    repeating-linear-gradient(0deg, rgba($grid-pink, .55) 0 2px, transparent 2px 36px);
  animation-name: rtGridFlow; animation-duration: $duration;
  animation-timing-function: linear; animation-iteration-count: infinite;
}
@keyframes rtGridFlow {
  from { transform: rotateX(58deg) translateY(0); }
  to { transform: rotateX(58deg) translateY(36px); }
}

perspective on the floor plus rotateX(58deg) on the plate pulls the horizontal lines toward a vanishing point, and the flow slides the plate itself by one cell (36px) instead of animating background-position, keeping everything on transform. The sun's slits are an overlay of stage-colored bands on its lower half, the title is two layers of text-shadow neon, and the comet loops in short periodic passes or streaks 96px diagonally when you press the button.

07Gradient pool background

Teal, pink, and violet pools rippling outward in rings on a dark board, swaying slowly — a backdrop for meditation and travel services.

Gradient pool background
Open in a new tab

07 · Gradient pool background — Measured area 5.185% · moving frames 22/23Original by GODRICH · SCSS and React ship in the zip · See the password

radialGradienttransform-originmix-blend-mode

One pool is four ellipses of the same color

<g class="pl__blob pl__blob--teal">
  <ellipse cx="96" cy="84" rx="64" ry="44" fill="url(#plTeal)" opacity=".34"/>
  <ellipse cx="99" cy="81" rx="52" ry="35" fill="url(#plTeal)" opacity=".5" transform="rotate(-8 99 81)"/>
  <ellipse cx="93" cy="86" rx="40" ry="26" fill="url(#plTeal)" opacity=".7" transform="rotate(7 93 86)"/>
  <ellipse cx="98" cy="82" rx="29" ry="18" fill="url(#plTeal)" opacity=".9" transform="rotate(-4 98 82)"/>
  <ellipse cx="96" cy="84" rx="18" ry="11" fill="#29d8c0"/>
</g>

Each pool stacks four ellipses whose centers drift 2-3px apart — exactly why the edges wobble like ink in water — with one bright core on top. SVG groups accept CSS transforms, so transform-box: fill-box plus a 1-second ±8-degree sway animates them; overlapping areas blend with mix-blend-mode: screen, and a click swaps the teal pool to translate(-62px, -58px) while pink takes its place.

08Game-studio hero backdrop

A dark hero where violet light blooms and a swirl band rotates slowly, made for game studio about pages.

Game-studio hero backdrop
Open in a new tab

08 · Game-studio hero backdrop — Measured area 13.677% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

repeating-conic-gradientanimation-directionfilter: blur

The swirl is radial stripes, blurred and masked

.gh__swirl {
  position: absolute; right: -70px; top: -46px; width: 210px; height: 210px;
  border-radius: 50%;
  background: repeating-conic-gradient(rgba(138, 92, 214, .5) 0 14deg, rgba(138, 92, 214, 0) 14deg 42deg);
  -webkit-mask-image: radial-gradient(circle, rgba(0, 0, 0, 1) 0 52%, rgba(0, 0, 0, 0) 74%);
  mask-image: radial-gradient(circle, rgba(0, 0, 0, 1) 0 52%, rgba(0, 0, 0, 0) 74%);
  filter: blur(6px);
  animation-name: ghSwirl; animation-duration: $duration;
  animation-timing-function: ease-in-out; animation-iteration-count: infinite;
  animation-direction: alternate;
}
.gh.is-rev .gh__swirl { animation-direction: alternate-reverse; }

repeating-conic-gradient paints the wedges, blur(6px) melts them, and a radial mask erases the rim, which reads as one slowly rotating vortex. Reversing it is a single class flipping animation-direction to alternate-reverse; the violet bloom breathes on a 2-second cycle, and five specks rise 96px on staggered delays.

09Trunk house

An open vintage trunk holding a mirror, framed pictures, a string of twinkling lights, a sofa, and a lamp — a story screen for travel and living brands.

Trunk house
Open in a new tab

09 · Trunk house — Measured area 0.165% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

animation-delaybox-shadowtransition

Six bulbs on staggered delays, warmth on one overlay

.tk__bulb {
  position: absolute; width: 5px; height: 5px; border-radius: 50%;
  background: $stage-yellow;
  box-shadow: 0 0 6px rgba(255, 210, 63, .9);
  animation-name: tkTwinkle; animation-duration: $dur-loop;
  animation-timing-function: $ease-out; animation-iteration-count: infinite;
  animation-fill-mode: both;
}
@keyframes tkTwinkle {
  0%, 100% { opacity: .35; }
  18% { opacity: 1; }
  46% { opacity: .5; }
}
.tk__warm {
  position: absolute; inset: 0; opacity: 0; pointer-events: none;
  background: radial-gradient(circle at 72% 78%, rgba(255, 210, 63, .3) 0%, rgba(255, 210, 63, 0) 58%);
}

Six bulbs light up in sequence on 250ms delays so the string breathes, and pressing the lamp raises the shade glow and the whole-room warmth overlay to opacity 1 together. The overlay sits after the lamp in the HTML and covers everything, so without pointer-events: none the lamp is unclickable — a line added only after the click actually failed during the build.

Where do simple css animation examples start when objects are drawn from shapes?

The first decision in any css draw circle animation or object piece is what moves: one part of the object (the drum, the legs), the whole object (the approaching car), or the ground behind it (lane markers, grid). Pick that first and the markup almost writes itself — five of these nine animate a part, four swap a state, which is why keyframe animation and transitions could stay separate. The second decision is the stage color: the cream washer body on an ink stage measured intensity 117.7, while the same shapes on a light stage lose contrast, so subject and stage are chosen as a set. When you don't know where to start drawing, lay the biggest mass first (body, roof, car frame) and punch the holes (windows, porthole, headlights) after — that order was fastest across all nine.

Where it breaks — the animation beats the transition

The high beam in 03 did not work at first. The glow carried a pulsing animation (a 2-second scale swing between .92 and 1.08) while the button wired a scale(1.7) transition, yet after clicking, the computed value stayed at the pulse midpoint matrix(0.96283). The CSS cascade puts animation values above transitions, so when both target the same property, the transition never shows no matter how fast it is. The fix is to switch the animation off while the state is on.

.ca.is-beam .ca__glow {
  animation-name: none;
  transform: scale(1.7); opacity: 1;
}

One line of animation-name: none clears the pulse, the scale(1.7) transition appears, and turning the beam off lets the pulse resume. The password for the nine-file archive is <span class="pw-inline" id="pw">5ak22r6m</span>, and it unpacks the vanilla and React versions side by side.

Three variations and accessibility

Name Value to change Feel
duration $dur-loop 2s → 4s drum, smoke, and grid stretch to half speed and the scene calms down
easing $ease-out → $ease-pop the crow's steps and the comet gain one bounce
color stage ink → paper the same shapes move from a night showroom to a white gallery

All three live in the variable block at the top of each style.scss. Under prefers-reduced-motion every item stops its spins, flows, and twinkles, and keeps its most readable still pose — the sock resting on stopped water, the house in daylight, the crow standing on the letters. The start-stop, mode, and lamp buttons keep working in the still state.

FAQ

Do simple css animation examples on objects need image files?

No. All nine here are rounded boxes, clip-path, and gradients, so zero images ship and the zip you download holds only HTML and SCSS (or the two React files). Without images, recoloring turns an object into a different one, which is how the color variation works.

Does an always-spinning drum like this drain the battery?

The motion is limited to transform and opacity, so nothing re-runs layout and the GPU does the drawing. When several of these run on one screen, pausing off-screen objects with animation-play-state is the safe pattern — exactly what the start-stop button here demonstrates.

My drawn object looks squashed on a small screen — what do I fix?

Almost always the stage-versus-object size budget. Each demo is built for 480×300 with a narrow-screen rule keeping it inside 320px, so when you enlarge an object, re-check that rule first. Overflow vertically and the grid cell grows a scrollbar that crops the scene.

Enter the archive password

The password is inside this article. You will find it as you read.