Publié le : 28 août 2025
La recherche Google est l'un des services les plus utilisés au monde. Par conséquent, les modifications apportées à notre expérience utilisateur peuvent avoir un impact sur des milliards d'utilisateurs. Nous rêvons depuis longtemps d'une expérience Web plus moderne et plus proche d'une application. Lorsque nous avons commencé à développer le mode IA, nous voulions créer une expérience pour nos utilisateurs où la transition du mode Recherche standard au mode IA se ferait de manière fluide et connectée. Lorsque nous avons entendu parler des transitions de vue entre documents, nous avons su qu'elles seraient parfaites pour cette fonctionnalité. Cette étude de cas partage ce que nous avons appris en ajoutant la fonctionnalité de transition lors du lancement du mode IA.
Les transitions de vue entre documents sont révolutionnaires en ce qui concerne les outils de navigateur natifs. Nous sommes impatients de voir comment elles façonneront le Web à l'avenir.
Changer le statu quo
La recherche Google est soumise à des exigences strictes et conservatrices concernant la compatibilité des navigateurs. En général, il était impossible d'utiliser une fonctionnalité à disponibilité limitée. Pour les transitions de vue entre documents, nous avons constaté qu'un polyfill n'était pas viable. Le principal obstacle était l'absence d'API de capture d'instantanés de pixels et les problèmes de performances majeurs liés au clonage de l'intégralité de la fenêtre d'affichage. Par conséquent, la meilleure façon de lancer la fonctionnalité en même temps que le mode IA était de l'utiliser comme amélioration progressive. Étant donné que les animations créées par les transitions de vue n'ont pas d'incidence directe sur la fonctionnalité du site Web, elles seraient simplement désactivées pour le trafic non compatible, ce qui correspond déjà à l'état de production actuel sans animations de transition.
Nous avons d'abord testé cette stratégie d'amélioration progressive auprès de nos utilisateurs internes. Nous avons ainsi pu recueillir des commentaires précoces, qui étaient très positifs. Les commentaires reçus ont également permis de détecter des bugs, y compris des problèmes de performances et des interactions inattendues avec d'autres fonctionnalités, comme des contextes de superposition qui se chevauchent.
Nous avons constaté que cette stratégie était efficace et je pense que nous l'appliquerons à d'autres nouvelles fonctionnalités du navigateur à l'avenir.
Difficultés rencontrées et solutions
Latence, blocage du rendu et minuteurs watchdog
Dans l'ensemble, la latence supplémentaire associée aux transitions de vue MPA est négligeable pour 99 % des cas d'utilisation, en particulier sur le matériel moderne. Toutefois, la recherche Google est extrêmement exigeante en termes de latence, et nous nous efforçons de créer des expériences utilisateur qui fonctionnent bien sur tous les appareils. Pour nous, même quelques millisecondes supplémentaires comptent. Nous avons donc dû investir dans la manière d'implémenter correctement les transitions de vue entre documents sans nuire à l'expérience utilisateur.
Le blocage du rendu est une technique qui se marie bien avec les transitions de vue entre documents. Les instantanés de pseudo-éléments du document entrant ne peuvent afficher que le contenu qui a déjà été rendu. Par conséquent, pour animer le contenu du document entrant, vous devez rendre le bloc jusqu'à ce que l'élément cible que vous souhaitez animer ait été rendu. Pour ce faire, utilisez l'attribut blocking
sur un HTMLLinkElement
. Le blocage du rendu présente des inconvénients, car l'attente d'un élément situé vers la fin de l'arborescence DOM du document entrant peut avoir un impact important sur la latence. Nous avons dû trouver le bon équilibre et n'afficher le bloc que sur les éléments qui s'affichent très tôt dans le cycle de vie de la page.
<!-- Link tag in the <head> of the incoming document -->
<link blocking="render" href="#target-id" rel="expect">
<!-- Element you want to animate in the <body> of the incoming document -->
<div id="target-id">
some content
</div>
Dans certains cas, il ne suffisait pas d'être précis sur l'élément sur lequel vous bloquiez le rendu. Certains appareils ou certaines connexions continueraient à constater une latence supplémentaire, même si le rendu était bloqué sur un élément situé au début de l'arborescence DOM. Pour gérer ces cas, nous avons écrit un script de minuteur de surveillance afin de supprimer le HTMLLinkElement
après un certain temps écoulé pour forcer le déblocage du rendu du document entrant.
Voici une méthode simple pour y parvenir :
function unblockRendering() {
const renderBlockingElements = document.querySelectorAll(
'link[blocking=render]',
);
for (const element of renderBlockingElements) {
element.remove();
}
}
const timeToUnblockRendering = t - performance.now();
if (timeToUnblockRendering > 0) {
setTimeout(unblockRendering, timeToUnblockRendering);
} else {
unblockRendering();
}
Limites de couverture
Un autre problème que nous avons rencontré est que la règle @ navigation: auto
de transition de vue inter-documents se produit au niveau global dans le document. Il n'existe aucun moyen intégré de limiter l'activation des transitions de vue entre documents à des cibles de clic spécifiques. Étant donné l'ampleur de ce changement, nous n'avons pas pu activer les transitions de vue entre documents pour 100 % des navigations dans la recherche Google. Nous avions besoin d'un moyen d'activer ou de désactiver dynamiquement les transitions de vue entre documents en fonction de la fonctionnalité avec laquelle l'utilisateur interagissait. Dans notre cas, nous ne les avons activées que pour les changements de mode vers et depuis le mode IA. Pour ce faire, nous avons mis à jour de manière programmatique la règle @navigation en fonction de la cible sur laquelle l'utilisateur a cliqué ou appuyé.
Voici comment activer ou désactiver la règle at-rule de transition de vue :
let viewTransitionAtRule: HTMLElement | undefined;
const DISABLED_VIEW_TRANSITION = '@view-transition{navigation:none;}';
const ENABLED_VIEW_TRANSITION = '@view-transition{navigation:auto;}';
function getVtAtRule(): HTMLElement {
if (!viewTransitionAtRule) {
viewTransitionAtRule = document.createElement('style');
document.head.append(viewTransitionAtRule);
}
return viewTransitionAtRule;
}
function disableVt() {
getVtAtRule().textContent = DISABLED_VIEW_TRANSITION;
}
function enableVt() {
getVtAtRule().textContent = ENABLED_VIEW_TRANSITION;
}
Jank et animations composées
Certaines animations générées automatiquement sur les pseudo-éléments de transition de vue ont entraîné des pertes d'images sur les anciens appareils, ce qui a nui à l'expérience fluide et transparente que nous souhaitons offrir aux utilisateurs. Pour améliorer les performances des animations, nous les avons réécrites à l'aide de techniques d'animation pouvant s'exécuter sur le compositeur. Pour ce faire, nous avons inspecté les images clés afin d'obtenir les dimensions des pseudo-éléments "avant" et "après", puis nous avons utilisé des calculs matriciels pour réécrire les images clés en conséquence. L'exemple suivant montre comment récupérer l'animation pour chaque pseudo-élément de transition de vue :
const pseudoElement = `::view-transition-group(${name})`;
const animation = document
.getAnimations()
.find(
(animation) =>
(animation.effect as KeyframeEffect)?.pseudoElement === pseudoElement,
);
Pour en savoir plus sur l'écriture de keyframes de transition de vue performantes, consultez View Transitions Applied: Dealing with the Snapshot Containing Block.
Autres points à surveiller
L'un des problèmes les plus importants est que le fait de taguer des éléments avec la propriété CSS view-transition-name
a un impact sur le contexte de superposition (spécification des transitions de vue : section 2.1.1). Cela a été la source de plusieurs bugs qui ont nécessité la modification du z-index
des éléments de conteneur.
Il est également important de noter que vous ne souhaiterez peut-être pas ajouter de valeurs view-transition-name
aux éléments par défaut. De nombreuses personnes travaillent sur la recherche Google. Pour éviter que les valeurs view-transition-name
définies par notre équipe sur les éléments entrent en conflit avec celles que pourraient utiliser les membres d'autres équipes, nous avons utilisé des types de transition de vue pour ajouter la propriété view-transition-name
de manière conditionnelle uniquement lorsqu'un type de transition de vue spécifique est actif.
Exemple de CSS pour ajouter le view-transition-name
de the-element
à un élément uniquement lorsque le type de transition de vue ai-mode
est actif :
html:active-view-transition-type(ai-mode) {
#target {
view-transition-name: the-element;
}
}
Une fois ces règles CSS en place pour toutes vos transitions de vue, vous pouvez modifier dynamiquement le type de transition de vue actuel pour toute navigation pendant les événements pageswap
et pagereveal
.
Exemple de mise à jour du type de transition de vue sur ai-mode
lors de l'événement pageswap
.
function updateViewTransitionTypes(
event: ViewTransitionEvent,
types: string[],
): void {
event.viewTransition.types.clear();
for (const type of types) {
event.viewTransition.types.add(type);
}
}
window.addEventListener(
'pageswap',
(e) => {
updateViewTransitionTypes(
e as ViewTransitionEvent,
['ai-mode'],
);
}
);
Cela nous permet d'éviter les conflits de noms et de ne pas créer d'instantanés inutiles d'éléments qui n'ont pas besoin de l'être lors du passage du mode IA à un autre mode et inversement.
Enfin, les problèmes de contexte d'empilement ne se produiraient que pendant la transition de vue. Pour résoudre ces problèmes, nous pouvons ensuite cibler les z-index des pseudo-éléments générés, au lieu de modifier arbitrairement les z-index des éléments d'origine dans le seul but de résoudre ce problème lors de l'utilisation des transitions de vue.
::view-transition-group(the-element) {
z-index: 100;
}
Étape suivante
Nous prévoyons d'utiliser les transitions de vue entre documents pour la recherche Google, y compris l'intégration à l'API Navigation une fois qu'elle sera disponible sur plusieurs navigateurs. Restez à l'écoute pour découvrir ce que nous allons développer ensuite !