Transizioni di elementi di gruppo

Quando gli elementi vengono aggiunti o rimossi da un elenco o riorganizzati, le transizioni possono aiutare gli utenti a mantenere il contesto. Le transizioni di visualizzazione consentono di passare da uno stato all'altro di un elemento assegnandogli un view-transition-name univoco. Quando più elementi di una pagina condividono lo stesso comportamento di transizione, view-transition-class ti consente di definire questa logica una sola volta nel CSS anziché ripeterla per ogni view-transition-name univoco. In questo modo, i fogli di stile rimangono gestibili e le animazioni sono coerenti in un gruppo di elementi.

Procedura di implementazione

  1. Assegna nomi univoci e un corso condiviso

    Ogni elemento che deve essere monitorato singolarmente durante una transizione deve avere un view-transition-name univoco.

    <!-- Mandatory: Each element must have a unique view-transition-name -->
    <li style="view-transition-name: item-1" class="item">Item 1</li>
    <li style="view-transition-name: item-2" class="item">Item 2</li>
    

    Per applicare gli stili condivisi, assegna anche un view-transition-class.

    .item {
      view-transition-class: list-item;
    }
    
  2. Definisci la logica di transizione condivisa

    Utilizza lo pseudo-elemento ::view-transition-group() con il selettore di classe per applicare gli stili a tutti i membri del gruppo.

    /* Targets any view transition group that has the 'list-item' class */
    ::view-transition-group(.list-item) {
      animation-duration: 0.5s;
      animation-timing-function: ease-in-out;
    }
    
    /* Handle accessibility by respecting motion preferences */
    @media (prefers-reduced-motion: reduce) {
      /* Disable all group transitions, including the default `root` group. */
      ::view-transition-group(*),
      ::view-transition-old(*),
      ::view-transition-new(*) {
        animation: none !important;
      }
    }
    
  3. (Facoltativo) Definisci le animazioni di entrata e uscita

    Utilizza il selettore :only-child per aggiungere transizioni specifiche agli elementi aggiunti o rimossi. Gli pseudo-elementi ::view-transition-new() e ::view-transition-old() sono elementi secondari di uno pseudo-elemento ::view-transition-image-pair(), quindi possiamo determinare se si tratta di un elemento aggiunto o rimosso se è l'unico elemento secondario.

    /* A `::view-transition-new()` element is the only child if it wasn't present before the view transition, so it is an added element. */
    ::view-transition-new(.list-item):only-child {
      animation-name: slide-in;
      /* Specify an animation duration if you want something different than the UA default of 0.5s */
      animation-duration: 1s;
    }
    /* A `::view-transition-old()` element is the only child if it isn't present after the view transition, so it is a removed element. */
    ::view-transition-old(.list-item):only-child {
      animation-name: slide-out;
      /* Specify an animation duration if you want something different than the UA default of 0.5s */
      animation-duration: 1s;
    }
    
    @keyframes slide-in {
      from {
        translate: -100vw 0;
      }
    }
    @keyframes slide-out {
      to {
        translate: -100vw 0;
      }
    }
    
  4. Attiva la transizione

    Aggrega l'aggiornamento del DOM in document.startViewTransition(). Il browser acquisirà lo stato precedente, eseguirà l'aggiornamento e poi animerà il nuovo stato.

    function updateList(newData) {
      document.startViewTransition(() => {
        // All DOM changes inside this callback will be transitioned
        render(newData);
      });
    }
    
  5. Mantieni l'interattività degli elementi non sottoposti a transizione

Le transizioni di visualizzazione funzionano sovrapponendo gli snapshot degli elementi DOM e poi eseguendo la transizione degli snapshot. Ciò significa che durante la transizione gli elementi non sono interattivi. Se sono presenti elementi interattivi che non vengono sottoposti a transizione, puoi renderli interattivi disattivando gli eventi touch sulle transizioni di visualizzazione.

::view-transition {
  /* Non-transitioned elements below the view transitions remain interactive */
  pointer-events: none;
}

Inoltre, per impostazione predefinita, l'elemento :root ha una transizione di visualizzazione denominata root, che attiva le transizioni di pagina intera predefinite. Se non vengono apportate modifiche all'elemento root, si verificherà una transizione tra due istantanee identiche, che non sono interattive. Poiché stiamo eseguendo la transizione solo di elementi specifici e non dell'intera schermata, possiamo disattivare la transizione root.

:root {
  /* Disable the root transition because we are only transitioning specific elements. */
  view-transition-name: none;
}

Strategie di riserva

Le transizioni di visualizzazione sono un potenziamento progressivo. Se il browser non supporta document.startViewTransition, l'aggiornamento del DOM dovrebbe comunque avvenire immediatamente, offrendo un'esperienza funzionale ma non animata.

if (document.startViewTransition) {
  document.startViewTransition(() => updateDOM());
} else {
  // Fallback: Perform the update without animation
  updateDOM();
}

Per CSS, i browser che non riconoscono view-transition-class o il selettore di classe ::view-transition-group() ignoreranno semplicemente queste regole e non verrà applicata alcuna animazione.