CSS scroll-state()

與容器查詢類似,但適用於卡住、固定和溢出的查詢。

發布日期:2025 年 1 月 15 日

Chrome 133 引進捲動狀態容器查詢,以此建構容器查詢。瀏覽器管理的固定位置、捲動對齊點和可捲動元素狀態,現在可透過 CSS 查詢及調整。

總覽

在捲動狀態查詢之前,您必須使用 JavaScript 瞭解元素是否卡住、固定或可捲動。標準版現在提供效能更佳的方法,可用來瞭解這項資訊並做出相應調整。我們也推出了新的動畫觸發方式,讓您可以透過 CSS 觸發捲動動畫。

以下簡要說明 Chrome 133 提供的狀態查詢:

卡住狀態
當元素卡在邊緣時,觸發樣式變更。
固定狀態
當元素在軸線上對齊時,觸發樣式變更。
可捲動狀態
在元素溢出時觸發樣式變更。

好消息是,您從容器查詢中學到的所有知識,都將有助於您使用捲動狀態查詢。

捲動驅動動畫和捲動狀態容器查詢之間也有未知的領域,我們需要嘗試使用時間和情境,找出捲動驅動動畫或捲動觸發捲動狀態動畫的最佳方式。以下影片和示範說明瞭這個問題:固定觸發動畫與捲動驅動動畫的比較。

(左) 捲動狀態 (scroll-state()) 觸發的動畫,(右) 捲動驅動動畫
https://codepen.io/web-dot-dev/pen/emOrBaV

第一個捲動狀態查詢

第一步是使用 container-type 屬性的新值定義容器。如同容器查詢,您要查詢的元素是您提供 container-type 的元素,以及選用的 container-name。使用捲動狀態查詢時,您可以為已對齊、卡住或溢出的元素提供 container-type: scroll-state

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;
}

第二步是選取會回應狀態的容器子項,因為容器查詢中,這個元素不能包含 container-type

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    @container scroll-state(stuck: top) {
      background: Highlight;
      color: HighlightText;
    }
  }
}

第三步:試用這項功能。以下 CSS 範例會在 .stuck-top 元素停留在 0 頂端時,將背景設為紅色。只要在已編寫的 CSS 中加入幾行程式碼,以及一個用於代理瀏覽器狀態的額外容器元素,元件就能更聰明地處理周遭環境。

https://codepen.io/web-dot-dev/pen/ByBxpwR

漸進式增強

@supports at-rule 和巢狀結構可讓您只需新增幾行程式碼,即可新增漸進式增強或條件式功能用法:

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  @supports (container-type: scroll-state) {
    > nav {
      @container scroll-state(stuck: top) {
        background: Highlight;
        color: HighlightText;
      }
    }
  }
}

此外,如果您使用捲動狀態查詢來為網頁周圍的元素製作動畫,請務必在動作周圍使用 @media (prefers-reduced-motion: no-preference) {}

應用實例

停滯

或許這個部分應該稱為「棘手情況」?這是一小組黏性狀態用途,以及需要建構的額外構想。

@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}

完整語法清單

在卡住時加入陰影

卡住的查詢最常見的用途之一,就是在導覽列卡住時新增 box-shadow,讓導覽列浮在疊加的內容上方。

https://codepen.io/web-dot-dev/pen/GgKdryj
.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    transition: box-shadow .3s ease;

    @container scroll-state(stuck: top) {
      box-shadow: var(--shadow-5);
    }
  }
}

啟用目前的卡住標頭

另一個常見的 UI 意見回饋情境是強調目前卡住的元素。在以字母排序的頻道清單中,這項功能可以提供實用且有助於提升使用體驗的功能。

https://codepen.io/web-dot-dev/pen/pvzVRaK
.sticky-slide {
  dt {
    container-type: scroll-state;
    position: sticky;
    inset-block-start: 0;
    inset-inline: 0;

    > header {
      transition: 
        background .3s ease,
        box-shadow .5s ease;

      @container scroll-state(stuck: top) {
        background: hsl(265 100% 27%);
        box-shadow: 0 5px 5px #0003;
      }
    }
  }
}

以下是另一種變化版本,其中標題會顯示在清單項目旁邊。無限可能!

https://codepen.io/web-dot-dev/pen/azoGpGg

意見交流

以下列出一些黏滯式示範,或許能激發您運用捲動狀態查詢為示範增添一點趣味,或移除 JavaScript。建議您嘗試建構自己喜歡的內容,這樣有助於您記住語法和概念 😏?。

比對成功

透過固定狀態查詢,我們可以移除 JavaScript 和 Snap 事件的部分責任,並將處理工作移至 CSS。

@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}

完整語法清單

提醒您,如果您略過「第一個捲動狀態查詢」一節,請注意,用於貼齊查詢的容器是含有 scroll-snap-align 的元素,而可調整的元素必須是該元素的子項。也就是說,您需要設定三個元素:

a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
    ⤷ a child of the snap target that can query the container for snap state

視覺上強化已固定的項目

在中心固定捲軸中,常見的做法是醒目顯示或突顯中心固定項目。在這個推薦評價範例中,我們使用了 not 關鍵字,因此所有未固定的推薦評價都會顯示低不透明度,而固定的推薦評價則會維持自然的呈現狀態。

https://codepen.io/web-dot-dev/pen/NPKMdBX
.demo {
  overflow: auto hidden;
  scroll-snap-type: x mandatory;

  > article {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      > * {
        transition: opacity .5s ease;

        @container not scroll-state(snapped: x) {
          opacity: .25;
        }
      }
    }
  }
}

顯示已固定項目的標題

這是一個很好的範例,說明如何透過捲動狀態查詢啟用捲動觸發動畫。這也是在 CSS 中尊重減少動畫效果的價值所在。

https://codepen.io/web-dot-dev/pen/XJrqpBG
.demo {
  overflow-x: auto;
  scroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  > .card {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      @media (prefers-reduced-motion: no-preference) {
        figcaption {
          transform: translateY(100%);

          @container scroll-state(snapped: x) {
            transform: translateY(0);
          }
        }
      }
    }
  }
}

在投影片元素中加入動畫

在演講時,動畫投影片或簡報元素是很常見的做法。過去,為此編寫交集觀察器相當麻煩,因為這麼做只會在投影片上設定一個類別。我們現在不需要任何 JavaScript。

https://codepen.io/web-dot-dev/pen/dPbeNqY
html {
  scroll-snap-type: y mandatory;
}

section {
  container-type: scroll-state;
  scroll-snap-align: start;
  scroll-snap-stop: always;

  @supports (container-type: scroll-state) {
    @media (prefers-reduced-motion: no-preference) {
      > h1 {
        transition: opacity .5s ease, transform .5s var(--ease-spring-3);
        transition-delay: .5s;
        opacity: 0;
        transform: scale(1.25);

        @container scroll-state(snapped: block) {
          opacity: 1;
          transform: scale(1);
        }
      }
    }
  }
}

您可能會發現,所有已固定的 CSS 狀態查詢都會像 scrollsnapchanging 一樣運作,而非 scrollsnapchange。這樣一來,您就能盡早提供固定元素的視覺回饋。如果太過積極,建議您改用 JavaScript 事件。

可捲動

當捲動區域可實際捲動時,捲動狀態查詢會非常實用,可顯示視覺提示。在推出捲動狀態查詢之前,這項資訊很難掌握

@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}

完整語法清單

使用陰影表示捲動

Lea Verou 曾經介紹過一項 CSS 技巧,使用 background-attachment: local 就能達到類似的效果,也可以透過捲動驅動動畫實現這項效果。每種技術都有取捨,我們需要探索每種技術最適合的使用時機和地點。

以下範例使用單一橫跨捲動區的黏滯元素。當上下兩個漸層都套用內容相關捲動狀態查詢 @container scroll-state(scrollable: top) 時,頂端漸層和底部漸層的透明度會以 @property 進行動畫效果:@container scroll-state(scrollable: top)

請注意,這是第一個同時具備 sizescroll-state 容器的容器。

https://codepen.io/web-dot-dev/pen/OPLZWBj
.scroll-container {
  container-type: scroll-state size;
  overflow: auto;

  &::after {
    content: " ";

    background: var(--_shadow-top), var(--_shadow-bottom);
    transition: 
      --_scroll-shadow-color-1-opacity .5s ease,
      --_scroll-shadow-color-2-opacity .5s ease;

    @container scroll-state(scrollable: top) {
      --_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
    }

    @container scroll-state(scrollable: bottom) {
      --_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
    }
  }
}

箭頭提示

有時顯示箭頭有助於使用者發現某個區域可捲動。這些元素通常會指向捲動方向,並在不再需要時消失。您可以使用下列程式碼執行這項操作。

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
}

@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
  rotate: .5turn;
}

返回頁首

另一個常見的捲動狀態互動是「捲動至頂端」便利按鈕。下列程式碼會在沒有向上捲動的情況下,讓「捲動至頂端」按鈕消失。

這個解決方案有點反向,但可讓您減少 CSS 的用量。按鈕的自然停留位置是在檢視畫面中,因此您需要在沒有向上捲動的情況下,指示按鈕隱藏。

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container not scroll-state(scrollable: top) {
  translate: 0 calc(100% + 10px);
}

持續研究

如需更多資訊,請參考以下幾項資源,從規格詳細資料到其他相關文章都有: