How to Configure Strict CSS View-Transition-Old and New Animation-Fill-Mode in Google Chrome

In modern web applications orchestrating dynamic page state changes via the View Transition API, a frequent visual regression is the “flash of un-animated content” (FOUC) or sudden flickering right before an animation begins or immediately after it terminates. When an element is assigned a staggered entrance or delayed exit using animation-delay, browsers default to applying keyframe styles only while the active animation interval is executing. Before the delay expires and after the keyframe duration concludes, the pseudo-element falls back to default layout styling, causing distracting flashes on screen.

By enforcing strict animation-fill-mode: both (or forwards / backwards) on ::view-transition-old and ::view-transition-new pseudo-elements, web authors ensure keyframe styles are projected seamlessly before execution and locked at the final frame until the transition pseudo-tree is dismantled in Google Chrome.

Chromium View Transition Fill-Mode Mechanics

The View Transition API generates a pseudo-element tree rooted at the document root:

::view-transition
 └─ ::view-transition-group(article-hero)
     └─ ::view-transition-image-pair(article-hero)
         ├─ ::view-transition-old(article-hero)
         └─ ::view-transition-new(article-hero)

Under default browser behaviour (from Chromium’s internal stylesheet):

  • animation-fill-mode: none;: Keyframe properties only apply during active execution. During an animation-delay, the element displays with full opacity, defeating the purpose of delayed fade-ins.
  • animation-fill-mode: backwards;: The element immediately adopts the from / 0% keyframe styles during any preceding delay period.
  • animation-fill-mode: forwards;: The element retains the to / 100% keyframe styles after execution until the transition completes.
  • animation-fill-mode: both;: Combines both behaviours, ensuring seamless visual continuity across the entire lifecycle.

Configuring Strict Fill Modes in Custom Stylesheets

To eliminate pre-animation flashing on delayed elements, always specify animation-fill-mode: both:

/* Delayed Modal Transition with Strict Fill Mode */
::view-transition-new(dialog-overlay) {
    animation-name: modal-fade-scale;
    animation-duration: 400ms;
    animation-delay: 150ms;
    animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
    animation-fill-mode: both; /* Prevents 150ms flash of full opacity */
}

@keyframes modal-fade-scale {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

Managing Staggered Grids Without Visual Artefacts

When choreographing staggered list reveals using CSS custom properties:

/* Batch Stagger Configuration */
::view-transition-new(*.stagger-item) {
    animation-name: slide-up-reveal;
    animation-duration: 350ms;
    animation-delay: var(--item-delay, 0ms);
    animation-fill-mode: both;
}

@keyframes slide-up-reveal {
    0% {
        opacity: 0;
        transform: translateY(20px);
    }
    100% {
        opacity: 1;
        transform: translateY(0);
    }
}

Inspecting Fill Modes in Chrome DevTools

To audit animation lifecycle states in Google Chrome:

  1. Open DevTools (F12) and bring up the Animations drawer via Ctrl+Shift+P > Show Animations.
  2. Trigger your state transition. Chrome DevTools captures the animation and displays each track.
  3. Scrub the timeline to the first frame (during the delay period).
  4. Select ::view-transition-new in the Elements tree and verify in the Computed panel that opacity: 0 and transform: scale(0.95) are active.

Configuring strict animation-fill-mode: both ensures rock-solid, flicker-free view transitions across Google Chrome.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.