Transições de elementos de grupo

À medida que os itens são adicionados, removidos ou reorganizados em uma lista, as transições podem ajudar os usuários a manter o contexto. As transições de visualização oferecem uma maneira de fazer a transição entre dois estados de um elemento, atribuindo a ele um view-transition-name exclusivo. Quando vários elementos em uma página compartilham o mesmo comportamento de transição, o view-transition-class permite definir essa lógica uma vez no CSS, em vez de repetir para cada view-transition-name exclusivo. Isso mantém as folhas de estilo fáceis de manter e garante animações consistentes em um grupo de elementos.

Etapas de implementação

  1. Atribuir nomes exclusivos e uma turma compartilhada

    Cada elemento que precisa ser rastreado individualmente durante uma transição precisa ter um view-transition-name exclusivo.

    <!-- 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>
    

    Para aplicar estilos compartilhados, atribua também um view-transition-class.

    .item {
      view-transition-class: list-item;
    }
    
  2. Definir a lógica de transição compartilhada

    Use o pseudoelemento ::view-transition-group() com o seletor de classe para aplicar estilos a todos os membros desse grupo.

    /* 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. Opcional: definir animações de entrada e saída

    Use o seletor :only-child para adicionar transições específicas aos elementos adicionados ou removidos. Os pseudoelementos ::view-transition-new() e ::view-transition-old() são filhos de um pseudoelemento ::view-transition-image-pair(). Portanto, podemos determinar se ele é um elemento adicionado ou removido se for o único filho.

    /* 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. Acionar a transição

    Envolva a atualização do DOM em document.startViewTransition(). O navegador vai capturar o estado antigo, realizar a atualização e, em seguida, animar para o novo estado.

    function updateList(newData) {
      document.startViewTransition(() => {
        // All DOM changes inside this callback will be transitioned
        render(newData);
      });
    }
    
  5. Manter a interatividade de elementos sem transição

As transições de visualização funcionam sobrepondo snapshots dos elementos do DOM e, em seguida, fazendo a transição dos snapshots. Isso significa que, durante a transição, os elementos não são interativos. Se houver elementos interativos que não são transicionados, você pode torná-los interativos desativando os eventos de toque nas transições de visualização.

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

Além disso, por padrão, o elemento :root tem uma transição de visualização chamada root, que permite transições de página inteira padrão. Se não houver mudanças no elemento raiz, essa será uma transição entre dois snapshots idênticos, que não são interativos. Como estamos fazendo a transição apenas de elementos específicos, e não de toda a tela, podemos desativar a transição root.

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

Estratégias de fallback

As transições de visualização são um aprimoramento progressivo. Se o navegador não for compatível com document.startViewTransition, a atualização do DOM ainda vai ocorrer imediatamente, proporcionando uma experiência funcional, mas sem animação.

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

No CSS, os navegadores que não reconhecem view-transition-class ou o seletor de classe ::view-transition-group() simplesmente ignoram essas regras, e nenhuma animação é aplicada.