使用容器滾動狀態查詢

容器滾動狀態查詢是一種容器查詢。它不像基於容器大小選擇性地應用樣式到後代元素,而是允許你基於容器的滾動狀態選擇性地應用樣式到後代元素。這可以包括容器是否部分滾動、是否吸附到滾動吸附容器祖先,或者是否透過position: sticky定位並粘滯到滾動容器祖先的邊界。

本文解釋瞭如何使用容器滾動狀態查詢,並提供了每種型別的一個示例。它假設你瞭解容器查詢的基礎知識。如果你是容器查詢的新手,請在繼續之前閱讀CSS 容器查詢

容器滾動狀態查詢的型別

scroll-state() 查詢中,你可以使用以下三個 @container 描述符:

  • scrollable:查詢容器是否可以透過使用者啟動的滾動(例如透過拖動捲軸或使用觸控板手勢)在給定方向上滾動。換句話說,給定方向上是否有任何溢位內容可以滾動到?這對於應用與滾動容器的滾動位置相關的樣式非常有用。例如,你可以在捲軸位於頂部時顯示一個提示,鼓勵人們向下滾動檢視更多內容,並在使用者實際開始滾動時將其隱藏。
  • snapped:查詢容器是否將沿給定軸吸附到滾動吸附容器祖先。這對於在元素吸附到滾動吸附容器時應用樣式非常有用。例如,你可能希望以某種方式突出顯示吸附的元素,或者顯示其以前隱藏的某些內容。
  • stuck:查詢具有 sticky position 值的容器是否粘滯到其滾動容器祖先的邊緣。這對於在 position: sticky 元素粘滯時對其進行不同的樣式設定非常有用——例如,你可以為它們提供不同的配色方案或佈局。

語法概述

要將容器元素建立為滾動狀態查詢容器,請在其上設定 container-type 屬性,並將其值設定為 scroll-state。你也可以選擇為其指定一個 container-name,以便可以使用特定的容器查詢來定位它。

css
.container {
  container-type: scroll-state;
  container-name: my-container;
}

然後,你可以建立一個 @container 塊,該塊指定查詢、如果測試透過則應用於容器子元素的規則,以及可選的要查詢的容器的 container-name。如果你不指定 container-name,則容器查詢將應用於頁面上的所有滾動狀態查詢容器。

在這裡,我們只查詢名為 my-container 的容器,以確定容器是否可以向其頂部邊緣滾動。

css
@container my-container scroll-state(scrollable: top) {
  /* CSS rules go here */
}

注意:為了將滾動狀態查詢與其他容器查詢分開,滾動狀態描述符和值放置在括號內,前面加上 scroll-statescroll-state( ... ))。這些構造看起來像函式,但它們不是。

使用 scrollable 查詢

滾動狀態 scrollable 查詢,寫為 scroll-state(scrollable: value),測試容器的滾動祖先是否可以透過使用者啟動的滾動在給定方向上滾動。如果不能,查詢返回 false。

value 表示你正在測試滾動可用性的方向,例如:

  • top:測試容器是否可以向其頂部邊緣滾動。
  • inline-end:測試容器是否可以向其內聯結束邊緣滾動。
  • y:測試容器是否可以沿其 y 軸的任一或兩個方向滾動。

如果測試透過,則 @container 塊內的規則將應用於匹配滾動容器的後代。

讓我們看一個例子,其中我們有一個充滿內容的滾動容器,以及一個方便的小連結,如果需要可以滾動回頂部。我們將使用 scrollable 查詢,僅當用戶開始向下滾動內容時才顯示該連結。

HTML

在 HTML 中,我們有一個 <article> 元素,其中包含足夠的內容以使文件滾動,前面是一個返回頂部連結

html
<a class="back-to-top" href="#" aria-label="Top of page">↑</a>
<article>
  <h1>Reader with container query-controlled "back-to-top" link</h1>
  <section>
    <header>
      <h2>This first section is interesting</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    </header>

    ...
  </section>

  ...
</article>

為了簡潔起見,我們隱藏了大部分 HTML。

CSS

.back-to-top 連結被賦予 fixedposition 值,放置在視口的右下角,並使用 80px 0translate 值移出視口。當任一值更改時,transition 值將動畫化 translatebackground-color

css
.back-to-top {
  width: 64px;
  height: 64px;
  color: white;
  text-align: center;
  position: fixed;
  bottom: 10px;
  right: 10px;
  translate: 80px 0;
  transition:
    0.4s translate,
    0.2s background-color;
}

此示例中的滾動容器<html> 元素本身,它被指定為滾動狀態查詢容器,其 container-type 值為 scroll-statecontainer-name 並非嚴格必需,但在程式碼新增到具有多個透過不同查詢定位的滾動狀態查詢容器的程式碼庫中時非常有用。

css
html {
  container-type: scroll-state;
  container-name: scroller;
}

接下來,我們定義一個 @container 塊,該塊設定此查詢的目標容器名稱,以及查詢本身——scrollable: top。此查詢僅當 <html> 元素可以向其頂部邊緣滾動時才應用塊內包含的規則——換句話說,如果容器之前已向下滾動。如果是這種情況,則將 translate: 0 0 應用於 .back-to-top 連結,這將使其平滑地回到螢幕上。

css
@container scroller scroll-state(scrollable: top) {
  .back-to-top {
    translate: 0 0;
  }
}

為了簡潔起見,我們隱藏了示例 CSS 的其餘部分。

結果

嘗試向下滾動文件,並注意“返回頂部”連結如何因此出現,由於 transition 而從視口右側平滑動畫。如果你透過啟用連結或手動滾動返回頂部,“返回頂部”連結將平滑地移出螢幕。

使用 snapped 查詢

僅當實現滾動吸附時才相關,滾動狀態snapped查詢(寫為scroll-state(snapped: value))測試容器是否將沿給定軸吸附到滾動吸附容器祖先。如果不是,查詢返回 false。

在這種情況下,value 表示你正在測試元素吸附能力的方向,例如:

  • x:測試容器是否水平吸附到其滾動吸附容器祖先。
  • inline:測試容器是否在內聯方向上吸附到其滾動吸附容器祖先。
  • y:測試容器是否在兩個方向上吸附到其滾動吸附容器祖先。

要評估具有非 none snapped 滾動狀態查詢的容器,它必須是一個具有滾動吸附容器祖先的容器,也就是說,該祖先的 scroll-snap-type 值不是 none。容器查詢 scroll-state(snapped: none) 匹配沒有滾動容器祖先的滾動狀態容器。

評估將在滾動吸附容器上觸發 scrollsnapchanging 事件時進行。

如果測試透過,則 @container 塊內的規則將應用於匹配的滾動吸附目標容器的後代。

在此示例中,我們將檢視一個具有垂直吸附子元素的滾動吸附容器,並使用 snapped 查詢僅在子元素吸附或即將吸附時為其設定樣式。

HTML

HTML 由一個 <main> 元素組成,該元素將成為滾動吸附容器。內部有幾個 <section> 元素,它們將成為吸附目標。每個 <section> 都包含一個包裝器 <div> 和一個 <h2> 標題。包含包裝器的目的是建立一個樣式目標,因為容器查詢允許對容器的後代進行樣式設定,而不是容器本身。

html
<main>
  <section>
    <div class="wrapper">
      <h2>Section 1</h2>
    </div>
  </section>

  ...
</main>

為了簡潔起見,我們隱藏了大部分 HTML。

CSS

我們在 <main> 元素上設定了 scrolloverflow 值和固定的 height,以將其轉換為垂直滾動容器。我們還設定了 y mandatoryscroll-snap-type 值,將 <main> 轉換為滾動吸附容器,吸附目標將沿 y 軸吸附到該容器;mandatory 意味著吸附目標將始終被吸附到。

css
main {
  overflow: scroll;
  scroll-snap-type: y mandatory;
  height: 450px;
  width: 250px;
  border: 3px solid black;
}

透過設定非 nonescroll-snap-align 值,將 <section> 元素指定為吸附目標。center 值表示它們將以其中心點吸附到容器。

css
section {
  font-family: "Helvetica", "Arial", sans-serif;
  width: 150px;
  height: 150px;
  margin: 50px auto;

  scroll-snap-align: center;
}

我們希望能夠查詢 <section> 元素。具體來說,我們希望測試 <section> 元素是否正在吸附到其容器,因此我們透過在其上設定 scroll-statecontainer-type 值,將它們指定為滾動狀態查詢容器。我們還為它們指定了一個 container-name,這並非嚴格必需,但如果我們的程式碼以後變得更復雜,並且我們有多個希望使用不同查詢定位的滾動狀態查詢容器,則會很有用。

css
section {
  container-type: scroll-state;
  container-name: snap-container;
}

接下來,我們定義一個 @container 塊,該塊設定我們在此查詢中定位的容器名稱以及查詢本身——snapped: y。此查詢僅當 <section> 元素垂直吸附到其容器時才應用塊中包含的規則。如果是這種情況,我們將新的 backgroundcolor 應用於 <section> 元素的子 .wrapper <div> 以突出顯示它。

css
@container snap-container scroll-state(snapped: y) {
  .wrapper {
    background: purple;
    color: white;
  }
}

結果

渲染結果如下所示。嘗試上下滾動容器,並注意當 <section> 吸附到其容器時,其樣式如何變化。

使用 stuck 查詢

滾動狀態stuck查詢(寫為scroll-state(stuck: value))測試具有stickyposition值的容器是否粘滯到其滾動容器祖先的邊緣。如果不是,則查詢返回 false。

在這種情況下,value 表示你正在測試的滾動容器邊緣,例如:

  • top:測試容器是否粘滯到其滾動容器祖先的頂部邊緣。
  • block-end:測試容器是否粘滯到其滾動容器祖先的塊結束邊緣。
  • none:測試容器是否未粘滯到其滾動容器祖先的任何邊緣。請注意,即使容器未設定 position: stickynone 查詢也會匹配。

如果查詢返回 true,則 @container 塊內的規則將應用於匹配的 position: sticky 容器的後代。

讓我們看一個例子,其中有一個包含溢位內容的滾動容器,其中的標題設定為 position: sticky,並在滾動到該位置時粘滯到容器的頂部邊緣。我們將使用 stuck 滾動狀態查詢,以便在標題粘滯到頂部邊緣時對其進行不同的樣式設定。

HTML

在 HTML 中,我們有一個 <article> 元素,其中包含足夠的內容以導致文件滾動。它使用幾個 <section> 元素進行結構化,每個元素都包含一個帶有巢狀內容的 <header>

html
<article>
  <h1>Sticky reader with scroll-state container query</h1>
  <section>
    <header>
      <h2>This first section is interesting</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    </header>

    ...
  </section>

  <section>
    <header>
      <h2>This one, not so much</h2>

      <p>Confecta res esset.</p>
    </header>

    ...
  </section>

  ...
</article>

為了簡潔起見,我們隱藏了大部分 HTML。

CSS

每個 <header> 都具有 stickyposition 值和 0top 值,這使得它們粘滯到滾動容器的頂部邊緣。為了測試 <header> 元素是否粘滯到容器頂部邊緣,它們被指定為滾動狀態查詢容器,其 container-type 值為 scroll-statecontainer-name 並非嚴格必需,但如果此程式碼新增到具有多個透過不同查詢定位的滾動狀態查詢容器的程式碼庫中,則會很有用。

css
header {
  background: white;
  position: sticky;
  top: 0;
  container-type: scroll-state;
  container-name: sticky-heading;
}

我們還為 <header> 元素中的 <h2><p> 元素提供了一些基本樣式,以及一個 transition 值,以便當它們的 background 值更改時,它們會平滑地動畫。

css
h2,
header p {
  margin: 0;
  transition: 0.4s background;
}

h2 {
  padding: 20px 5px;
  margin-bottom: 10px;
}

header p {
  font-style: italic;
  padding: 10px 5px;
}

接下來,我們定義一個 @container 塊,該塊設定我們在此查詢中定位的容器名稱以及查詢本身——stuck: top。此查詢僅當 <header> 元素粘滯到其滾動容器的頂部時才應用塊中包含的規則。在這種情況下,不同的 backgroundbox-shadow 將應用於包含的 <h2><p>

css
@container sticky-heading scroll-state(stuck: top) {
  h2,
  p {
    background: #cccccc;
    box-shadow: 0 5px 2px #00000077;
  }
}

為了簡潔起見,我們隱藏了 CSS 的其餘部分。

結果

嘗試上下滾動文件,並注意當 <h2><p> 元素粘滯到其容器頂部邊緣時,它們如何轉換為新的配色方案。

另見