CSS animations and keyframes
CSS animations let you define multi-step motion sequences that play automatically, loop indefinitely, or run on a trigger — without any JavaScript. This article covers how to use the Animations section in the Effects pane, the built-in presets, custom keyframes, and accessibility considerations.
Animations vs. transitions
Transitions and animations both move elements smoothly between states, but they serve different purposes:
| Transitions | Animations | |
|---|---|---|
| Trigger | State change (hover, focus) | Automatic, on load, or via class |
| Keyframes | Two (from → to) | Two or more |
| Looping | No | Yes (animation-iteration-count) |
| Direction control | No | Yes (normal, reverse, alternate) |
Use transitions for interactive state changes. Use animations for entrance effects, loaders, and any motion that plays without user interaction.
The Animations section in the Effects pane
Select an element and open the Effects pane. Scroll to the Animation section. You’ll find:
- Preset selector — a dropdown of built-in named animations
- Duration — how long one cycle takes (seconds)
- Delay — how long to wait before the animation starts
- Timing function — acceleration curve (same options as transitions)
- Iteration count — how many times to play (number or
infinite) - Fill mode — what styles apply before and after the animation runs
- Direction — playback direction
Built-in animation presets
Site Designer ships several ready-to-use animation presets. Apply them from the preset dropdown:
| Preset | Effect | Good for |
|---|---|---|
| Fade in | Opacity 0 → 1 | Section reveals, image entrances |
| Slide up | Translate Y up + fade | Card and content entrances |
| Bounce | Elastic scale overshoot | Attention-grabbing CTAs |
| Pulse | Rhythmic scale 1 → 1.05 → 1 | Notification badges, live indicators |
| Spin | Continuous 360° rotation | Loading spinners, decorative icons |
Key animation properties
fill-mode controls what happens outside the animation’s active duration:
forwards— the element keeps the styles of the last keyframe after the animation ends. Most entrance animations need this so the element doesn’t snap back to invisible.backwards— applies the first keyframe’s styles during the delay period.both— combines both behaviors. Use this as your default for entrance animations.none— default; the element snaps to its pre-animation state when done.
iteration-count controls looping:
- A number (e.g.,
3) plays the animation that many times. infiniteloops the animation forever. Use for spinners, pulse effects, and ambient motion.
direction controls playback:
normal— plays forward every time.reverse— plays backward every time.alternate— plays forward, then backward, then forward. Ideal for breathing/pulse effects.alternate-reverse— plays backward first, then forward.
Creating custom keyframes
The built-in presets cover common needs. For custom motion, click Edit keyframes in the Animations section to open the keyframe editor. You can define values at 0%, 25%, 50%, 75%, and 100% of the animation duration for any animatable property.
Triggering animations on scroll
CSS animations play as soon as the element is parsed — they don’t wait for the element to enter the viewport. For entrance animations that should fire as the user scrolls down the page, Site Designer provides a Scroll Trigger toggle in the Animations section.
When enabled, Site Designer injects a small IntersectionObserver snippet via custom code that adds an .is-visible class to the element when it enters the viewport. The animation is bound to .is-visible rather than the element itself, so it only plays when the element scrolls into view.
If you need more control over the scroll trigger behavior, you can implement a custom observer via Project Settings → Custom Code → Body Scripts.
Accessibility: prefers-reduced-motion
Always wrap looping or large-motion animations in a prefers-reduced-motion query. Site Designer’s default stylesheet includes:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
This means your animations are safe to ship — users who need reduced motion get a static experience, while everyone else gets the full animation.