Brifing

Advanced Interactions with CSS Animation Triggers

How to control scroll and viewport-based animations without JavaScript

CSS-Tricks2 min

1What is animation-trigger?

The CSS animation-trigger property delays animation playback until a specific trigger (scroll, viewport position or DOM event) occurs. For example, you can start a fade-in animation when an element enters the viewport. Traditionally implemented with Intersection Observer API in JavaScript, this functionality is now natively supported in CSS. Simple syntax: animation-trigger: --trigger-name action. Currently experimental in Chrome 115+ and Safari TP.

2Trigger types

Two main trigger types exist: Timeline-based (scroll/view progress) and event-based (click/hover). Scroll-triggered animations start/stop based on element's viewport position. For example, timeline-trigger-source: scroll() tracks scroll position. Event-based triggers respond to user interactions. Currently, timeline-based triggers are more commonly used in production.

3Activation ranges

timeline-trigger-activation-range defines when animation triggers based on viewport position. 'contain' triggers when element is fully visible; 'cover' when partially visible. Example: timeline-trigger: --fade-in scroll() contain/cover starts animation when element fully enters viewport and continues until it partially exits. These ranges are crucial for responsive designs.

4Animation actions

Eight different actions supported: play-forwards, play-backwards, pause, reset etc. For example, animation-trigger: --menu-anim play-once makes menu animation play only once. Separate enter/exit actions (e.g., play-backwards when exiting) enable sophisticated transitions. The 'replay' action resets progress to 0 and plays immediately.

5Trigger scope management

trigger-scope property limits trigger's scope. By default trigger names work globally, but can be scoped to specific DOM subtrees. Prevents conflicts in complex components. Example: .sidebar { trigger-scope: --sidebar-anim; } controls animations only within sidebar. Cascade order determines which trigger applies when duplicates exist.

6Scroll-driven vs scroll-triggered

Scroll-driven animations (continuously synced with scroll position) differ from scroll-triggered (binary state-based). In scroll-driven, animation progresses continuously with scroll; in triggered version, animation starts/stops at specific thresholds. Example: a chart can continuously rotate with scroll (driven) or fade-in at certain point (triggered).

7Parent-child synchronization

Define trigger on parent element and apply animations to children for synchronized animation groups. Example: when .hero section enters viewport, its heading, subheading and buttons can animate sequentially. This pattern is ideal for micro-interactions and provides performance benefits by reducing DOM operations.

8Future and limitations

Animation Triggers spec is currently in Editor's Draft stage. Experimental support in Chrome 115+ and Safari TP. While not as flexible as JavaScript, it covers ~80% of use cases. Key advantages: performance (runs off main thread) and maintainability (stays in CSS). Expected to gain popularity for LCP element entry animations soon. Fallbacks needed for unsupported browsers.

Original article: CSS-Tricks — CSS'de Animasyon Tetikleyicileri ile Gelişmiş Etkileşimler