CSS的未來:CSS容器查詢

CSS的未來:CSS容器查詢

當我說 “即將到來” 時,我的意思是它還沒有被任何瀏覽器支援,而且規格也沒有最終確定(在寫這篇文章的時候)。也就是說,它在下一個版本的Chrome中是一個標誌,而且我毫不懷疑它很快就會出現在所有 “現代” 瀏覽器中。

什麼是容器查詢

容器查詢類似於媒體查詢,但有一個主要的,也是關鍵的區別。媒體查詢可以查詢整個文件,並根據這些查詢來修改內容。例如,如果文件超過1025px,你可能想把內容移到兩列而不是一列。這將看起來像這樣。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
main.content {
column-count: 1;
column-gap: 2em;
}
@media screen and (min-width: 1025px) {
main.content {
column-count: 2;
}
}
main.content { column-count: 1; column-gap: 2em; } @media screen and (min-width: 1025px) { main.content { column-count: 2; } }
main.content {
column-count: 1;
column-gap: 2em;
}
@media screen and (min-width: 1025px) {
main.content {
column-count: 2;
}
}

容器查詢遵循同樣的原則,但不是查詢整個文件,而是查詢容器。

他們是如何幫助開發者的

想象一下下面的情況;你有一個聯絡卡,你想在你的網站上到處顯示。在一些地方,它在主要內容中,但在其他地方,你決定將它顯示在一個旁側。在同一個媒體查詢中,旁白可能是250px,但主要部分可能是700px,導致卡片需要看起來不同。解決這個問題很簡單,你需要用不同的媒體查詢為卡片設定不同的類,但還有一個更好的方法…… 容器查詢!

如何使用容器查詢

要使用容器查詢,我們必須告訴容器(我們想要應用查詢的元素的父級)我們關心它的尺寸,我們用新的 contain 屬性來做。

  • none –表示該元素以正常方式呈現,沒有應用任何包含規則。
  • strict –表示除樣式外的所有包含規則都應用於該元素。這等同於 contain: size layout paint。
  • content –表示除了size和style之外的所有包含規則都應用於該元素。這等同於包含:layout paint。
  • size –表示該元素可以被調整大小,而不需要檢查其後代的大小。
  • layout –表示元素外部的任何東西都不能影響其內部佈局,反之亦然。
  • style – 表示對於那些可以對不止一個元素和它的子元素產生影響的屬性,這些影響不會轉移到包含元素。請注意,這個值在規範中被標記為 “at-risk”,可能不會在任何地方被支援。
  • paint –表示該元素的後代不會顯示在其邊界之外。如果包含的盒子在螢幕外,瀏覽器不需要畫出其包含的元素–這些元素也必須在螢幕外,因為它們完全被該盒子所包含。如果一個後代超出了包含元素的邊界,那麼這個後裔將被剪裁到包含元素的邊界框中。

目前Mozilla上的文件有點缺失,這很罕見。我們想使用 inline-size 屬性,在Mozilla的其他地方描述為

當我們使用媒體查詢時,大多數時候我們關心的是可用寬度(或 inline-size )。

實踐例子

讓我們以前面的聯絡卡為例,想出一些程式碼來描述它。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<div>
<main>
<div>
<img src="profile.png" alt="profile" />
<div>
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</main>
<aside>
<div>
<img src="profile.png" alt="profile" />
<div>
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</aside>
</div>
<div> <main> <div> <img src="profile.png" alt="profile" /> <div> <h1>Both Names</h1> <p>Some info about me</p> </div> </div> </main> <aside> <div> <img src="profile.png" alt="profile" /> <div> <h1>Both Names</h1> <p>Some info about me</p> </div> </div> </aside> </div>
<div>
<main>
<div>
<img src="profile.png" alt="profile" />
<div>
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</main>
<aside>
<div>
<img src="profile.png" alt="profile" />
<div>
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</aside>
</div>

這個HTML是相當簡單的,但我認為它表達了一個觀點,我們有一個聯絡卡,它在兩個地方,有可能有極大的不同寬度。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* Just some simple css to get it started */
.site {
display: flex;
max-width: 800px;
margin: 0 auto;
}
main.content {
width: 60%;
background: #ccc;
}
aside.side-panel {
width: 40%;
background: tomato;
}
/* Real css starts here */
main.content, aside.side-panel {
contain: layout inline-size;
}
.contact-card {
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
background-color: white;
padding: 2em;
box-sizing: border-box;
border-radius: 2px;
margin: 1em;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.4)
}
.contact-card__profile-image {
height: 50px;
width: 50px;
border-radius: 50px;
border: 1px solid black;
}
.contact-card__profile-information {
margin-left: 0.5em;
}
.contact-card__profile-information h1 {
text-align: center;
margin: 0;
font-size: 1.2em;
}
.contact-card__profile-information p {
text-align: center;
margin: 0.5em 0 0 0;
}
@container (min-width: 450px) {
.contact-card {
width: 300px;
flex-direction: row;
align-items: flex-start;
}
.contact-card__profile-information h1 {
text-align: left;
}
.contact-card__profile-information p {
text-align: left;
}
}
/* Just some simple css to get it started */ .site { display: flex; max-width: 800px; margin: 0 auto; } main.content { width: 60%; background: #ccc; } aside.side-panel { width: 40%; background: tomato; } /* Real css starts here */ main.content, aside.side-panel { contain: layout inline-size; } .contact-card { display: flex; flex-direction: column; align-items: center; width: 200px; background-color: white; padding: 2em; box-sizing: border-box; border-radius: 2px; margin: 1em; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.4) } .contact-card__profile-image { height: 50px; width: 50px; border-radius: 50px; border: 1px solid black; } .contact-card__profile-information { margin-left: 0.5em; } .contact-card__profile-information h1 { text-align: center; margin: 0; font-size: 1.2em; } .contact-card__profile-information p { text-align: center; margin: 0.5em 0 0 0; } @container (min-width: 450px) { .contact-card { width: 300px; flex-direction: row; align-items: flex-start; } .contact-card__profile-information h1 { text-align: left; } .contact-card__profile-information p { text-align: left; } }
/* Just some simple css to get it started */
.site {
display: flex;
max-width: 800px;
margin: 0 auto;
}
main.content {
width: 60%;
background: #ccc;
}
aside.side-panel {
width: 40%;
background: tomato;
}
/* Real css starts here */
main.content, aside.side-panel {
contain: layout inline-size;
}
.contact-card {
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
background-color: white;
padding: 2em;
box-sizing: border-box;
border-radius: 2px;
margin: 1em;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.4)
}
.contact-card__profile-image {
height: 50px;
width: 50px;
border-radius: 50px;
border: 1px solid black;
}
.contact-card__profile-information {
margin-left: 0.5em;
}
.contact-card__profile-information h1 {
text-align: center;
margin: 0;
font-size: 1.2em;
}
.contact-card__profile-information p {
text-align: center;
margin: 0.5em 0 0 0;
}
@container (min-width: 450px) {
.contact-card {
width: 300px;
flex-direction: row;
align-items: flex-start;
}
.contact-card__profile-information h1 {
text-align: left;
}
.contact-card__profile-information p {
text-align: left;
}
}

在這個CSS中,我們為 contact-card 設計了樣式,然後我們有一個容器查詢,當我們傳遞450px的寬度時,它就會改變卡片的樣式。正如你所看到的,它基本上與媒體查詢相同,但它是基於容器的。

下面是程式碼的呈現方式(希望有一天我們能在更多的瀏覽器中試用)。這裡是程式碼,如果在實際工作中,jsfiddle

程式碼的呈現方式

影響規範化

正如我在一開始所說的,規範還沒有最終確定,如果你想看看人們的建議,或者你想自己提出建議,現在還有時間去做。請到git issues板上看一看。

小結

我對此非常興奮,我主要是用React工作,我真的很期待元件能夠根據其父級的大小來改變。

評論留言