發布日期:2025 年 8 月 28 日
Google 搜尋是全球觸及範圍最廣的服務之一,因此使用者體驗的變更可能會影響數十億使用者。我們一直希望網頁體驗能更具現代感,並提供類似應用程式的體驗。在開發 AI 模式時,我們希望為使用者打造流暢的體驗,讓他們從標準搜尋模式切換到 AI 模式時,感覺自然而連貫。我們聽說了跨文件檢視區塊轉場效果,就知道這項功能與檢視區塊轉場效果非常合適。這份個案研究將分享我們在推出 AI 模式時,一併新增轉場功能的心得。
跨文件檢視畫面轉場效果是原生瀏覽器工具的一大突破,我們很期待這項功能在未來如何改變網路。
改變現狀
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 規則後,您就可以在 pageswap
和 pagereveal
事件期間,動態變更任何導覽的目前檢視區塊轉場效果類型。
在 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 支援跨瀏覽器)。敬請期待我們接下來會打造什麼!