案例研究:Google 如何使用檢視區塊轉場效果,為全新 AI 模式打造連線體驗

發布日期:2025 年 8 月 28 日

Google 搜尋是全球觸及範圍最廣的服務之一,因此使用者體驗的變更可能會影響數十億使用者。我們一直希望網頁體驗能更具現代感,並提供類似應用程式的體驗。在開發 AI 模式時,我們希望為使用者打造流暢的體驗,讓他們從標準搜尋模式切換到 AI 模式時,感覺自然而連貫。我們聽說了跨文件檢視區塊轉場效果,就知道這項功能與檢視區塊轉場效果非常合適。這份個案研究將分享我們在推出 AI 模式時,一併新增轉場功能的心得。

這段影片記錄了在 Google 搜尋上進行搜尋的過程,以及從搜尋結果切換至 AI 模式的步驟。轉場效果使用檢視區塊轉場。

跨文件檢視畫面轉場效果是原生瀏覽器工具的一大突破,我們很期待這項功能在未來如何改變網路。

Browser Support

  • Chrome: 126.
  • Edge: 126.
  • Firefox: not supported.
  • Safari: 18.2.

Source

改變現狀

Google 搜尋對瀏覽器支援有嚴格且保守的要求。一般來說,使用供應情形有限的功能會受到限制。就跨文件檢視區塊轉換而言,我們發現填補程式不可行,主要阻礙是沒有像素快照 API,且複製整個檢視區塊會造成重大效能問題。因此,以漸進式增強功能的形式推出這項功能,是與 AI 模式一同發布的最佳方式。由於檢視區塊轉換建立的動畫不會直接影響網站功能,因此系統會針對不支援的流量停用動畫,這與目前沒有轉換動畫的正式版狀態相同。

我們首先對內部使用者測試這項漸進式強化策略,這讓我們獲得了早期意見回饋,而且絕大多數都是正面的。我們也根據收到的意見回報,修正了效能問題和與其他功能 (例如重疊的堆疊環境) 發生非預期互動等錯誤。

我們發現這項策略相當成功,相信未來會將這項策略套用至其他新的瀏覽器功能。

我們遇到的困難及解決方法

延遲、轉譯封鎖和看門狗計時器

整體而言,對於 99% 的用途,MPA 檢視區塊轉場效果造成的延遲時間微不足道,尤其是在現代硬體上更是如此。不過,Google 搜尋對延遲時間的要求極高,我們致力於打造適用於所有裝置的優質使用者體驗。對我們來說,即使是幾毫秒的延遲也很重要,因此我們必須投入資源,確保正確導入跨文件檢視畫面轉場效果,同時不影響任何人的使用者體驗。

轉譯封鎖技術非常適合搭配跨文件檢視畫面轉換使用。傳入文件的虛擬元素快照只能顯示已轉譯的內容。因此,如要為傳入文件中的內容製作動畫,您需要算繪區塊,直到要製作動畫的目標元素算繪完成為止。如要這麼做,請在 HTMLLinkElement 上使用blocking 屬性。等待傳入文件 DOM 樹狀結構尾端的元素,可能會大幅延遲,因此算是一種缺點。我們必須相應地平衡這項取捨,並只在網頁生命週期極早算繪的元素上算繪區塊。

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

在某些情況下,精確指出要封鎖哪個元素並不足夠。即使元素附近的 DOM 樹狀結構開頭有算繪封鎖,特定裝置或連線仍會出現延遲。為處理這些情況,我們編寫了監控計時器指令碼,在經過一段時間後移除 HTMLLinkElement,強制解除封鎖傳入文件的算繪作業。

簡單做法如下:

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();
}

保固範圍限制

我們遇到的另一個問題是,文件間的檢視區塊轉場效果 at-rule navigation: auto 會在文件內以全域層級發生。目前沒有內建方法可將跨文件檢視區塊轉換的啟用範圍,限制為僅適用於特定點擊目標。由於這項變更規模龐大,我們無法在 Google 搜尋上為所有導覽啟用跨文件檢視畫面轉場效果。我們需要根據使用者互動的功能,動態啟用或停用跨文件檢視區塊轉換。在本例中,我們只針對 AI 模式的切換啟用這些事件。我們是根據點選或輕觸的目標,以程式輔助方式更新導覽 @ 規則,藉此達成上述目的。

如要切換檢視區塊轉換 @ 規則,請按照下列步驟操作:

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;
}

卡頓和合成動畫

檢視區塊轉場效果虛擬元素上自動產生的部分動畫,會導致舊型裝置影格掉格,破壞我們想為使用者提供的流暢體驗。為提升動畫效能,我們使用可在合成器上執行的動畫技術,重新編寫動畫。我們檢查了關鍵影格,取得前後快照虛擬元素的維度,並使用矩陣數學相應地重寫關鍵影格,因此能夠達成這項作業。以下範例說明如何擷取每個檢視區塊轉場效果虛擬元素的動畫:

const pseudoElement = `::view-transition-group(${name})`;
const animation = document
  .getAnimations()
  .find(
    (animation) =>
      (animation.effect as KeyframeEffect)?.pseudoElement === pseudoElement,
  );

如要進一步瞭解如何編寫高效能的檢視區塊轉場效果關鍵影格,請參閱「套用檢視區塊轉場效果:處理含有區塊的快照」。

其他注意事項

其中一個較明顯的問題是,使用 view-transition-name CSS 屬性標記元素會影響堆疊內容 (檢視區塊轉場效果規格:第 2.1.1 節)。這是多個錯誤的來源,需要修改容器元素的 z-index

此外,請注意,您可能不想預設將 view-transition-name 值新增至元素。Google 搜尋團隊有許多成員,為避免團隊在元素上設定的 view-transition-name 值,與其他團隊可能使用的值發生衝突,我們利用檢視區塊轉場效果類型,僅在特定檢視區塊轉場效果類型處於啟用狀態時,有條件地新增 view-transition-name 屬性。

以下是 CSS 範例,只有在 ai-mode 的檢視區塊轉換類型處於啟用狀態時,才會將 view-transition-name 新增至元素:the-element

html:active-view-transition-type(ai-mode) {
  #target {
    view-transition-name: the-element;
  }
}

為所有檢視區塊轉場效果設定這些 CSS 規則後,您就可以在 pageswappagereveal 事件期間,動態變更任何導覽的目前檢視區塊轉場效果類型。

pageswap 事件期間,將檢視區塊轉場效果類型更新為 ai-mode 的範例。

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'],
    );
  }
);

這樣做可避免命名衝突,並防止不必要的元素快照,這些元素不需要在進入和離開 AI 模式時建立快照。

最後,任何堆疊內容問題只會在檢視畫面轉場期間出現。如要解決這些問題,我們可以指定產生的虛擬元素的 z-index,而不是任意修改原始元素的 z-index,只為了在使用檢視區塊轉換時解決這個問題。

::view-transition-group(the-element) {
  z-index: 100;
}

後續步驟

我們計畫在 Google 搜尋中使用跨文件檢視畫面轉場效果,包括與Navigation API 整合 (一旦該 API 支援跨瀏覽器)。敬請期待我們接下來會打造什麼!