大家好,今年很快地又要過半了。這篇文我想來簡單整理一下近期的 CSS 有什麼相對較新的、我個人覺得很新鮮的語法。
2023-2024 的 CSS 新增了什麼有趣的新語法?
block 的元素可以垂直置中了
約莫今年四月,在 Firefox 完成實作後,所有主瀏覽器已經讓 Block Element 支援垂直置中的功能。例如:
如果在元素高度為固定的情況,以往我傾向用 Flexbox
去做到垂直置中,現在使用 align-content: center
就能做到了;當然,使用 padding
去做上下內距相等值的拓寬也可以。
文件參閱:https://developer.mozilla.org/en-US/docs/Web/CSS/align-content
支援度:https://caniuse.com/mdn-css_properties_align-content_block_context
Subgrid
Grid 是一種網格模組,SubGrid 就是在父層的 Grid 裡面再套一個 Grid,區別在於它會對齊父網格的行和列定義,並繼承父層如 gap 的部分屬性,例如:
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="subgrid-container">
<div class="subgrid-item">Subgrid Item 1</div>
<div class="subgrid-item">Subgrid Item 2</div>
<div class="subgrid-item">Subgrid Item 3</div>
</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
</div>
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
gap: 10px;
border: 2px solid black;
padding: 10px;
}
.item {
border: 1px solid #333;
padding: 20px;
background-color: #f0f0f0;
}
.subgrid-container {
display: grid;
grid-column: 1 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
border: 2px dashed red;
}
.subgrid-item {
border: 1px solid #666;
padding: 10px;
background-color: #e0e0e0;
}
這邊可以看到:
.subgrid-container {
display: grid;
grid-column: 1 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
border: 2px dashed red;
}
我們使用 grid-column: 1 / 4
讓其佔用三個網格。
grid-template-columns
我們採用了 subgrid
,因此它會沿用父層的 grid-template-columns: 1fr 1fr 1fr
及 gap: 10px
。
相較於這篇文章的其他新 CSS 語法,subgrid
適用於更進階和複雜的 CSS 排版,其功能也相當多且強大,有空會再寫一篇文專門介紹。
文件參閱:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Subgrid
支援度:https://caniuse.com/css-subgrid
更靈活的 CSS 變數
如果在開發上是使用原生 CSS 而非例如 CSS Modules 或 Sass 等工具或庫,應該會對這樣的語法不陌生:
:root {
--blue: #6495ED;
}
p {
color: var(--blue);
}
若在樣式生效的 block 內有宣告變數,CSS 會繼承並選用該樣式:
<p>text outside container with color: var(--blue);</p>
<div class="container">
<p>text inside container with color: var(--blue);</p>
</div>
:root {
/* 較淺的藍色*/
--blue: #6495ED;
}
.container p {
/* 較深的藍色*/
--blue: #000080;
}
p {
color: var(--blue);
}
CSS 的 var
可以做到 fallback 避免因為變數不存在導致樣式失效的情況:
h3 {
/* 採用 red */
color: var(--primary-color, red);
}
h4 {
/* 採用 blue*/
--primary-color: blue;
color: var(--primary-color, red);
}
我們可以使用 @property
來定義變數要不要進行繼承。例如:
<div class="parent">
<span>Parent element</span>
<div class="child">
<span>Child element with inheritance disabled for --box-color.</span>
</div>
</div>
@property --box-color {
syntax: "<color>";
/* 因為這裡設定 inherits 為 false, 所以 child 不會繼承 parent 的 --box-color */
inherits: false;
initial-value: gold;
}
.parent {
--box-color: silver;
background-color: var(--box-color);
}
.child {
width: 80%;
height: 40%;
background-color: var(--box-color);
}
在這個例子中,雖然說 .parent
有定義 --box-color
為 silver
,但因為我們運用 @property --box-color
將 inherits
設為 false
,.child
就不會採用 .parent
的 silver
,而是會採用 gold
作為初始值。
文件參閱:https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
支援度:https://caniuse.com/mdn-css_at-rules_property
:has()
:has
是 CSS 的一個 pseudo class,括號中可以傳入一個選擇器作為參數。例如:
<section>
<article>
<h1>Morning Times</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</p>
</article>
<article>
<h1>Morning Times</h1>
<h3>Get ready to be surprised!</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</p>
</article>
</section>
section {
display: flex;
gap: 20px;
}
article {
border: 2px solid #000;
padding: 16px;
}
h1 {
font-size: 48px;
}
h1,
h3,
p {
margin: 0;
}
h1:has(+ h3) {
color: red;
}
+
是接續兄弟選擇器(Next-sibling combinator),若撰寫 a + b { /* ... */ }
,當 a
的下一個兄弟元素為 b
,內部樣式就會生效。
以上述例子來看,
h1:has(+ h3) {
color: red;
}
<article>
<h1>Morning Times</h1>
<h3>Get ready to be surprised!</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</p>
</article>
這段 HTML 就會生效;相對地若 h1
的下一個元素不是 h3
便不會生效。以下範例會讓擁有 h3
子元素的 article
套上黃色背景:
article:has(h3) {
background-color: yellow;
}
文件參閱:https://developer.mozilla.org/zh-CN/docs/Web/CSS/:has
支援度:https://caniuse.com/css-has
:is()
:is
中可以傳入多個選擇器做為參數,簡化共用樣式的冗長寫法。例如:
<ul class="red-text">
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
</ul>
<ol class="red-text">
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
<li>Lorem ipsum dolor sit amet.</li>
</ol>
:is(ol, ul).red-text li {
color: red;
}
:is
會選擇列表中任意一個選擇器可以選擇的元素。這樣講有點抽象,例如:
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) :is(ul, menu, dir) {
color: red;
}
當這樣寫的時候,上一層會選擇下一層每一個參數的選擇器:
也就是類似於這樣的寫法:
/* 等同下列樣式: */
ol ol ul,
ol ul ul,
ol menu ul,
ol dir ul,
ol ol menu,
ol ul menu,
ol menu menu,
ol dir menu,
ol ol dir,
ol ul dir,
ol menu dir,
ol dir dir,
ul ol ul,
ul ul ul,
ul menu ul,
ul dir ul,
ul ol menu,
ul ul menu,
ul menu menu,
ul dir menu,
ul ol dir,
ul ul dir,
ul menu dir,
ul dir dir,
menu ol ul,
menu ul ul,
menu menu ul,
menu dir ul,
menu ol menu,
menu ul menu,
menu menu menu,
menu dir menu,
menu ol dir,
menu ul dir,
menu menu dir,
menu dir dir,
dir ol ul,
dir ul ul,
dir menu ul,
dir dir ul,
dir ol menu,
dir ul menu,
dir menu menu,
dir dir menu,
dir ol dir,
dir ul dir,
dir menu dir,
dir dir dir {
color: red;
}
文件參閱:https://developer.mozilla.org/zh-CN/docs/Web/CSS/:is
支援度:https://caniuse.com/css-matches-pseudo
巢狀
我們已經可以直接在原生的 CSS 檔案中寫巢狀了,這個功能在去年年底已經被所有主流瀏覽器實作出來。
文件參閱:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting
支援度:https://caniuse.com/css-nesting
預處理器/後處理器死了嗎?
不論國內外,我們總能每隔幾天就看到有人在說 “PHP is dead.”, “jQuery is dead” 這類的論述;在 CSS 巢狀正式被實作時,我確實也看過有人在 Medium 發文說 “Stop using CSS preprocessor” 這類的論述,我個人針對不論是前面兩個與 CSS 較無相關或是不要再使用預處理器這類的論述都是比較持反對意見的,原因很簡單:
所有知名的庫、框架、工具甚至程式語言都是為了解決特定問題而誕生的。
CSS 相較幾年前確實有了不少躍進,然而相對於預處理器,像是 Mixin, for 這類很常用的語法目前依然是不支援的;此外當然還有像是 autoprefixer 這類解決跨瀏覽器 CSS 屬性問題的工具。
此外,雖說主流瀏覽器都會在使用者不知道的情況下偷偷更新,但像是 iPhone 有些人會刻意卡在某個版本,Safari 沒有一起更新的狀態下,就會有瀏覽器舊導致部分樣式無法採用的窘境,因此在執行上是否要用新的 CSS 語法,還是要與需求方確認最低需要支援的瀏覽器版號,避免提升後續的維護成本。
以上就是關於今年 CSS 一些新語法我自己整理的心得,若內文有任何錯誤也歡迎指出!
References: