The Web Stories animation system brings elements to life with entrance effects, motion, and visual interest. Animations are defined in serializable format and render consistently in both the editor and published stories.
Animation System Architecture
Animations are managed in the packages/animation package with dual rendering:
WAAPI (Web Animations API) - For editor preview
AMP - For published story output
Both share common keyframes to ensure visual parity.
Reference: docs/animations.md:54-58
Animation Provider
The animation system is integrated through the StoryAnimation.Provider:
import { StoryAnimation } from '@googleforcreators/animation' ;
< StoryAnimation.Provider animations = { animations } elements = { elements } >
{ /* Story pages */ }
</ StoryAnimation.Provider >
Reference: packages/story-editor/src/components/canvas/displayLayer.js
Animation Types
Animation Effects
Effects are opinionated, complex animations for common use cases:
export const ANIMATION_EFFECTS = {
DROP: { value: AnimationType . EffectDrop , name: 'Drop' },
FADE_IN: { value: AnimationType . EffectFadeIn , name: 'Fade In' },
FLY_IN: { value: AnimationType . EffectFlyIn , name: 'Fly In' },
PAN: { value: AnimationType . EffectPan , name: 'Pan' },
PULSE: { value: AnimationType . EffectPulse , name: 'Pulse' },
TWIRL_IN: { value: AnimationType . EffectTwirlIn , name: 'Twirl In' },
WHOOSH_IN: { value: AnimationType . EffectWhooshIn , name: 'Whoosh In' },
ZOOM: { value: AnimationType . EffectZoom , name: 'Scale' },
ROTATE_IN: { value: AnimationType . EffectRotateIn , name: 'Rotate In' },
};
Reference: packages/animation/src/constants.ts:58-95
Background Animations
Special animations for background images:
export const BACKGROUND_ANIMATION_EFFECTS = {
ZOOM: { value: AnimationType . EffectBackgroundZoom , name: 'Zoom' },
PAN: { value: AnimationType . EffectBackgroundPan , name: 'Pan' },
PAN_AND_ZOOM: {
value: AnimationType . EffectBackgroundPanAndZoom ,
name: 'Pan and Zoom'
},
};
Reference: packages/animation/src/constants.ts:97-110
Animation Parts
Atomic, configurable animations for advanced use:
export const ANIMATION_PARTS = {
BLINK_ON: { value: AnimationType . BlinkOn , name: 'Blink On' },
BOUNCE: { value: AnimationType . Bounce , name: 'Bounce' },
FADE: { value: AnimationType . Fade , name: 'Fade' },
FLIP: { value: AnimationType . Flip , name: 'Flip' },
FLOAT_ON: { value: AnimationType . FloatOn , name: 'Float On' },
MOVE: { value: AnimationType . Move , name: 'Move' },
PULSE: { value: AnimationType . Pulse , name: 'Pulse' },
SPIN: { value: AnimationType . Spin , name: 'Spin' },
ZOOM: { value: AnimationType . Zoom , name: 'Zoom' },
};
Reference: packages/animation/src/constants.ts:112-149
The editor primarily uses Animation Effects. Animation Parts are available for advanced customization.
Adding Animations
Animation Panel
Add animations through the Design panel:
Select element
Click an element on the canvas to select it.
Open Animation panel
The Animation panel appears in the right sidebar Design section.
Choose effect
Select an animation from the Effect Chooser dropdown.
Adjust settings
Configure direction, duration, and other effect-specific options.
Reference: packages/story-editor/src/components/panels/design/animation/
Effect Chooser Dropdown
< EffectChooserDropdown
value = { animation ?. type }
onChange = { handleAnimationChange }
isBackgroundEffects = { isBackground }
/>
Reference: packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/
Animation Configuration
Serializable Animation Object
Animations are stored as JSON objects:
const animationObject = {
id: 'unique-id' , // Unique identifier
type: 'effect-drop' , // Animation type
targets: [ 'element-123' ], // Target element IDs
duration: 1000 , // Duration in milliseconds
delay: 0 , // Delay before start
// Effect-specific properties:
ease: 'cubic-bezier(0.4, 0.4, 0.0, 1)' ,
panDir: 'leftToRight' ,
};
Reference: docs/animations.md:9-23
Easing Functions
Supported easing curves:
export const BEZIER = {
linear: 'linear' ,
in: 'ease-in' ,
out: 'ease-out' ,
inOut: 'ease-in-out' ,
// Quad
inQuad: 'cubic-bezier(0.55, 0.085, 0.68, 0.53)' ,
outQuad: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)' ,
inOutQuad: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)' ,
// ... more bezier curves
default: 'cubic-bezier(0.4, 0.4, 0.0, 1)' ,
};
Reference: packages/animation/src/constants.ts:27-54
Direction Controls
Many animations support directional input:
< DirectionRadioInput
value = { direction }
onChange = { setDirection }
directions = { availableDirections }
/>
Common directions:
Fly In : Left to Right, Right to Left, Top to Bottom, Bottom to Top
Pan : Same directional options
Rotate In : Clockwise, Counter-clockwise
Reference: packages/story-editor/src/components/panels/design/animation/directionRadioInput.js
Animation Details
Drop Effect
// packages/animation/src/parts/effects/drop.ts
interface DropAnimation {
type : 'effect-drop' ;
duration : number ; // Default: 1600ms
delay : number ; // Default: 0
easing : BezierType ; // Default: 'cubic-bezier(0.4, 0.4, 0.0, 1)'
}
Element drops in from above with bounce effect.
Reference: packages/animation/src/parts/effects/drop.ts
Fade In Effect
// packages/animation/src/parts/effects/fadeIn.ts
interface FadeInAnimation {
type : 'effect-fade-in' ;
duration : number ; // Default: 1000ms
delay : number ;
easing : BezierType ;
}
Element gradually appears with opacity transition.
Reference: packages/animation/src/parts/effects/fadeIn.ts
Fly In Effect
interface FlyInAnimation {
type : 'effect-fly-in' ;
duration : number ; // Default: 1000ms
delay : number ;
flyInDir : 'leftToRight' | 'rightToLeft' | 'topToBottom' | 'bottomToTop' ;
easing : BezierType ;
}
Element enters from the specified direction.
Reference: packages/animation/src/parts/effects/flyIn.tsx
Pan Effect
interface PanAnimation {
type : 'effect-pan' ;
duration : number ;
panDir : 'leftToRight' | 'rightToLeft' | 'topToBottom' | 'bottomToTop' ;
easing : BezierType ;
}
Element moves across the screen in the specified direction.
Reference: packages/animation/src/parts/effects/pan.ts
Rotate In Effect
interface RotateInAnimation {
type : 'effect-rotate-in' ;
duration : number ;
rotateInDir : 'clockwise' | 'counterClockwise' ;
easing : BezierType ;
}
Element rotates as it appears.
Reference: packages/animation/src/parts/effects/rotateIn.tsx
Zoom (Scale) Effect
interface ZoomAnimation {
type : 'effect-zoom' ;
duration : number ;
scaleDirection : 'scaleIn' | 'scaleOut' ;
easing : BezierType ;
}
Element scales in or out.
Reference: packages/animation/src/parts/effects/zoom.tsx
Background Animations
Background images have special animation considerations:
Background Pan
// packages/animation/src/parts/effects/backgroundPan.ts
interface BackgroundPanAnimation {
type : 'effect-background-pan' ;
duration : number ;
panDir : Direction ;
}
Pans background image, accounting for current offset and zoom to prevent panning past borders.
Reference: packages/animation/src/parts/effects/backgroundPan.ts
Background Zoom
// Zoom constraints
export const BG_MIN_SCALE = 100 ;
export const BG_MAX_SCALE = 400 ;
Background zoom is constrained to prevent excessive scaling.
Reference: packages/animation/src/constants.ts:156-157
Animation State Management
Animations are stored in the story state:
const { animations } = useStory (({ state }) => ({
animations: state . currentPage . animations
}));
Reference: docs/animations.md:5
WAAPI Wrapper
Elements are wrapped for Web Animations API:
< StoryAnimation.WAAPIWrapper
target = { element }
animation = { animation }
>
{ children }
</ StoryAnimation.WAAPIWrapper >
Reference: packages/story-editor/src/components/canvas/displayElement.js
AMP Output
For published stories, AMP animations are used:
< StoryAnimation.AMPWrapper
target = { element }
animation = { animation }
>
{ children }
</ StoryAnimation.AMPWrapper >
Reference: packages/output/src/element.js
Animation Timeline
An internal animation timeline tool was removed in PR #7067. For complex multi-element animations, consider using templates with pre-configured animation sequences.
Reference: docs/animations.md:76-84
Single Target Constraint
Animations in the editor target only one element:
“We have changed this spec to only allow an animation to have a single target element. This new spec is manually enforced in the editor code.”
Reference: docs/animations.md:70-74
Preview Animations
Test animations in the editor:
In-Editor Preview
Story Preview
Animations play automatically in the Display Layer as you navigate between pages. The preview uses WAAPI for real-time playback.
Click the Preview button in the header to see the full story experience. This uses AMP animations matching the published output.
Animation Panel Components
Effect Panel
< EffectPanel
selectedElement = { element }
animation = { currentAnimation }
onChange = { updateAnimation }
/>
Reference: packages/story-editor/src/components/panels/design/animation/effectPanel.js
< EffectInput
effectConfig = { config }
value = { effectValue }
onChange = { handleChange }
/>
Reference: packages/story-editor/src/components/panels/design/animation/effectInput.js
Creating Custom Animations
Animation Part Structure
import { createAnimationPart } from '@googleforcreators/animation' ;
const customAnimation = createAnimationPart ({
type: 'my-custom-animation' ,
defaultDuration: 1000 ,
generateKeyframes : ( args ) => {
return [
{ offset: 0 , /* initial state */ },
{ offset: 1 , /* final state */ },
];
},
});
Reference: packages/animation/src/parts/createAnimationPart.ts
Best Practices
Use animations sparingly
Too many animations can overwhelm users. Choose 1-2 key elements per page.
Match animation to content
Use subtle animations for text, more dramatic for hero images.
Consider timing
Animations should complete before users tap to next page (typically under 2 seconds).
Test on devices
Preview animations on mobile devices to ensure smooth performance.
Maintain accessibility
Avoid animations that could trigger vestibular disorders (rapid spinning, flashing).
Excessive or complex animations can impact story performance, especially on lower-end devices.
Debugging Animations
Animation issues can be debugged through:
Browser DevTools - Inspect WAAPI animations in the Animations panel
Preview Mode - Test AMP animations in preview
Console Logging - Animation provider logs warnings for invalid configurations
Next Steps
Templates Use templates with pre-configured animations
Text & Styling Combine animations with text effects
Media Library Animate images and videos