捲動狀態容器查詢可讓您根據元素目前的捲動狀態設定樣式,例如元素是否「停滯」(透過黏性定位) 或「貼齊」(透過捲動貼齊)。這樣一來,您就能在輪轉介面或圖片庫中,以視覺方式區分使用中的項目,不必依賴 JavaScript 交集觀察器或捲動事件監聽器。
核心實作
如要醒目顯示貼齊項目,您必須建立捲動貼齊容器、將貼齊目標定義為捲動狀態容器,然後查詢該狀態,為子系設定樣式。
1. 建立捲動貼齊容器
上層容器必須啟用 scroll-snap-type。
<div class="carousel">
<div class="carousel-item">
<div class="card">Product 1 content</div>
</div>
<div class="carousel-item">
<div class="card">Product 2 content</div>
</div>
</div>
.carousel {
display: flex;
overflow-x: auto;
/* MANDATORY: Enable scroll snapping on the container */
scroll-snap-type: x mandatory;
}
2. 將貼齊目標定義為捲動狀態容器
輪轉介面中應追蹤貼齊效果的每個項目,都必須宣告為 scroll-state 容器。
.carousel-item {
/* Define where the item snaps within the container */
scroll-snap-align: center;
/* MANDATORY: Establish this element as a scroll-state query container */
container-type: scroll-state;
}
3. 查詢 snapped 狀態
由於容器查詢會設定子系的樣式,因此您必須將醒目顯示樣式套用至貼齊目標內的元素。由於捲動容器設為在 X 軸上溢位,請使用 scroll-state(snapped: x) 查詢。
必要:請將樣式包裝在 @media (prefers-reduced-motion: no-preference) 中,只向未要求減少動態效果的使用者顯示效果。視用途而定,您可能可以保留部分效果,但在這個例子中,卡片會從白色閃爍到藍色,可能會對部分使用者造成問題,因此我們完全停用這項效果。
/* Specify transition outside of queries so that it is applied regardless of state. */
.card {
transition:
scale 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),
background-color 0.4s,
color 0.4s,
box-shadow 0.4s;
}
/*
Only show the effect for users not requesting reduced motion. Disable completely, including the color change, as it causes a flash that may be problematic.
*/
@media (prefers-reduced-motion: no-preference) {
/* Style the content when its parent .carousel-item is snapped on the x axis */
@container scroll-state(snapped: x) {
.card {
background: #007bff;
color: white;
scale: 1.15;
box-shadow: 0 10px 25px rgba(0, 123, 255, 0.3);
}
}
}
/* MANDATORY Copy-Paste Safety: Disable highlight scaling/flashing for motion sensitive users */
@media (prefers-reduced-motion: reduce) {
.card {
transition: none !important;
scale: 1 !important;
}
}
snapped 描述元可查詢特定軸:x、y、inline、block 或 both。
無障礙設定
AVOID:搭配互動元素使用 scroll-state。
為貼齊項目加上視覺醒目顯示效果可提升使用者體驗,但貼齊項目不會顯示在無障礙樹狀結構中。套用至貼齊項目的視覺主題不應傳達元素處於啟用或聚焦狀態,且鍵盤焦點環應清晰可見,並與 snapped 醒目顯示區別。如果貼齊項目可互動,則必須採用其他標準無障礙做法,確保其無障礙功能。
貼齊是由捲動觸發,不會移動鍵盤焦點。不過,鍵盤焦點可能會導致捲動容器移動,進而變更貼齊項目,而該項目不一定是焦點項目。這可能會造成使用者混淆,因此不建議這麼做。
備用策略
如果瀏覽器不支援捲動狀態查詢,請提供實用的基本體驗,確保所有項目都清晰可辨,即使沒有「啟用中」醒目顯示也一樣。
特徵偵測
您可以使用 @supports,僅為支援的瀏覽器提供強化功能:
@supports (container-type: scroll-state) {
/* Enhancement styles here */
}
JavaScript 備用廣告
如果醒目顯示對使用者體驗至關重要,請使用 IntersectionObserver 判斷貼齊項目。提供內嵌值為負數的 rootMargin,將觀察區域調整為輪轉介面中央的細長部分。舉例來說,如果元素位於輪轉介面中央 2% 的位置,則視為相交,請將 rootMargin 設為 "0px -49%"。
// Optional: detect support and apply a JS-based fallback
if (!CSS.supports('container-type', 'scroll-state')) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// Toggle a class based on intersection
entry.target.classList.toggle('is-snapped', entry.isIntersecting);
});
}, {
root: document.querySelector(".carousel"),
// Carousel item intersects if any part of the carousel item is in the middle 2% of the carousel.
rootMargin: "0px -49%"
});
document.querySelectorAll('.carousel-item').forEach(item => {
observer.observe(item);
});
}