相信很多小伙伴都用過 CSS 的屏幕寬度媒體查詢,比如這樣:
@media screen and (min-width: 900px) { div { padding: 1rem 3rem; } }
這里表示的是與屏幕寬度相關的樣式設置,上面的代碼表示當屏幕寬度大于 900px 時,內部的樣式代碼塊才能生效。
其實不僅僅是上面的屏幕寬度媒體查詢,在 CSS 中,存在大量的以?@
?符號開頭的規則。稱之為?@規則
(at-rule)。本文就將介紹一下除去媒體查詢之外,其他有意思的且在未來會越來越重要的?@規則
?規則。
at-rule @規則
@規則(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
,?@styleset
?and?@character-variant
), 允許作者在font-variant-alternates?中使用通用名稱,用于在 OpenType 中以不同方式激活功能。它允許在使用幾種字體時簡化 CSS。@property
?(實驗性),是CSS Houdini?API 的一部分,它允許開發者顯式地定義他們的css 自定義屬性, 允許進行屬性類型檢查、設定默認值以及定義該自定義屬性是否可以被繼承。@layer
, 聲明了一個 級聯層,同一層內的規則將級聯在一起,這給予了開發者對層疊機制的更多控制。
除去我們非常熟悉的?@media
、keyframes
?以及?@font-face
,像是?@supports
、@counter-style
、@property
、@layer
?等都已經或將在未來 Web 應用中扮演舉足輕重的作用。
下面,就跟隨本文,一起對它們一探究竟。你也可以跳過你已經掌握的,翻到對應你還不太了解的 @ 規則下,迅速了解它們。
@[email protected]@namespace
這三個可以放在一起講解,他們的語法比較簡單,也相對好理解。其中:
1、@charset
:指定樣式表中使用的字符編碼。它必須是樣式表中的第一個元素,而前面不得有任何字符。
像這樣:
// style.css @charset "UTF-8";
注意,如果有多個 @charset @規則被聲明,只有第一個會被使用。
很多人會有疑惑,這個聲明到底有什么用呢?
事實上,如果 CSS 文件中有任何非 ASCII 文本,例如字體名稱,偽元素的 content 屬性值、選擇器等中的非 ASCII 字符,都需要確保 CSS 解析器知道如何轉換字節正確轉換為字符,以便它理解 CSS 代碼。
所以如果當你發現你的偽元素 content 中插入了一些內容,但是經過打包編譯后它亂碼了,很有可能是因為你忘了聲明這個字符集。
2、@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 底部,從而造成了頁面的閃爍。當網絡較差時,閃爍體驗更為明顯。
3、@namespace
?:@namespace
?是用來定義使用在 CSS 樣式表中的 XML 命名空間的 @規則。定義的命名空間可以把通配、元素和屬性選擇器限制在指定命名空間里的元素。
并且,任何 @namespace 規則都必須在所有的?@charset
?和?@import
規則之后,并且在樣式表中,位于其他任何樣式聲明之前。
總的來說,@namespace
?在現如今的 CSS 生態中,屬于非常冷門的一個規則?;旧衔覐臉I這么久,沒怎么見過這個屬性的具體使用。
@[email protected]@font-face
這三個 @ 規則,大家應該非常熟悉。
@media
:如果滿足媒介查詢的條件則條件規則組里的規則生效@keyframes
:定義 CSS 動畫的中間步驟@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?特性檢測
好,介紹完一些后續會非常重要從?@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?&&[email protected] and?&&[email protected] or
@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)
。
@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 規則。這三個語法必須同時得到瀏覽器的支持,如果表達式為真,則可以用于實現多行省略效果:
<p>碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記碼云筆記</p> 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; } } p { width: 300px; padding: 0 5px; font-size: 16px; line-height: 2; margin: 10px auto; background: #ddd; }
效果如下:
@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 元素添加漸變。
<div></div> div { margin: 10px auto; width: 200px; height: 200px; background: #fc0; } @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) } }
效果如下:
Can i use?
兼容性來看,先看看?Can i use(更新至 2022/11/03)?吧:
大部分瀏覽器都已經支持了,我們已經可以開始使用起來了,使用?@supports
?實現漸進增強的效果。
@counter-style?CSS 計數器
@counter-style
:是一個 CSS at-rule,它讓開發者可以自定義 counter 的樣式。一個 @counter-style 規則定義了如何把一個計數器的值轉化為字符串表示。
利用?@counter-style
,我們可以構建自定義的計數器樣式。
當然,在?@counter-style
?之前,CSS 還有一種實現簡單計數器的規范,它由如下幾個屬性共同構成:
counter-reset
: 初始化計數器的值counter-increment
:在初始化之后,計數器的值就可以使用 counter-increment 來指定其為遞增或遞減counter()
:計數器的值可以使用 counter() 或 counters() 函數以在 CSS 偽元素的 content 屬性中顯示
我們來看最簡單的一個例子,我們想實現一個 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); }
簡單解釋一下:
- 在?
ul
?的樣式中,每次都會初始化一個 CSS 計數器?stepCount
,默認值為 0 - 在?
li::before
?中的?counter-increment: stepCount 1
?表示每次調用到這里,stepCount 的值加 1 - 最后通過?
counter(stepCount)
?將當前具體的計數值通過偽元素的 content 顯現出來
OK,那么為什么有了上述的 CSS 計數器規范后,又新增了?@counter-style
?CSS 計數器規范呢?
@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; }
效果如下:
完整CSS代碼:
body, html { width: 100%; height: 100%; display: flex; } @counter-style circled-alpha { system: fixed; symbols: 😀 😄 😁 😆 😅 😂 🤣 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨; suffix: " "; } ul { margin: auto; width: 800px; font-size: 24px; line-height: 1.5; } li { list-style: circled-alpha; }
當然,實際使用過程中,@counter-style
?的語法會有一點點復雜,可選的屬性也有很多,更為具體的可以仔細學習下文檔 —?MDN — @counter-style
@property?CSS 自定義屬性
@property
CSS at-rule 是 CSS Houdini API 的一部分, 它允許開發者顯式地定義他們的 CSS 自定義屬性,允許進行屬性類型檢查、設定默認值以及定義該自定義屬性是否可以被繼承。
正常而言,我們定義和使用一個 CSS 自定義屬性的方法是這樣的:
:root { --whiteColor: #fff; } p { color: (--whiteColor); }
而有了?@property
?規則之后,我們還可以像下述代碼這樣去定義個 CSS 自定義屬性:
@property --property-name { syntax: ''; inherits: false; initial-value: #fff; } p { color: var(--property-name); }
簡單解讀下:
@property --property-name
?中的?--property-name
?就是自定義屬性的名稱,定義后可在 CSS 中通過?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
?設定過渡動畫,再看看這次的效果:
完整代碼:
<div class="normal"></div> <div class="property"></div>
html, body { width: 100%; height: 100%; display: flex; } :root { --colorA: #fff; --colorB: #000; } @property --houdini-colorA { syntax: ''; inherits: false; initial-value: #fff; } @property --houdini-colorB { syntax: ''; inherits: false; initial-value: #000; } div { width: 200px; height: 200px; margin: auto; cursor: pointer; } .normal { background: linear-gradient(45deg, var(--colorA), var(--colorB)); transition: 1s background; &:hover { --colorA: yellowgreen; --colorB: deeppink; } } .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; } }
CSS @property
規則的強大之處在于,很多以往無法使用 CSS 進行動畫的效果,如今,借助它都可以實現!
@layer
@layer
?可謂是 CSS 圈 2022 年最受矚目的新特性。
它的出現,目的在于讓大型項目中的 CSS 文件及內容,可以得到更好的控制和管理。
CSS @layer 從?CSS Cascading and Inheritance Level 5?被規范定義。
何為 CSS @layer?簡單而言,CSS?@規則[email protected] 級聯層, 同一層內的規則將級聯在一起, 這給予了開發者對層疊機制的更多控制。
語法也非常簡單,看這樣一個例子:
@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 的誕生,讓我們有能力更好的劃分頁面的樣式層級,更好的處理內部樣式與外部引用樣式的優先級順序,屬于比較重大的一次革新。
@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) {}
?的意思便是,當?.wrap
?容器的寬度小于 400 px 時,采用內部定義的樣式,否則,使用外部默認的樣式
關于容器查詢更為具體的語法,我建議還是上 MDN 或者規范詳細看看 —?MDN — CSS Container Queries
@scroll-timeline
@scroll-timeline
?能夠設定一個動畫的開始和結束由滾動容器內的滾動進度決定,而不是由時間決定。
意思是,我們可以定義一個動畫效果,該動畫的開始和結束可以通過容器的滾動來進行控制。
利用它,我們可以使用純 CSS 實現頁面滾動與 CSS 動畫的結合。
遺憾的是,這個如此好的特性,最近已經被規范廢棄,已經不再推薦使用了:
意思是,即便目前有一些瀏覽器已經支持了?@scroll-timeline
,但是它很快又將要退出歷史舞臺。不再建議再使用這個 at-rule 規則。
這里,
@scroll-timeline
?雖然被廢棄了,但是 CSS 將會換一種實現方式卷土重來。
總結
到這里,其實還有幾個非常冷門且不太實用的 at-rule 規則,譬如:
@color-profile
:允許定義并命名一個顏色配置文件@font-feature-values
:主要是相對字體功能的拓展
能夠搜集到資料太少,文檔也相對簡陋,目前實用的場景太少,就不詳細展開。
綜上,可以看到,整個 at-rule 家族還是非常強大的,引入了非常多新的特性及功能,讓 CSS 生態愈發強大。讓 CSS 可以做到的事情越來越多,我們也有理由期待未來 CSS 會在 Web 領域扮演愈發重要的角色。
1. 本站所有文章教程及資源素材均來源于網絡與用戶分享或為本站原創,僅限用于學習和研究。
2. 如果內容損害你的權益請聯系客服QQ:1642748312給予處理。
碼云筆記 » [email protected]