@container

Baseline 廣泛可用 *

此特性已經非常成熟,可以在許多裝置和瀏覽器版本上使用。自 2023 年 2 月起,所有主流瀏覽器均已支援。

* 此特性的某些部分可能存在不同級別的支援。

@container CSS @ 規則是一種條件組規則,用於將樣式應用於包含上下文。樣式宣告會根據一個條件進行過濾,如果條件為真,則將樣式應用於該容器。當被查詢的容器尺寸、<style-feature> 或滾動狀態發生變化時,將對該條件進行求值。

container-name 屬性指定一個查詢容器名稱的列表。@container 規則可以使用這些名稱來篩選要定位的查詢容器。可選的、區分大小寫的 <container-name> 可以篩選查詢所針對的查詢容器。

一旦為元素選擇了符合條件的查詢容器,<container-condition> 中的每個容器特性都將針對該查詢容器進行求值。

語法

css
/* With a <size-query> */
@container (width > 400px) {
  h2 {
    font-size: 1.5em;
  }
}

/* With an optional <container-name> */
@container tall (height > 30rem) {
  p {
    line-height: 1.6;
  }
}

/* With a <scroll-state> */
@container scroll-state(scrollable: top) {
  .back-to-top-link {
    visibility: visible;
  }
}

/* With a <container-name> and a <scroll-state> */
@container sticky-heading scroll-state(stuck: top) {
  h2 {
    background: purple;
    color: white;
  }
}

/* Multiple queries in a single condition */
@container (width > 400px) and style(--responsive: true) {
  h2 {
    font-size: 1.5em;
  }
}

/* Condition list */
@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
  h2 {
    font-size: 1.5em;
  }
}

引數

<container-condition>

一個可選的 <container-name> 和一個 <container-query>。如果條件為真,則應用 <stylesheet> 中定義的樣式。

<container-name>

可選。當查詢的求值為真時,樣式將應用到的容器的名稱,指定為 <ident>

<container-query>

一組特性,當容器的尺寸、<style-feature> 或滾動狀態發生變化時,會對查詢容器進行求值。

容器查詢中的邏輯關鍵字

邏輯關鍵字可用於定義容器條件。

  • and 組合兩個或多個條件。
  • or 組合兩個或多個條件。
  • not 對條件取反。每個容器查詢只允許有一個 'not' 條件,並且不能與 andor 關鍵字一起使用。
css
@container (width > 400px) and (height > 400px) {
  /* <stylesheet> */
}

@container (width > 400px) or (height > 400px) {
  /* <stylesheet> */
}

@container not (width < 400px) {
  /* <stylesheet> */
}

命名包含上下文

可以使用 container-name 屬性為包含上下文命名。

css
.post {
  container-name: sidebar;
  container-type: inline-size;
}

其簡寫語法是使用 container,形式為 container: <name> / <type>,例如:

css
.post {
  container: sidebar / inline-size;
}

在容器查詢中,container-name 屬性用於將容器集篩選為具有匹配的查詢容器名稱的容器。

css
@container sidebar (width > 400px) {
  /* <stylesheet> */
}

有關用法和命名限制的詳細資訊,請參見 container-name 頁面。

描述符

<container-condition> 查詢包括尺寸滾動狀態容器描述符。

尺寸容器描述符

<container-condition> 可以包含一個或多個布林尺寸查詢,每個查詢都包含在一組括號內。尺寸查詢包括一個尺寸描述符、一個值,以及(取決於描述符)一個比較運算子。查詢始終以內容盒作為比較物件。包含多個條件的語法與 @media 尺寸特性查詢的語法相同。

css
@container (min-width: 400px) {
  /* … */
}
@container (orientation: landscape) and (width > 400px) {
  /* … */
}
@container (15em <= block-size <= 30em) {
  /* … */
}
aspect-ratio

容器的 aspect-ratio,計算為容器的寬度與高度之比,表示為 <ratio> 值。

block-size

容器的 block-size,表示為 <length> 值。

height

容器的高度,表示為 <length> 值。

inline-size

容器的 inline-size,表示為 <length> 值。

orientation

容器的方向,可以是 landscape(橫向)或 portrait(縱向)。

width

容器的寬度,表示為 <length> 值。

滾動狀態容器描述符

滾動狀態容器描述符在 <container-condition> 中指定,位於 scroll-state 關鍵字後的一組括號內,例如:

css
@container scroll-state(scrollable: top) {
  /* … */
}
@container scroll-state(stuck: inline-end) {
  /* … */
}
@container scroll-state(snapped: both) {
  /* … */
}

滾動狀態容器描述符支援的關鍵字包括物理值和流相對值

scrollable

查詢容器是否可以在給定方向上透過使用者發起的滾動操作(例如拖動捲軸或使用觸控板手勢)進行滾動。換句話說,在給定方向上是否存在可以滾動的溢位內容?有效的 scrollable 值包括以下關鍵字:

none

容器不是滾動容器,或者在任何方向上都不能滾動。

top

容器可以向上邊緣滾動。

容器可以向右邊緣滾動。

bottom

容器可以向下邊緣滾動。

left

容器可以向左邊緣滾動。

x

容器可以水平地向其左邊緣或右邊緣之一或兩者滾動。

y

容器可以垂直地向其上邊緣或下邊緣之一或兩者滾動。

block-start

容器可以向其塊起始邊緣滾動。

block-end

容器可以向其塊結束邊緣滾動。

inline-start

容器可以向其行內起始邊緣滾動。

inline-end

容器可以向其行內結束邊緣滾動。

block

容器可以在其塊方向上向其塊起始或塊結束邊緣之一或兩者滾動。

inline

容器可以在其行內方向上向其行內起始和行內結束邊緣之一或兩者滾動。

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

要評估容器是否可滾動,而不關心方向,請使用 not 運算子和 none 值:

css
@container not scroll-state(scrollable: none) {
  /* … */
}
snapped

查詢容器是否將沿給定軸貼合到滾動貼合容器祖先。有效的 snapped 值包括以下關鍵字:

none

容器不是其祖先滾動容器的滾動貼合目標。當實現 snapped: none 查詢時,作為滾動容器貼合目標的容器將應用 @container 樣式,而非貼合目標應用這些樣式。

x

容器是其祖先滾動容器的水平滾動貼合目標,即它正在水平地貼合其祖先。

y

容器是其祖先滾動容器的垂直滾動貼合目標,即它正在垂直地貼合其祖先。

block

容器是其祖先滾動容器的塊軸滾動貼合目標,即它正在塊方向上貼合其祖先。

inline

容器是其祖先滾動容器的行內軸滾動貼合目標,即它正在行內方向上貼合其祖先。

both

容器同時是其祖先滾動容器的水平和垂直滾動貼合目標,並且在兩個方向上都貼合其祖先。如果容器僅沿水平垂直軸貼合其祖先,則不會匹配。它需要同時滿足兩個條件。

要評估一個具有非 nonesnapped 滾動狀態查詢的容器,它必須是一個具有滾動容器祖先的容器,且該祖先的 scroll-snap-type 值不為 none。即使沒有滾動容器祖先,snapped: none 查詢也會匹配。

當滾動貼合容器上觸發 scrollsnapchanging 事件時,會進行求值。如果測試透過,@container 塊內的規則將應用於該容器的後代元素。

要評估容器是否是貼合目標,而不關心方向,請使用 not 運算子和 none 值:

css
@container not scroll-state(snapped: none) {
  /* … */
}
stuck

查詢一個 position 值為 sticky 的容器是否固定在其滾動容器祖先的邊緣。有效的 stuck 值包括以下關鍵字:

none

容器沒有固定在其容器的任何邊緣。請注意,即使容器沒有設定 position: stickynone 查詢也會匹配。

top

容器固定在其容器的上邊緣。

right

容器固定在其容器的右邊緣。

bottom

容器固定在其容器的下邊緣。

left

容器固定在其容器的左邊緣。

block-start

容器固定在其容器的塊起始邊緣。

block-end

容器固定在其容器的塊結束邊緣。

inline-start

容器固定在其容器的行內起始邊緣。

inline-end

容器固定在其容器的行內結束邊緣。

要評估一個具有非 nonestuck 滾動狀態查詢的容器,它必須設定了 position: sticky,並且位於一個滾動容器內。如果測試透過,@container 塊內的規則將應用於 position: sticky 容器的後代元素。

來自相對軸的兩個值可能同時匹配:

css
@container scroll-state((stuck: top) and (stuck: left)) {
  /* … */
}

但是,來自相對邊緣的兩個值永遠不會同時匹配:

css
@container scroll-state((stuck: left) and (stuck: right)) {
  /* … */
}

要評估容器是否固定,而不關心方向,請使用 not 運算子和 none 值:

css
@container not scroll-state(stuck: none) {
  /* … */
}

正式語法

@container = 
@container <container-condition># { <block-contents> }

<container-condition> =
[ <container-name>? <container-query>? ]!

<container-name> =
<custom-ident>

<container-query> =
not <query-in-parens> |
<query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]

<query-in-parens> =
( <container-query> ) |
( <size-feature> ) |
style( <style-query> ) |
scroll-state( <scroll-state-query> ) |
<general-enclosed>

<style-query> =
not <style-in-parens> |
<style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ] |
<style-feature>

<scroll-state-query> =
not <scroll-state-in-parens> |
<scroll-state-in-parens> [ [ and <scroll-state-in-parens> ]* | [ or <scroll-state-in-parens> ]* ] |
<scroll-state-feature>

<general-enclosed> =
[ <function-token> <any-value>? ) ] |
[ ( <any-value>? ) ]

<style-in-parens> =
( <style-query> ) |
( <style-feature> ) |
<general-enclosed>

<style-feature> =
<style-feature-plain> |
<style-feature-boolean> |
<style-range>

<scroll-state-in-parens> =
( <scroll-state-query> ) |
( <scroll-state-feature> ) |
<general-enclosed>

<style-feature-plain> =
<style-feature-name> : <style-feature-value>

<style-feature-boolean> =
<style-feature-name>

<style-range> =
<style-range-value> <mf-comparison> <style-range-value> |
<style-range-value> <mf-lt> <style-range-value> <mf-lt> <style-range-value> |
<style-range-value> <mf-gt> <style-range-value> <mf-gt> <style-range-value>

<style-range-value> =
<custom-property-name> |
<style-feature-value>

<mf-comparison> =
<mf-lt> |
<mf-gt> |
<mf-eq>

<mf-lt> =
'<' '='?

<mf-gt> =
'>' '='?

<mf-eq> =
'='

示例

根據容器大小設定樣式

考慮以下一個帶有標題和一些文字的卡片元件示例:

html
<div class="post">
  <div class="card">
    <h2>Card title</h2>
    <p>Card content</p>
  </div>
</div>

可以使用 container-type 屬性建立容器上下文,在本例中,在 .post 類上使用 inline-size 值。然後,你可以使用 @container @ 規則將樣式應用於寬度小於 650px 的容器中的 .card 類的元素。

css
/* A container context based on inline size */
.post {
  container-type: inline-size;
}

/* Apply styles if the container is narrower than 650px */
@container (width < 650px) {
  .card {
    width: 50%;
    background-color: lightgray;
    font-size: 1em;
  }
}

建立命名的容器上下文

給定以下 HTML 示例,它是一個帶有標題和一些文字的卡片元件:

html
<div class="post">
  <div class="card">
    <h2>Card title</h2>
    <p>Card content</p>
  </div>
</div>

首先,使用 container-typecontainer-name 屬性建立一個容器上下文。此宣告的簡寫語法在 container 頁面中有描述。

css
.post {
  container-type: inline-size;
  container-name: summary;
}

接下來,透過將名稱新增到容器查詢中來定位該容器:

css
@container summary (width >= 400px) {
  .card {
    font-size: 1.5em;
  }
}

巢狀容器查詢

在一個容器查詢中不能定位多個容器。但可以巢狀容器查詢,效果相同。

如果名為 summary 的容器寬度大於 400px,並且其祖先容器寬度大於 800px,則以下查詢求值為真並應用宣告的樣式:

css
@container summary (width > 400px) {
  @container (width > 800px) {
    /* <stylesheet> */
  }
}

容器樣式查詢

容器查詢還可以評估容器元素的計算樣式。容器樣式查詢是使用一個或多個 style() 函式表示法的 @container 查詢。將樣式特性組合成樣式查詢的布林語法和邏輯與CSS 特性查詢相同。

css
@container style(<style-feature>),
    not style(<style-feature>),
    style(<style-feature>) and style(<style-feature>),
    style(<style-feature>) or style(<style-feature>) {
  /* <stylesheet> */
}

每個 style() 的引數都是一個 <style-feature><style-feature> 是一個有效的 CSS 宣告、一個 CSS 屬性或一個 <custom-property-name>

css
@container style(--themeBackground),
    not style(background-color: red),
    style(color: green) and style(background-color: transparent),
    style(--themeColor: blue) or style(--themeColor: purple) {
  /* <stylesheet> */
}

如果計算值與給定屬性的初始值不同,則沒有值的樣式特性求值為真。

如果作為 style() 函式引數傳遞的 <style-feature> 是一個宣告,那麼當該宣告的值與被查詢容器的該屬性的計算值相同時,樣式查詢求值為真。否則,它解析為假。

以下容器查詢檢查容器元素的 --accent-color計算值是否為 blue

css
@container style(--accent-color: blue) {
  /* <stylesheet> */
}

注意:如果一個自定義屬性的值為 blue,那麼等效的十六進位制程式碼 #0000ff 將不匹配,除非該屬性已使用 @property 定義為顏色,以便瀏覽器可以正確比較計算值。

查詢簡寫屬性的樣式特性,如果其每個普通屬性的計算值都匹配,則為真,否則為假。例如,如果構成該簡寫屬性的所有 12 個普通屬性(border-bottom-style 等)都為真,則 @container style(border: 2px solid red) 將解析為真。

全域性關鍵字 revertrevert-layer<style-feature> 中作為值是無效的,並導致容器樣式查詢為假。

滾動狀態查詢

有關滾動狀態查詢示例的完整演練,請參見使用容器滾動狀態查詢

規範

規範
CSS 條件規則模組第五版
# container-rule

瀏覽器相容性

另見