Intersection Observer 可能是普遍受歡迎的 API 之一,而且適用於所有主要瀏覽器。開發人員已將這項 API 用於各種用途,包括延遲載入圖片和影片、在元素抵達 position: sticky 時傳送通知、觸發 Analytics 事件等等。
最基本的 IntersectionObserver v1 API 如下所示:
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Intersection Observer 第 1 版的可見度難題
透過 Intersection Observer v1 API,您可以瞭解元素捲動至視窗檢視區塊的時機。不過,您無法判斷該元素是否遭到其他網頁內容遮蓋 (稱為「遮蔽」),或元素是否因 CSS (例如 transform、opacity 或 filter) 而經過修改,導致元素無法顯示。
如果是頂層文件中的元素,可以透過 JavaScript 分析 DOM 來判斷這項資訊,例如使用 DocumentOrShadowRoot.elementFromPoint()。反之,如果相關元素位於第三方 iframe 中,則無法取得相同資訊。
報表的重要性
遺憾的是,網路上有惡意行為人。舉例來說,不實的發布商可能會在網站上使用單次點擊出價廣告。他們可能會誘騙使用者點擊這些廣告,以賺取更多收益,至少在廣告聯播網發現他們的計畫之前是如此。這類廣告通常會透過 iframe 放送。
為誤導使用者,發布商可能會使用 CSS 將廣告 iframe 完全設為透明:iframe { opacity: 0; }。然後將這些透明的 iframe 放在吸引人的內容上,例如使用者想點選的可愛貓咪影片。這就是所謂的「點擊劫持」。
您可以在示範的上方部分,查看這類點擊劫持攻擊的實際運作情形。試著「觀看」貓咪影片,並啟動惡作劇模式。即使您在 iframe 透明時 (無意) 點擊廣告,系統仍會將點擊記錄為有效。

Intersection Observer 第 2 版的改善項目
Intersection Observer v2 可以追蹤元素「可見度」,就像人類定義的一樣。如果您在 IntersectionObserver 建構函式中設定選項,產生的 IntersectionObserverEntry 執行個體會包含名為 isVisible 的新布林值欄位。當 isVisible
為 true 時,瀏覽器會確保元素完全不會被其他內容遮蓋,且沒有任何會隱藏或變更顯示效果的視覺效果。如果 isVisible 是 false,瀏覽器就無法做出這項保證。
根據
規格,誤判是允許的:即使元素確實可見且未變更,isVisible 仍可為 false。為了提升效能,瀏覽器會使用較簡單的計算方式 (例如邊界方塊和矩形),不會檢查每個像素的複雜細節 (例如 border-radius)。
但無論如何,我們絕不允許誤報。也就是說,如果元素未完全顯示且未經修改,isVisible 就不會是 true。
套用這些變更
IntersectionObserver 建構函式現在會採用兩個額外的設定屬性:
delay是數字,表示特定目標的觀察器通知之間,以毫秒為單位的最短延遲時間。trackVisibility是布林值,用於指出觀察器是否會追蹤目標顯示設定的變更。
如果 trackVisibility 為 true,delay 必須設為 100 或更高的值 (也就是每 100 毫秒最多一則通知)。由於計算可視度需要耗費大量資源,因此這項預防措施可避免效能降低和電池耗電量增加。負責的開發人員應使用可容許的最大延遲值。
規格會計算可視度。與第 1 版相同,當觀察者的 trackVisibility 屬性為 false 時,目標會視為可見
在第 2 版中,如果符合下列條件,目標就會視為隱藏:
具有有效的轉換矩陣,而非 2D 平移或成比例的 2D 放大。
目標或其所含區塊鏈中的任何元素,有效不透明度小於 1.0。
目標或其所含區塊鏈中的任何元素已套用篩選器。
如果導入作業無法保證目標完全不會被其他網頁內容遮住。
這表示目前的實作方式相當保守,以確保曝光度。舉例來說,套用幾乎無法察覺的灰階濾鏡 (filter: grayscale(0.01%)),或設定最小的透明度 (opacity: 0.99),都會導致元素隱形。
以下程式碼範例說明瞭新版 API 的功能。您可以在示範的第二個部分中,查看點擊追蹤邏輯的運作情形。請嘗試「觀看」小狗影片,啟用「詐騙模式」,將自己轉換成惡意行為者,並瞭解 Intersection Observer v2 如何防止系統追蹤非正當的廣告點擊。Intersection Observer v2 可保護我們。

<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support v2, fallback to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
其他資源
- 交集觀測器工作草案。
- Chrome 平台狀態的 Intersection Observer v2。
特別銘謝
感謝 Simeon Vincent、Yoav Weiss 和 Mathias Bynens 審查,以及 Stefan Zager 審查並在 Chrome 中導入這項功能。