Data di pubblicazione: 28 agosto 2025
La Ricerca Google ha una delle portate più ampie al mondo, pertanto le modifiche alla nostra esperienza utente possono avere un impatto su miliardi di utenti. Sogniamo da tempo un'esperienza web più moderna e simile a un'app. Quando abbiamo iniziato a sviluppare AI Mode, volevamo creare un'esperienza per i nostri utenti in cui la transizione dalla ricerca standard alla modalità AI fosse fluida e connessa. Quando abbiamo sentito parlare delle transizioni di visualizzazione tra documenti, abbiamo capito che si trattava di un abbinamento perfetto per la funzionalità. Questo case study condivide ciò che abbiamo imparato aggiungendo la funzionalità di transizione insieme al lancio di AI Mode.
Le transizioni di visualizzazione tra documenti sono una svolta per quanto riguarda gli strumenti nativi del browser e siamo entusiasti di vedere come plasmeranno il web in futuro.
Modificare lo status quo
La Ricerca Google ha requisiti di supporto del browser rigorosi e conservativi. In genere, l'utilizzo di una funzionalità con disponibilità limitata è stato vietato. Per le transizioni di visualizzazione tra documenti, abbiamo scoperto che un polyfill non era sostenibile, in quanto il principale problema era che non esisteva un'API di acquisizione di pixel e la clonazione dell'intera area visibile presentava gravi problemi di prestazioni. Pertanto, l'utilizzo della funzionalità come miglioramento progressivo è stato il modo migliore per lanciarla insieme alla modalità AI. Poiché le animazioni create dalle transizioni di visualizzazione non influiscono direttamente sulla funzionalità del sito web, per il traffico non supportato vengono semplicemente disattivate, come già avviene nello stato di produzione attuale senza animazioni di transizione.
Abbiamo testato per la prima volta questa strategia di miglioramento progressivo con i nostri utenti interni. In questo modo abbiamo ricevuto un feedback iniziale, che è stato estremamente positivo. I feedback ricevuti hanno anche evidenziato bug, tra cui problemi di prestazioni e interazioni non intenzionali con altre funzionalità, come contesti di stacking sovrapposti.
Abbiamo riscontrato che questa strategia è efficace e credo che la utilizzeremo anche per altre nuove funzionalità del browser in futuro.
Difficoltà riscontrate e risoluzione
Latenza, blocco del rendering e timer watchdog
Nel complesso, la latenza aggiuntiva che deriva dalle transizioni di visualizzazione MPA è trascurabile per il 99% dei casi d'uso, soprattutto su hardware moderni. Tuttavia, la Ricerca Google ha standard molto elevati in termini di latenza e ci impegniamo a creare esperienze utente che funzionino bene su tutti i dispositivi. Per noi, anche pochi millisecondi in più fanno la differenza, quindi abbiamo dovuto investire su come implementare correttamente le transizioni di visualizzazione tra documenti senza compromettere l'esperienza utente.
Il blocco del rendering è una tecnica che si abbina bene alle transizioni di visualizzazione tra documenti. Gli snapshot degli pseudo-elementi del documento in arrivo possono visualizzare solo i contenuti di cui è già stato eseguito il rendering. Pertanto, per animare i contenuti del documento in arrivo, devi eseguire il rendering del blocco finché non viene eseguito il rendering dell'elemento di destinazione che vuoi animare. Per farlo, utilizza l'attributo blocking
in un HTMLLinkElement
. Il blocco del rendering presenta degli svantaggi, in quanto l'attesa di un elemento che si trova verso la fine dell'albero DOM del documento in arrivo può avere un impatto sostanziale sulla latenza. Abbiamo dovuto bilanciare questo compromesso di conseguenza e bloccare il rendering solo sugli elementi che vengono visualizzati molto presto nel ciclo di vita della pagina.
<!-- 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>
In alcuni casi, la precisione dell'elemento su cui bloccare il rendering non è stata sufficiente. Alcuni dispositivi o connessioni vedrebbero comunque una latenza aggiuntiva anche quando il rendering è bloccato su un elemento vicino all'inizio dell'albero DOM. Per gestire questi casi, abbiamo scritto uno script di watchdog timer per rimuovere HTMLLinkElement
dopo un determinato periodo di tempo trascorso per forzare lo sblocco del rendering del documento in arrivo.
Un modo semplice per farlo è il seguente:
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();
}
Limitazioni della copertura
Un altro problema riscontrato è che la regola @ navigation: auto
per le transizioni di visualizzazione tra documenti viene applicata a livello globale all'interno del documento. Non esiste un modo integrato per limitare l'attivazione delle transizioni di visualizzazione tra documenti solo a target di clic specifici. Poiché si tratta di una modifica di grandi dimensioni, non è stato possibile attivare le transizioni di visualizzazione tra documenti nel 100% delle navigazioni nella Ricerca Google. Avevamo bisogno di un modo per attivare o disattivare dinamicamente le transizioni di visualizzazione tra documenti a seconda della funzionalità con cui l'utente interagiva. Nel nostro caso, li abbiamo attivati solo per i cambi di modalità da e verso la modalità AI. A questo scopo, abbiamo aggiornato a livello di programmazione la regola @ di navigazione in base alla destinazione selezionata.
Per attivare/disattivare la regola @ di transizione della visualizzazione:
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;
}
Scatti e animazioni composite
Alcune delle animazioni generate automaticamente sugli pseudo-elementi di transizione della visualizzazione causavano cali di frame sui dispositivi meno recenti, compromettendo l'esperienza pulita e fluida che vogliamo offrire agli utenti. Per migliorare le prestazioni delle animazioni, le abbiamo riscritte utilizzando tecniche di animazione che possono essere eseguite sul compositore. Siamo riusciti a farlo ispezionando i fotogrammi chiave per ottenere le dimensioni degli pseudo-elementi delle istantanee prima e dopo e utilizzando la matematica delle matrici per riscrivere i fotogrammi chiave di conseguenza. Il seguente esempio mostra come recuperare l'animazione per ogni pseudo-elemento di transizione della visualizzazione:
const pseudoElement = `::view-transition-group(${name})`;
const animation = document
.getAnimations()
.find(
(animation) =>
(animation.effect as KeyframeEffect)?.pseudoElement === pseudoElement,
);
Scopri di più sulla scrittura di keyframe di transizione delle visualizzazioni performanti in View Transitions Applied: Dealing with the Snapshot Containing Block.
Altri aspetti a cui prestare attenzione
Uno dei problemi più evidenti è che l'applicazione di tag agli elementi con la proprietà CSS view-transition-name
influisce sul contesto di sovrapposizione (specifica delle transizioni di visualizzazione: sezione 2.1.1). Questa è stata l'origine di più bug che richiedevano la modifica di z-index
degli elementi contenitore.
Un altro aspetto da tenere presente è che potresti non voler aggiungere valori view-transition-name
agli elementi per impostazione predefinita. Molte persone lavorano alla Ricerca Google. Per evitare che i valori view-transition-name
impostati dal nostro team sugli elementi entrino in conflitto con i valori che potrebbero essere utilizzati da persone di altri team, abbiamo utilizzato i tipi di transizione di visualizzazione per aggiungere in modo condizionale la proprietà view-transition-name
solo mentre è attivo un tipo di transizione di visualizzazione specifico.
Esempio di CSS per aggiungere view-transition-name
di the-element
a un elemento solo quando è attivo il tipo di transizione di visualizzazione ai-mode
:
html:active-view-transition-type(ai-mode) {
#target {
view-transition-name: the-element;
}
}
Una volta implementate queste regole CSS per tutte le transizioni di visualizzazione, puoi modificare dinamicamente il tipo di transizione di visualizzazione corrente per qualsiasi navigazione durante gli eventi pageswap
e pagereveal
.
Esempio di aggiornamento del tipo di transizione della visualizzazione a ai-mode
durante l'evento 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'],
);
}
);
In questo modo evitiamo conflitti di denominazione e non eseguiamo lo snapshot non necessario di elementi che non devono essere inclusi nello snapshot durante il passaggio alla modalità AI e il ritorno alla modalità normale.
Infine, eventuali problemi di contesto di sovrapposizione sarebbero presenti solo durante la transizione della visualizzazione. Per risolvere questi problemi, possiamo quindi scegliere come target gli z-index degli pseudo-elementi generati, anziché modificare arbitrariamente gli z-index degli elementi originali al solo scopo di risolvere questo problema quando si utilizzano le transizioni di visualizzazione.
::view-transition-group(the-element) {
z-index: 100;
}
Passaggi successivi
Abbiamo in programma di utilizzare le transizioni di visualizzazione tra documenti per la Ricerca Google, inclusa l'integrazione con l'API Navigation una volta che sarà disponibile su più browser. Continua a seguirci per scoprire i nostri prossimi progetti.