Native CSS animations

CSS transitions and @keyframes animations are recorded automatically — no setup, no adapter.

On this page
  1. Transitions
  2. Keyframe animations
  3. What is compared
  4. Scroll-driven animations
  5. Tips

CSS transitions and CSS animations need no setup. The browser exposes them through document.getAnimations() as CSSTransition and CSSAnimation objects, and MotionPR's agent reads their timing, keyframes and easing directly.

Installnothing
Confignothing
Recordstype: "css-transition" or "css-animation", source: "native", driver: "css"
StatusVerified in Chromium (capture engine browser tests and the demo app)

Interactive engine demo: needs JavaScript.

Transitions

CSS
.nav-panel {
  transform: translateX(100%);
  transition: transform 320ms cubic-bezier(0.16, 1, 0.3, 1);
}
.nav-open .nav-panel {
  transform: translateX(0);
}

This is the demo app's navigation panel (its stylesheet writes the curve as var(--expo-out)).

One record per transitioned property and element, named after the property (css-transition “transform” on nav-panel). transition-delay, transition-duration and transition-timing-function become timing.delay, timing.duration and the effect easing. Shorthands are recorded as the longhands the browser transitions.

Keyframe animations

CSS
@keyframes dialog-in {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.modal-open .dialog {
  animation: dialog-in 420ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

One record per animation name and element (css-animation “dialog-in” on dialog), with every keyframe value. animation-timing-function applies per keyframe segment in CSS, so it is stored in timing.keyframeEasings; when all segments share one easing it is also the record's effective easing and is compared as a curve. animation-iteration-count: infinite is recorded with one iteration sampled.

What is compared

Everything in Motion comparison: duration, delay, easing curve, iterations, direction, fill, keyframe values (colours, clip-path, sizes), sampled trajectories, opacity and size, and added or removed animations. The demo app has five native scenarios; their real results:

ScenarioChange in the candidateReported
navigationduration 320 → 560 ms, easing → ease-in-outtwo warnings per checkpoint, plus the sampled path (info)
modalentrance easing now overshootswarning: easing, max deviation 12%
faqanswer reveal gains a 120 ms delaywarning: Delay 0ms → 120ms (+120ms)
cta-hoverlift −2 px → −6 px with a scale-upinfo: translateY at end: -2px → -6px, scaleX at end: 1 → 1.04
image-revealthe clip-path reveal is removedcritical: Removed: css-animation “wipe-in” on case-image
featuresa new badge animation is addedwarning: Added: css-animation “pop” on feature-badge

Scroll-driven animations

CSS scroll-driven animations (animation-timeline: scroll() or view()) are recorded as metadata: their progress follows scroll position, not time, so they cannot be replayed at chosen times. They appear with timeline: "scroll" or "view" and are correlated with scroll motion as scroll-linked.

Tips

  • Give animated elements a data-motionpr-id so they are matched across versions with high confidence (Animation identification).
  • Pseudo-elements (::before, ::after) are recorded with pseudoElement on the identity.
  • transition: all records each property that actually transitions.