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:

TransitionsAnimations
TriggerState change (hover, focus)Automatic, on load, or via class
KeyframesTwo (from → to)Two or more
LoopingNoYes (animation-iteration-count)
Direction controlNoYes (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:

PresetEffectGood for
Fade inOpacity 0 → 1Section reveals, image entrances
Slide upTranslate Y up + fadeCard and content entrances
BounceElastic scale overshootAttention-grabbing CTAs
PulseRhythmic scale 1 → 1.05 → 1Notification badges, live indicators
SpinContinuous 360° rotationLoading 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.
  • infinite loops 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.