大部分同學都用過 CSS 的螢幕寬度媒體查詢,像是這樣:
@media screen and (min-width: 900px) {
div {
padding: 1rem 3rem;
}
}
這裡表示的是與螢幕寬度相關的樣式設定,上面的代碼表示當螢幕寬度大于 900px 時,内部的樣式代碼塊才能生效。
其實不僅僅是上面的螢幕寬度媒體查詢,在 CSS 中,存在大量的以
@
符号開頭的規則。稱之為
@規則
(at-rule)。本文就将介紹一下除去媒體查詢之外,其他有意思的且在未來會越來越重要的
@規則
規則。
at-rule @規則
OK,什麼是 @規則(at-rule )呢?
一個 at-rule 是一個 CSS 語句,以 at 符号開頭, '
@
' (
U+0040 COMMERCIAL AT
), 後跟一個辨別符,并包括直到下一個分号的所有内容, '
;
' (
U+003B SEMICOLON
), 或下一個 CSS 塊,以先到者為準。
除去我們最為熟悉的
@media
之外,CSS 還有哪些 @規則 呢?
下面是一些 @規則,由它們的标示符指定,每種規則都有不同的文法:
- @charset, 定義樣式表使用的字元集。
- @import, 告訴 CSS 引擎引入一個外部樣式表。
- @namespace, 告訴 CSS 引擎必須考慮 XML 命名空間。
下面是一些嵌套 @ 規則,是嵌套語句的子集,不僅可以作為樣式表裡的一個語句,也可以用在條件規則組裡:
- @media,如果滿足媒介查詢的條件則條件規則組裡的規則生效。
- @page,描述列印文檔時布局的變化。
- @font-face,描述将下載下傳的外部的字型。
- @keyframes,描述 CSS 動畫的中間步驟。
- @supports, 如果滿足給定條件則條件規則組裡的規則生效。
- @document,如果文檔樣式表滿足給定條件則條件規則組裡的規則生效。 (推延至 CSS Level 4 規範)
- @viewport (已廢棄),規則讓我們可以對文檔的大小進行設定。這個特性主要被用于移動裝置,但是也可以用在支援類似“固定到邊緣”等特性的桌面浏覽器,如微軟的 Edge。
- @counter-style — 一個
規則定義了如何把一個計數器的值轉化為字元串表示。@counter-style
- @font-feature-values (plus
, @swash
, @ornaments
, @annotation
, @stylistic
and @styleset
), 允許作者在font-variant-alternates 中使用通用名稱,用于在 OpenType 中以不同方式激活功能。它允許在使用幾種字型時簡化 CSS。@character-variant
- @property (實驗性),是CSS Houdini API 的一部分,它允許開發者顯式地定義他們的css 自定義屬性, 允許進行屬性類型檢查、設定預設值以及定義該自定義屬性是否可以被繼承。
- @layer, 聲明了一個 級聯層,同一層内的規則将級聯在一起,這給予了開發者對層疊機制的更多控制。
除去我們非常熟悉的
@media
、
keyframes
以及
@font-face
,像是
@supports
、
@counter-style
、
@property
、
@layer
等都已經或将在未來 Web 應用中扮演舉足輕重的作用。
下面,就跟随本文,一起對它們一探究竟。你也可以跳過你已經掌握的,翻到對應你還不太了解的 @ 規則下,迅速了解它們。
@charset、@import、@namespace
這三個可以放在一起講解,他們的文法比較簡單,也相對好了解。其中:
-
:指定樣式表中使用的字元編碼。它必須是樣式表中的第一個元素,而前面不得有任何字元。@charset
像是這樣:
// style.css
@charset "UTF-8";
注意,如果有多個 @charset @規則被聲明,隻有第一個會被使用。
很多人會有疑惑,這個聲明到底有什麼用呢?
事實上,如果 CSS 檔案中有任何非 ASCII 文本,例如字型名稱,僞元素的 content 屬性值、選擇器等中的非 ASCII 字元,都需要確定 CSS 解析器知道如何轉換位元組正确轉換為字元,以便它了解 CSS 代碼。
是以如果當你發現你的僞元素 content 中插入了一些内容,但是經過打包編譯後它亂碼了,很有可能是因為你忘了聲明這個字元集。
-
:用于從其他樣式表導入樣式規則。這些規則必須先于所有其他類型的規則,@import
規則除外@charset
@import 有兩種文法:
- url() 内包含 style sheet 的 URI
- 直接寫 style sheet 的 URI 的字元串
還可以直接在後面定義媒體查詢規則,像是這樣:
@import 'custom.css';
@import url('landscape.css');
@import url('landscape.css') screen and (orientation:landscape);
合理的使用
@import
其實也是有好處的:
- 可以合理的控制 CSS 檔案的大小
- 更好的分治與複用
很多人可能會經常看到,網絡上會有各種抵制 @import的文章,不過既然設計了 @import,總有它的有用之處,不能過于絕對。使用
@import
影響頁面性能的地方主要展現在兩個方面:
- 影響浏覽器的并行下載下傳
- 優先級問題,樣式互相覆寫
- 導緻頁面閃爍
這裡可以簡單解釋一下。首先我們得知道,加載頁面時,link 标簽引入的 CSS 被同時加載,而 @import 引入的 CSS 将在頁面加載完畢後被加載。
CSS 解析引擎在對一個 CSS 檔案進行解析時,如在檔案頂部遇到
@import
規則,将被替換為該 @import 導入的 CSS 檔案中的全部樣式。而
@import
内的規則其後被加載,卻會在加載完畢後置于樣式表頂部,最終渲染時,如果存在同名同優先級樣式,會被下面的同名樣式層疊,導緻所謂的優先級沖突。
實際上,浏覽器渲染的動作一般會執行多次的。最後一次渲染,一定是基于之前加載過的所有樣式整合後渲染樹進行繪制頁面的,
而由于
@import
内的規則的加載時機問題,會在頁面内容加載完後再加載。相當于把 CSS 放在了 body 底部,進而造成了頁面的閃爍。當網絡較差時,閃爍體驗更為明顯。
-
:@namespace
是用來定義使用在 CSS 樣式表中的 XML 命名空間的 @規則。定義的命名空間可以把通配、元素和屬性選擇器限制在指定命名空間裡的元素。@namespace
并且,任何 @namespace 規則都必須在所有的
@charset
和
@import
規則之後,并且在樣式表中,位于其他任何樣式聲明之前。
總的來說,
@namespace
在現如今的 CSS 生态中,屬于非常冷門的一個規則。基本上我從業這麼久,沒怎麼見過這個屬性的具體使用。
如果你對它确實感興趣,可以看看這篇詳解 -- spacing-out-on-css-namespaces.
@media
、 @keyframes
、 @font-face
@media
@keyframes
@font-face
這三個 @ 規則,大家應該非常熟悉。
-
:如果滿足媒介查詢的條件則條件規則組裡的規則生效@media
-
:定義 CSS 動畫的中間步驟@keyframes
-
:描述将下載下傳的外部的字型@font-face
@keyframes
和
@font-face
這兩個大家肯定非常熟悉。
但是
@media
其實内有乾坤!除了螢幕寬度媒體查詢外,其實還存在非常多不同功能的媒體查詢!
下面我會列出一些在未來,我認為會越來越被提及使用到的
@media
規則。
prefers-reduced-motion 減弱動畫效果
prefers-reduced-motion 規則查詢用于減弱動畫效果,除了預設規則,隻有一種文法取值
prefers-reduced-motion: reduce
,開啟了該規則後,相當于告訴使用者代理,希望他看到的頁面,可以删除或替換掉一些會讓部分視覺運動障礙者不适的動畫類型。
規範原文:Indicates that user has notified the system that they prefer an interface that removes or replaces the types of motion-based animation that trigger discomfort for those with vestibular motion disorders.
vestibular motion disorders 是一種視覺運動障礙患者,中文我隻能谷歌翻譯,翻譯出來是前庭運動障礙,我感覺不太對,谷歌了一下是一種會導緻眩暈的一類病症,譬如一個動畫一秒閃爍多次,就會導緻患者的不适。
使用方法,還是上面那段代碼:
.ele {
animation: aniName 5s infinite linear;
}
@media (prefers-reduced-motion: reduce) {
.ele {
animation: none;
}
}
如果我們有一些類似這樣的動畫:
在使用者開啟了
prefers-reduced-motion: reduce
時,就應該把它去掉。那麼該如何開啟這個選項呢?MDN -- prefers-reduced-motion 給出的是:
- 在 GTK/Gnome 中,可以通過 GNOME Tweaks (在“通用”或“外觀”菜單中,取決于具體版本) 的配置,設定 gtk-enable-animations 的值為 false
- 可以在 GTK 3 的配置檔案中的 [Settings] 子產品下設定 gtk-enable-animations = false
- 在 Windows 10 中:設定 > 輕松擷取 > 顯示 > 在 Windows 中顯示動畫
- 在 Windows 7 中:控制台 > 輕松擷取 > ?是計算機更易于檢視 > 關閉不必要動畫
- 在 MacOS 中:系統偏好 > 輔助使用 > 顯示 > 減少運動
- 在 iOS 上:設定 > 通用 > 輔助性 > 減少運動
- 在 Android 9+ 上:設定 > 輔助性 > 移除動畫
prefers-color-scheme 适配明暗主題
prefers-color-scheme
還是非常好了解的,它用于比對使用者通過作業系統設定的明亮或夜間(暗)模式。它有兩個不同的取值:
-
: 明亮模式prefers-color-scheme: light
-
: 夜間(暗)模式prefers-color-scheme: dark
文法如下,如果我們預設的是明亮模式,隻需要适配夜間模式即可:
body {
background: white;
color: black;
}
@media (prefers-color-scheme: dark) {
body {
background: black;
color: white;
}
}
當然,上述隻是 CSS 代碼示意,要做到兩套主題的切換肯定不是這麼簡單,方法也很多,本文不贅述,讀者可以自行了解各種實作主題切換,或者是明暗切換的方案。
prefers-contrast 調整内容色彩對比度
prefers-contrast
該 CSS 媒體功能是用來檢測使用者是否要求将網頁内容以更高或者更低的對比度進行呈現。其中:
-
:預設值,不作任何變化prefers-contrast: no-preference
-
:希望使用對比度更低的界面prefers-contrast: less
-
:希望使用對比度更高的界面prefers-contrast: more
以
prefers-contrast: less
為例子,文法如下:
body {
background: #fff; // 文字與背景對比度為 5.74
color: #666;
}
// 提升對比度
@media (prefers-contrast: more) {
body {
background: #fff; // 文字與背景對比度為 21
color: #000;
}
}
上面隻是僞 CSS 代碼,具體可能需要對具體的一些元素進行處理,或者使用
filter: contrast()
全局統一處理,當開啟配置時,用于實作類似這樣的功能:
什麼是色彩對比度
是否曾關心過頁面内容的展示,使用的顔色是否恰當?色弱、色盲使用者能否正常看清内容?良好的色彩使用,在任何時候都是有益的,而且不僅僅局限于對于色弱、色盲使用者。在戶外用手機、陽光很強看不清,符合無障礙标準的高清晰度、高對比度文字就更容易閱讀。
這裡就有一個概念 -- 顔色對比度,簡單地說,描述就是兩種顔色在亮度(Brightness)上的差别。運用到我們的頁面上,大多數的情況就是背景色(background-color)與内容顔色(color)的對比差異。
最權威的網際網路無障礙規範 —— WCAG AA規範規定,所有重要内容的色彩對比度需要達到 4.5:1 或以上(字号大于18号時達到 3:1 或以上),才算擁有較好的可讀性。
prefers-reduced-transparency 減少透明元素
prefers-reduced-transparency
該 CSS 媒體功能是用來檢測使用者是否要求減少網頁中的透明元素:
-
:預設值,不作任何變化prefers-contrast: no-preference
-
:希望界面元素存在盡可能少的透明元素prefers-contrast: reduce
以
prefers-contrast: reduce
為例子,文法如下:
.ele {
opacity: 0.5;
}
// 減少透明元素
@media (prefers-contrast: reduce) {
.ele {
opacity: 1;
}
}
我在上一次,介紹這個功能的時候,它還是一片紅色,但是短短半年,整個相容性已經有了很大的提升!
prefers-reduced-data 減少資料傳輸
對于部分網速較差的地區,或者流量很貴的情況,使用者會希望減少頁面中的流量請求,基于此有了
prefers-reduced-data
。
prefers-reduced-data
該 CSS 媒體查詢功能是用于告知使用者代理,希望減少頁面的流量請求。
-
:預設值,不作任何變化prefers-reduced-data: no-preference
-
:希望界面元素消耗更少的網際網路流量prefers-reduced-data: reduce
以
prefers-reduced-data: reduce
為例子,文法如下:
.ele {
background-image: url(image-1800w.jpg);
}
// 降低圖檔品質
@media (prefers-reduced-data: reduce) {
.ele {
background-image: url(image-600w.jpg);
}
}
當檢測到使用者開啟了
prefers-reduced-data: reduce
,我們将提供壓縮度更高,尺寸更小,消耗流量更少的圖檔。
當然,上述代碼隻是個示意,我們可以做的其實有更多。
不過,這是仍處于實驗室的功能,暫時沒有任何浏覽器支援該媒體查詢~ 😢
當然,從 Chrome 85+ 開始,可以通過開啟
#enable-experimental-web-platform-features
實驗室選項開啟該功能!
@supports
特性檢測
@supports
好,介紹完一些後續會非常重要從
@media
規則後,我們來看看
@supports
。
傳統的 CSS 特性檢測都是通過 javascript 實作的,但是如今,原生 CSS 即可實作特性檢測的功能。
CSS
@supports
通過 CSS 文法來實作特性檢測,并在内部 CSS 區塊中寫入如果特性檢測通過希望實作的 CSS 語句。
文法:
@supports <supports_condition> {
/* specific rules */
}
舉個例子:
div {
position: fixed;
}
@supports (position:sticky) {
div {
position:sticky;
}
}
上面的例子中,
position: sticky
是 position 的一個比較新的屬性,用于實作黏性布局,可以輕松實作一些以往需要 Javascript 才能實作的布局,但是不一定在一些低端機型上相容。
上面的寫法,首先定義了 div 的
position: fixed
,緊接着下面一句
@supports (position:sticky)
則是特性檢測括号内的内容,如果目前浏覽器支援
@supports
文法,并且支援
position:sticky
文法,那麼 div 的 則會被設定為
position:sticky
。
我們可以看到,
@supports
文法的核心就在于這一句:
@supports (...) { }
,括号内是一個 CSS 表達式,如果浏覽器判斷括号内的表達式合法,那麼接下來就會去渲染括号内的 CSS 表達式。除了這種最正常的用法,還可以配合其他幾個關鍵字:
@supports not
&& @supports and
&& @supports or
@supports not
@supports and
@supports or
@supports not
-- 非
@supports not
not 操作符可以放在任何表達式的前面來産生一個新的表達式,新的表達式為原表達式的值的否定。看個例子:
.container {
translate: 50% 10%;
rotate: 80deg;
scale: 1.5;
}
// 如果不支援上述的文法,則 supports 内的文法生效
@supports not (scale: 1) {
.container {
transform: translate(50%, 10%) rotate(80deg) scale(1.5);
}
}
因為添加了 not 關鍵字,是以與上面第一個例子相反,這裡如果檢測到浏覽器不支援 transform 這種分開單獨的寫法 --
scale: 1
,則将
.container
的 transform 屬性合在一起寫,寫成
transform: translate(50%, 10%) rotate(80deg) scale(1.5)
。
關于 transform 的分開寫法,如果你還不太了解,可以戳:解放生産力!transform 支援單獨指派改變
@supports and
-- 與
@supports and
這個也好了解,多重判斷,類似 javascript 的
&&
運算符符。用 and 操作符連接配接兩個原始的表達式。隻有兩個原始表達式的值都為真,生成的表達式才為真,反之為假。
當然,and 可以連接配接任意多個表達式看個例子:
p {
overflow: hidden;
text-overflow: ellipsis;
}
@supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical) {
p {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
上面同時,檢測
@supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical)
了三個文法,如果同時支援,則設定三個 CSS 規則。這三個文法必須同時得到浏覽器的支援,如果表達式為真,則可以用于實作多行省略效果:
CodePen Demo - @supportAnd
@supports or
-- 或
@supports or
了解了
@supports and
,就很好了解
@supports or
了,與 javascript 的
||
運算符類似,表達式中隻要有一個為真,則生成表達式表達式為真。
看例子:
@supports (background:-webkit-linear-gradient(0deg, yellow, red)) or (background:linear-gradient(90deg, yellow, red)){
div {
background:-webkit-linear-gradient(0deg, yellow, red);
background:linear-gradient(90deg, yellow, red)
}
}
上面的例子中,隻有檢測到浏覽器支援
background:-webkit-linear-gradient(0deg, yellow, red)
或者(or)
background:linear-gradient(90deg, yellow, red)
其中一個,則給 div 元素添加漸變。
CodePen Demo -- @supports or
當然,關鍵字
not
還可以和
and
或者
or
混合使用。感興趣的可以嘗試一下。
Can i use?
相容性來看,先看看 Can i use(更新至 2022/10/13) 吧:
大部分浏覽器都已經支援了,我們已經可以開始使用起來了,使用
@supports
實作漸進增強的效果。
@counter-style
CSS 計數器
@counter-style
@counter-style
:是一個 CSS at-rule,它讓開發者可以自定義 counter 的樣式。一個 @counter-style 規則定義了如何把一個計數器的值轉化為字元串表示。
利用
@counter-style
,我們可以建構自定義的計數器樣式。
當然,在
@counter-style
之前,CSS 還有一種實作簡單計數器的規範,它由如下幾個屬性共同構成:
-
: 初始化計數器的值counter-reset
-
:在初始化之後,計數器的值就可以使用 counter-increment 來指定其為遞增或遞減counter-increment
-
:計數器的值可以使用 counter() 或 counters() 函數以在 CSS 僞元素的 content 屬性中顯示counter()
我們來看最簡單的一個例子,我們想實作一個 ul 布局,其中的 li 個數不定,但是均分每行的空間,并且能夠自動帶上序号,像是這樣:
使用
counter-reset
、
counter-increment
、
counter()
這一套,非常的簡單就能實作,像是這樣:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
// ... <li> 個數不定
</ul>
<ul>
// ... <li> 個數不定
</ul>
給每個 li 元素标序号這個事情就可以交給 CSS 計數器:
ul {
display: flex;
justify-content: space-around;
counter-reset: stepCount;
}
li {
position: relative;
}
li::before {
position: absolute;
counter-increment: stepCount 1;
content: counter(stepCount);
}
簡單解釋一下:
- 在
的樣式中,每次都會初始化一個 CSS 計數器 ul
,預設值為 0stepCount
- 在
中的 li::before
表示每次調用到這裡,stepCount 的值加 1counter-increment: stepCount 1
- 最後通過
将目前具體的計數值通過僞元素的 content 顯現出來counter(stepCount)
OK,那麼為什麼有了上述的 CSS 計數器規範後,又新增了
@counter-style
CSS 計數器規範呢?
@counter-style
的意義
@counter-style
這是因為,上述的
counter-reset
、
counter-increment
、
counter()
這一套更多的生成的數字類型的計數器。
但是,數字類型的計數器無法滿足目前全球化的排版的訴求。基于此,
@counter-style
規則用一種開放的方式彌補了這一缺點,在預定義的樣式不能滿足需求時,它可以使開發者自定義他們自己的計數器樣式。
舉個例子,我們使用 MDN 上的例子作為示例:
<ul>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </li>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </li>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </li>
<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </li>
</ul>
@counter-style circled-alpha {
system: fixed;
symbols: Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ;
suffix: " ";
}
li {
list-style: circled-alpha;
}
這樣,我們就可以得到自定義的計數字首:
有了這個,我們就可以将上述的
symbols
替換成其他我們喜歡我計數圖形,譬如 emoji 圖形:
@counter-style circled-alpha {
system: fixed;
symbols: 😀 😄 😁 😆 😅 😂 🤣 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨;
suffix: " ";
}
li {
list-style: circled-alpha;
}
看看效果:
CodePen Demo -- @counter-style
當然,實際使用過程中,
@counter-style
的文法會有一點點複雜,可選的屬性也有很多,更為具體的可以仔細學習下文檔 -- MDN -- @counter-style
@property
CSS 自定義屬性
@property
@property CSS at-rule 是 CSS Houdini API 的一部分, 它允許開發者顯式地定義他們的 CSS 自定義屬性,允許進行屬性類型檢查、設定預設值以及定義該自定義屬性是否可以被繼承。
正常而言,我們定義和使用一個 CSS 自定義屬性的方法是這樣的:
:root {
--whiteColor: #fff;
}
p {
color: (--whiteColor);
}
而有了
@property
規則之後,我們還可以像下述代碼這樣去定義個 CSS 自定義屬性:
<style>
@property --property-name {
syntax: '<color>';
inherits: false;
initial-value: #fff;
}
p {
color: var(--property-name);
}
</style>
簡單解讀下:
-
中的 @property --property-name
就是自定義屬性的名稱,定義後可在 CSS 中通過 --property-name
進行引用var(--property-name)
- syntax:該自定義屬性的文法規則,也可以了解為表示定義的自定義屬性的類型
- inherits:是否允許繼承
- initial-value:初始值
其中,
@property
規則中的 syntax 和 inherits 描述符是必需的。
當然,在 JavaScript 内定義的寫法也很簡單,順便一提:
<script>
CSS.registerProperty({
name: "--property-name",
syntax: "<color>",
inherits: false,
initialValue: "#c0ffee"
});
</script>
CSS @property 的優勢
為什麼要使用這麼麻煩的文法定義 CSS 自定義屬性呢?CSS Houdini 定義的自定義變量的優勢在哪裡?
我們來看這樣一個例子,我們有這樣一個漸變的圖案:
<div></div>
div {
background: linear-gradient(45deg, #fff, #000);
}
我們改造下上述代碼,改為使用 CSS 自定義屬性:
:root {
--colorA: #fff;
--colorB: #000;
}
div {
background: linear-gradient(45deg, var(--colorA), var(--colorB));
}
得到的還是同樣的一個漸變圖:
我們再加上一個過渡效果:
:root {
--colorA: #fff;
--colorB: #000;
}
div {
background: linear-gradient(45deg, var(--colorA), var(--colorB));
transition: 1s background;
&:hover {
--colorA: yellowgreen;
--colorB: deeppink;
}
}
看看滑鼠 Hover 的時候,會發生什麼:
雖然我們設定了 1s 的過渡動畫
transition: 1s background
,但是很可惜,CSS 是不支援背景漸變色的直接過渡變化的,我們得到的隻是兩幀之間的直接變化。
使用 CSS @property 進行改造
OK,接下來我們就使用本文的主角,使用 Houdini API 中的 CSS 自定義屬性替換原本的 CSS 自定義屬性。
簡單進行改造一下,使用
color
syntax 文法類型:
@property --houdini-colorA {
syntax: '<color>';
inherits: false;
initial-value: #fff;
}
@property --houdini-colorB {
syntax: '<color>';
inherits: false;
initial-value: #000;
}
.property {
background: linear-gradient(45deg, var(--houdini-colorA), var(--houdini-colorB));
transition: 1s --houdini-colorA, 1s --houdini-colorB;
&:hover {
--houdini-colorA: yellowgreen;
--houdini-colorB: deeppink;
}
}
我們使用了
@property
文法,定義了兩個 CSS Houdini 自定義變量
--houdini-colorA
和
--houdini-colorB
,在 hover 變化的時候,改變這兩個顔色。
需要關注的是,我們設定的過渡語句
transition: 1s --houdini-colorA, 1s --houdini-colorB
,在這裡,我們是針對 CSS Houdini 自定義變量設定過渡,而不是針對
background
設定過渡動畫,再看看這次的效果:
Wow,成功了,漸變色的變化從兩幀的逐幀動畫變成了補間動畫,實作了從一個漸變色過渡到另外一個漸變色的效果!而這,都得益于 CSS Houdini 自定義變量的強大能力!
CodePen Demo -- CSS Houdini 自定義變量實作漸變色過渡動畫
CSS @property 規則的強大之處在于,很多以往無法使用 CSS 進行動畫的效果,如今,借助它都可以實作!
更多 CSS @property 的用法,你可以戳 CSS @property,讓不可能變可能
@layer
@layer
@layer
可謂是 CSS 圈 2022 年最受矚目的新特性。
它的出現,目的在于讓大型項目中的 CSS 檔案及内容,可以得到更好的控制和管理。
CSS @layer 從 CSS Cascading and Inheritance Level 5 被規範定義。
何為 CSS @layer?簡單而言,CSS @規則 中的@layer聲明了一個 級聯層, 同一層内的規則将級聯在一起, 這給予了開發者對層疊機制的更多控制。
文法也非常簡單,看這樣一個例子:
@layer utilities {
/* 建立一個名為 utilities 的級聯層 */
}
這樣,我們就建立一個名為 utilities 的 @layer 級聯層。
@layer 級聯層如何使用呢?
通過 @layer 級聯層管理樣式優先級
@layer 級聯層最大的功能,就是用于控制不同樣式之間的優先級。
看下面這樣一個例子,我們定義了兩個 @layer 級聯層 A 和 B:
<div></div>
div {
width: 200px;
height: 200px;
}
@layer A {
div {
background: blue;
}
}
@layer B {
div {
background: green;
}
}
由于
@layer B
的順序排在
@layer A
之後,是以
@layer B
内的所有樣式優先級都會比
@layer A
高,最終 div 的顔色為
green
:
當然,如果頁面内的 @layer 太多,可能不太好記住所有 @layer 的順序,是以,還有這樣一種寫法。
我們可以同時命名多個 @layer 層,其後再補充其中的樣式規則。
<div></div>
@layer B, C, A;
div {
width: 200px;
height: 200px;
}
@layer A {
div {
background: blue;
}
}
@layer B {
div {
background: green;
}
}
@layer C {
div {
background: orange;
}
}
上述代碼,我們首先定義了
@layer B, C, A
三個 @layer 級聯層。而後再後面的 CSS 代碼中補充了每個級聯層的 CSS 代碼,但是樣式的優先級為:
A > C > B
是以,最終的 div 的顔色值為 @layer A 中定義的顔色,為
blue
:
到這裡,CSS @layer 的作用可以清晰的被窺見。
利用 CSS @layer,我們可以将 CSS 不同子產品劃入不同的 @layer 中,利用先後順序,非常好的去控制全局的樣式優先級。
CSS @layer 的誕生,讓我們有能力更好的劃分頁面的樣式層級,更好的處理内部樣式與外部引用樣式的優先級順序,屬于比較重大的一次革新。
這裡隻是非常簡單的介紹了 @layer 規則,更詳細的,你可以戳這裡:2022 年最受矚目的新特性 CSS @layer 到底是個啥?
@container
容器查詢
@container
@container
:提供了一種,基于容器的可用寬度來改變布局的方式。
容器查詢也是一個非常新且重要的特性,彌補了過往媒體查詢的不足。
在之前,響應式有這麼個掣肘。同一 DOM 的不同布局形态如果想要變化,需要依賴諸如媒體查詢來實作。
像是這樣:
通過浏覽器視窗大小的變化,借助媒體查詢,實作不一樣的布局。
但是,在現如今,大部分 PC 端頁面使用的是基于 Flex/Grid 的彈性布局。
很多時候,當内容數不确定的時候,即便是相同的浏覽器視窗寬度下,元素的布局及寬度可能也是不一緻的。
考慮下面這種情況:
<!-- 情況一 -->
<ul class="wrap">
<li></li>
<li></li>
<li></li>
</ul>
<!-- 情況二 -->
<ul class="wrap">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
.wrap {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
li {
width: 190px;
height: 100px;
flex-grow: 1;
flex-shrink: 0;
}
這種情況下,如果需要在不同寬度下對最後一個元素做一下處理,傳統方式還是比較麻煩的。
在這種情況下,容器查詢(CSS Container Queries)就應運而生了!
容器查詢的能力
容器查詢它給予了 CSS,在不改變浏覽器視口寬度的前提下,隻是根據容器的寬度變化,對布局做成調整的能力。
還是上面的例子,簡單的代碼示意:
<div class="wrap">
<div class="g-container">
<div class="child">Title</div>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus vel eligendi, esse illum similique sint!!</p>
</div>
</div>
.wrap {
width: 500px;
resize: horizontal;
overflow: auto;
}
.g-container {
display: flex;
flex-wrap: nowrap;
}
.wrap {
/* CSS CONTAINER */
container-name: wrap;
container-type: inline-size;
}
@container wrap (max-width: 400px) {
.g-container {
flex-wrap: wrap;
flex-direction: column;
}
}
像是這樣,我們通過
resize: horizontal
來模拟單個容器的寬度變化,在這種情況下,容器查詢能夠做到在不同寬度下,改變容器内部的布局。
這樣,就簡單實作了一個容器查詢功能:
注意,仔細和上面的例子作對比,這裡,浏覽器的視口寬度是沒有變化的,變化的隻是容器的寬度!
媒體查詢與容器查詢的異同,通過一張簡單的圖看看,核心的點在于容器的寬度發生變化時,視口的寬度不一定會發生變化:
我們簡單拆解下上述的代碼,非常好了解。
- 在
的樣式中,通過 .warp
注冊一個容器container-name: wrap
- 注冊完容器之後,便可以通過
容器查詢文法,在内部寫入不同情況下的另外一套樣式@container wrap ()
- 這裡
的意思便是,當 @container wrap (max-width: 400px) {}
容器的寬度小于 400 px 時,采用内部定義的樣式,否則,使用外部預設的樣式.wrap
關于容器查詢更為具體的文法,我建議還是上 MDN 或者規範詳細看看 -- MDN -- CSS Container Queries
@scroll-timeline
@scroll-timeline
在之前,我介紹了 CSS 最新的特性
@scroll-timeline
,譬如這兩篇文章:
- 革命性創新,動畫殺手锏 @scroll-timeline
- 超酷炫的轉場動畫?CSS 輕松拿下!
@scroll-timeline
能夠設定一個動畫的開始和結束由滾動容器内的滾動進度決定,而不是由時間決定。
意思是,我們可以定義一個動畫效果,該動畫的開始和結束可以通過容器的滾動來進行控制。
利用它,我們可以使用純 CSS 實作頁面滾動與 CSS 動畫的結合,像是這樣:
遺憾的是,這個如此好的特性,最近已經被規範廢棄,已經不再推薦使用了:
意思是,即便目前有一些浏覽器已經支援了
@scroll-timeline
,但是它很快又将要退出曆史舞台。不再建議再使用這個 at-rule 規則。
這裡, @scroll-timeline
雖然被廢棄了,但是 CSS 将會換一種實作方式卷土重來。
總結一下
到這裡,其實還有幾個非常冷門且不太實用的 at-rule 規則,譬如:
-
:允許定義并命名一個顔色配置檔案@color-profile
-
:主要是相對字型功能的拓展@font-feature-values
能夠搜集到資料太少,文檔也相對簡陋,目前實用的場景太少,就不詳細展開。
綜上,可以看到,整個 at-rule 家族還是非常強大的,引入了非常多新的特性及功能,讓 CSS 生态愈發強大。讓 CSS 可以做到的事情越來越多,我們也有理由期待未來 CSS 會在 Web 領域扮演愈發重要的角色。
好了,本文到此結束,希望本文對你有所幫助 😃