重磅!2022年CSS新增的十個實用功能
2022 年 CSS 新增了很多特性,例如容器查詢、父選擇器、子網格、級聯層、新視口單位等,多項期待已久的功能已集成到常青瀏覽器(自動升級到最新版本的瀏覽器,包括 Chrome、Edge、Firefox 和 Safari)中。下面就來看看 2022 年 CSS 新增的 10 個實用功能吧!
1. 顏色相關
下面來看看和 CSS 顏色相關的一些更新。CSS 工作組有兩個新規范將改變我們在 Web 上使用顏色的方式:CSS Color Module Level 4(候選推薦)和 CSS Color Module Level 5(工作草案)。兩者仍處于實驗階段,截至 2022 年 12 月,只有 Safari 已實現。
(1)新顏色函數語法
CSS Color Module Level 4 引入了顏色函數的新語法,例如rgb()和hsl()。新語法省略了逗號,依靠空格來分隔顏色空間的每個通道。它還支持可選的 alpha 參數,從而不再需要額外的顏色函數,例如rgba()和hsla()。逗號分隔的形式現在被規范稱為“遺留語法”。
(2)新色彩空間
新的顏色規范為網絡添加了大量新的顏色空間:
- HWB:色調、白度、黑度
- LCH:亮度、色度、色調
- CIE L * a * b*
- Oklab
- Oklch
- Display P3
這只是新增的顏色空間的一部分,其中一些色彩空間,比如 Display P3,提供了比 sRGB 空間更寬的色域,這意味著我們將可以使用更多顏色,并且這些顏色將比一直使用的顏色更鮮艷。
(3)相對顏色語法
CSS Color Module Level 5 通過引入相對顏色語法進一步增強了顏色函數。。此語法可以基于另一種顏色定義新顏色。可以通過首先使用 from 關鍵字定義原色,然后像往常一樣在顏色函數中指定新顏色的通道來使用它。
當提供原始顏色時,可以訪問“通道關鍵字”,允許引用顏色空間中的每個通道。關鍵字根據使用的顏色函數而變化。對于 rgb(),有 r、g 和 b 通道關鍵字;對于 oklch(),將擁有 l、c 和 h 關鍵字。對于每個顏色函數,還有一個 alpha 通道關鍵字,它是原始顏色的 alpha 通道。
可以在 calc() 表達式中使用這些通道關鍵字來修改原始顏色:
除此之外,還可以跨顏色空間定義相對顏色。當使用一個空間中最初定義的顏色并使用不同的顏色空間定義新顏色時,瀏覽器將首先將原始顏色轉換為新的顏色空間。
下面使用 Oklch 通過將色調旋轉 120°(? 圈)來定義基于 sRGB 中定義的原色的二次色:
(4)color-mix()
CSS Color Module Level 5 規范還引入了一個 color-mix() 函數,允許在不同的顏色空間中混合顏色。
上面代碼中,會產生 50-50 的紫色和紫紅色混合。
2. 全新動態視口單位
新增的 CSS 視口單元用于處理帶有動態工具欄的移動視口。
要想調整與視口一樣大的尺寸,可以使用現有的視口單位 vw 和 vh:
- vw:視口大小寬度的 1%;
- vh:視口大小高度的 1%;
下面元素的寬度為 100vw,高度為 100vh,它將完全覆蓋整個視口:
除了 vh 和 vw,還有:
- vmin:vw或vh中的較小者。
- vmax:vw或vh中的較大者。
這些單位在瀏覽器中都得到了很好的支持。雖然這些單位在桌面瀏覽器上運行良好,但在移動瀏覽器上就會存在一些問題,視口大小受動態工具欄存在與否的影響。這些是用戶界面,例如地址欄和標簽欄等。盡管視口大小可以更改,但 vw 和 vh 大小不會。因此,尺寸為 100vh 高的元素會從視口中溢出。
當向下滾動時,這些動態工具欄將縮回。在這種狀態下,尺寸為 100vh 高的元素將覆蓋整個視口。
為了解決這個問題,CSS 工作組規定了視口的各種狀態:
- 大視口:視口大小假設任何動態擴展和縮回的 UA 接口被縮回。
- 小視口:視口大小假設任何動態擴展和縮回的 UA 接口都可以擴展。
新視口也有指定的單位:
- 大視口的單位帶有 lv 前綴,單位為 lvw、lvh、lvi、lvb、lvmin 和 lvmax。
- 小視口的單位帶有 sv 前綴,單位是 svw、svh、svi、svb、svmin 和 svmax。
除非調整視口本身的大小,否則這些視口百分比單位的大小是固定的。
除了大視口和小視口之外,還有一個動態視口,動態考慮了瀏覽器 UI:
- 當動態工具欄展開時,動態視口等于小視口的大小。
- 當動態工具欄縮回時,動態視口等于大視口的大小。
它的單位帶有 dv 前綴:dvw、dvh、dvi、dvb、dvmin 和 dvmax。它們的尺寸在對應的 lv* 和 sv* 之間。
瀏覽器對這些單位的支持情況如下:
參考:https://web.dev/viewport-units/
3.@container:容器查詢
CSS 容器查詢是一種超越與視口相關的媒體查詢的方法,而可以根據元素所在的容器修改元素的行為,不僅是依賴視口大小來更改元素的樣式。
想要使用容器查詢,首先需要在容器上定義 container-type
還可以使用 container-name 來命名容器,如果有多層容器,這將很有用,這樣就可以更明確地了解哪些查詢會影響元素。type 和 name 都可以使用簡寫的 container 屬性來定義,其中 name在前,并通過正斜杠與 type 分隔。
然后就可以使用@container開始查詢了。一旦滿足該條件,CSS 將應用于該容器內的元素。
最后來看一個實際的應用:
現在就可以設置一個容器查詢來更改文章樣式及其任何后代的樣式,這將基于 main 的寬度,因為它是容器元素。
這樣,當文章的寬度小于 60ch 時,就會采用更小的 padding 和 font-size 值。
瀏覽器對容器查詢的支持情況如下:
4.@layer:級聯層
在 2022 年 2 月/3 月,所有現代瀏覽器都發布了 Cascade Layers(級聯層),可以用來控制選擇器如何交互,而不管它們的特殊性或代碼順序。下面來看一個例子:
@layer 聲明了一個_級聯層_,同一層內的規則將級聯在一起,這給予了開發者對層疊機制的更多控制。
上面例子中定義了多個級聯層,當一個聲明中具有多個級聯層時,后定義的級聯層具有更高的優先級。因此上面例子中,state 層具有更高的優先級,即使 theme 樣式中具有更高的特定性(權重)并且在代碼中出現得更晚。
我們還可以嵌套圖層:
層按照每個層名稱首次出現在代碼庫中的順序堆疊,后面的層名稱優先于前面的層。這意味著可以允許它們隱式堆疊:
或者可以像上面例子一樣,按順序引入層名稱來明確定義層順序:
瀏覽器對級聯層的支持情況如下:
可以看到,目前主流瀏覽器都支持 CSS 級聯層功能。
5.:has:父選擇器
:has()選擇器可以檢查父元素中是否存在特定的元素。例如,如果一個卡片組件中有圖片,就給它添加一個display:flex。這以前在 CSS 中是無法實現的,但是新的 :has() 選擇器就可以幫助我們選擇包含特定元素的父元素。
在CSS中,我們無法根據元素中是否存在特定的元素來設置父元素的樣式,要想實現這一點,就必須創建CSS類,并根據需要進行類的切換。來看下面的例子:
這里我們有兩種卡片:包含圖片和不包含圖片。在CSS中需要這樣做:
這里創建了一個類card-plain,專門用于沒有圖片的卡片,在沒有圖片時就不需要flex布局。如果使用 CSS 中的父選擇器 :has 就不需要再寫這個類,只需要使用它來檢查卡片中是否包含.card-image即可:
根據 CSS 規范,:has() 選擇器可以檢查父元素是否包含至少一個元素,或者一個條件,例如輸入是否獲取到焦點。
:has() 選擇器不僅可以檢查父元素是否包含特定的子元素,還可以檢查一個元素后面是否跟有另一個元素:
這將檢查 <h2> 元素是否直接跟在 <p> 元素之后。
我們也可以將它與表單元素一起使用來檢查輸入是否獲取到了焦點:
瀏覽器對 :has() 的支持情況如下:
可以看到,最新版的 Chrome、Edge、Safari 都已經支持了 :has() 選擇器,而 Firfox 目前還不支持
6.:focus-visible
:focus-visible 是一個現代CSS 焦點選擇器。今年 3 月,Safari 15.4 發布了 :focus-visible 偽類,不久之后,它成為常青瀏覽器中使用的默認元素焦點行為。
當元素匹配:focus偽類并且客戶端的啟發式引擎決定焦點應當可見 (在這種情況下很多瀏覽器默認顯示“焦點框”。) 時,:focus-visible 偽類將生效。
注意:Firefox 需要通過較舊的前綴偽類 :-moz-focusring 來支持類似的功能。
下面來看一個例子,:focus-visible 選擇器利用客戶端的行為決定是否匹配。當使用鼠標點擊控件和用鍵盤 tab 切換控件時會有所不同。
效果如下:
這段代碼的表現如下:
- 默認樣式:使用鍵盤控制時,input和button的邊框都是細藍色的;使用鼠標控制時,input的邊框是細藍色的,button的邊框是細黑色的;
- :focus:無論使用鼠標控制還是鍵盤控制,input和button的邊框都是粗黑色的;
- :focus-visible:使用鍵盤控制時,input和button的邊框都是粗橙色的;使用鼠標控制時,input的邊框是粗橙色的,button的邊框是細黑色的;
使用這個偽類,就可以有效地根據用戶的輸入方式 (鼠標 or 鍵盤) 來展示不同形式的焦點。
瀏覽器對 :focus-visible 的支持情況如下:
可以看到,目前主流瀏覽器都已經支持 :focus-visible。
7.color-scheme
color-scheme 是一個 CSS 屬性,當用戶選擇系統配色方案時(系統配色方案的常見選擇是“深色模式”和“淺色模式”),操作系統會對用戶界面進行調整。這包括表單控件、滾動條和 CSS 系統顏色的使用值。
當把上面的代碼復制到樣式表中,頁面就會根據操作系統的設置的暗/亮模式來顯示不同的樣式:
可以看到,當切換系統配色模式時,文字顏色,背景顏色,以及表單(滾動條、選擇下拉框、單選框、復選框、輸入框等)樣式都發生了變化,這樣就省去了我們很多兩種模式下的樣式定義工作。
通常,屬性的值是以下幾種:
其中:
- normal:表示元素未指定任何配色方案,因此應使用瀏覽器的默認配色方案呈現。
- light:表示可以使用操作系統亮色配色方案渲染元素。
- dark:表示可以使用操作系統深色配色方案渲染元素。
需要注意,當light和right都有時,需要light在前,right在后。要想將整個頁面配置為用戶的配色方案首選項,就可以像上面一樣,在 :root 元素上指定 color-scheme。
我們甚至可以僅在 HTML 中就可以獲得深色模式:
瀏覽器對 color-scheme 的支持情況如下:
8.accent-color
accent-color 屬性可以在不改變瀏覽器默認表單組件基本樣式的前提下重置組件的顏色。該屬性目前支持以下 HTML 控件元素:
- 復選框:<input type=”checkbox”>
- 單選框:<input type=”radio”>
- 范圍選擇框:<input type=”range”>
- 進度條:<progress>
下面來看一個例子:
效果如下:
可以看到,這些表單元素都變成我們定義的顏色。
需要注意,如果給表單元素設置了自定義樣式,那 accent-color 就可能會失效。例如,將進度條的 border 設置為藍色:
樣式會是下面這樣,其并不符合預期(進度條邊框為藍色),出現了意料之外的效果。所以,如果使用了 accent-color 定義表單樣式,就要盡量避免再給表單元素自定義其他樣式:
瀏覽器對 accent-color 的支持情況如下:
9.scale、rotate、translate
2022 年 8 月,Chromium 完成了使用單個 rotate, scale, translate 屬性來對 CSS 變換進行更細粒度的控制。
要想在 CSS 中使用變換,需要使用 transform 屬性,該屬性接受一個或多個 <transform-function>:
在上面的代碼中,目標元素會在 X 軸上平移 50%,旋轉 30 度,最后放大到 120%。雖然這樣 transform 屬性可以正常工作,但當想要單獨更改這些值中的任何一個時,就會比較麻煩。
比如,想要在鼠標懸浮時更改 scale 的大小,就需要將 transform 屬性中的所有函數都復制一遍,即使它們的值保持不變。
而在 Chrome 104 中,就可以使用rotate, scale, translate 屬性來單獨定義變換的這些部分。使用這些屬性來重寫前面的變換示例:
這樣,如果想在某些情況下單獨修改每個屬性時,就不需要再復制其他沒有變化的屬性。
原始的 CSS 變換屬性和新屬性之間的一個主要區別是應用聲明的變換順序:
- 使用 transform時,變換函數會按照它們編寫的順序,從左到右;
- 使用單獨的變換屬性時,順序不是聲明的順序。而始終是:首先平移,然后旋轉,最后縮放。
這意味著以下兩端代碼的執行結果是一樣的:
在這兩種情況下,目標元素都會首先在 X 軸上平移 50%,然后旋轉 30 度,最后縮放 1.2。
如果其中一個單獨的變換屬性與 transform 屬性一起聲明,則首先應用單獨的變換(rotate, scale, translate),最后應用 transform。
瀏覽器對 rotate, scale, translate 的支持情況如下:
10.subgrid:子網格
subgrid 允許元素在行軸或列軸上繼承其父元素的網格,主要解決當網格嵌套網格時,子網格的位置和軌道不能和父網格對齊的問題。使用子網格時,需要讓 grid-template-columns 和 grid-template-rows 屬性的值使用 subgrid 關鍵字。
- grid-template-rows:基于網格行維度,定義網格線的名稱和網格軌道的尺寸大小。
- grid-template-columns:基于網格列維度,定義網格線的名稱和網格軌道的尺寸大小。
下面來看一個例子,有一個嵌套網格,它正在為行和列創建自己的軌道。這些軌道是獨立的,因此不會與父網格上的軌道對齊。
上面代碼的效果如下:
下面將 grid-template-columns 的軌道列表替換為 subgrid 關鍵字。嵌套網格的列軌道現在與父級上的列軌道對齊。
更改完之后的效果如下:
只要父級本身就是一個網格,就可以繼續將子網格繼承到子級中。以下示例顯示了三個網格,每個網格都嵌套在另一個網格中,并繼承了其父級的軌道。子項指示哪個網格是它們的父項。
使用 Firefox DevTools 突出顯示每個網格,突出顯示外部網格顯示子網格和網格項如何與該網格對齊:
瀏覽器對子網格的支持情況如下: