掃二維碼與項(xiàng)目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
最近,有一則非常振奮人心的消息,CSS 即將原生支持嵌套 --Agenda+ to publish FPWD of Nesting[1],表示 CSS 嵌套規(guī)范即將進(jìn)入規(guī)范的 FWPD 階段。

創(chuàng)新互聯(lián)于2013年開始,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元茫崖做網(wǎng)站,已為上家服務(wù),為茫崖各地企業(yè)和個人服務(wù),聯(lián)系電話:18982081108
目前對應(yīng)的規(guī)范為 --CSS Nesting Module[2]。
隨著 CSS 自定義屬性(CSS Variable)的大規(guī)模兼容,到如今 CSS 即將支持嵌套,一些預(yù)處理器的核心功能已經(jīng)被 CSS 原生支持,這是否表示 SASS/LESS 等預(yù)處理器已無用武之地?即將被淘汰了?
首先簡單介紹一下,一個規(guī)范從提出到落地,會經(jīng)歷的一些階段:
上文說的,即將進(jìn)入 FPWD,只是處于規(guī)范的第 2 個階段 WD 階段,F(xiàn)PWD 表示第一次公開工作草案( First Public Working Draft (FPWD))。FPWD 后面還會有數(shù)個工作草案,會處理來自 CSSWG 內(nèi)部和小組外部更廣泛社會的反饋。完善規(guī)范的設(shè)計(jì)。
也就是說,目前來看,即便后面的流程順利,要等到瀏覽器大范圍實(shí)現(xiàn)該規(guī)范到能落地的那天還有非常長一段時間。
除此之外,我覺得 SASS\LESS 等預(yù)處理器還有一些比較有意思的功能(函數(shù)),是即便原生 CSS 支持了自定義屬性和嵌套之后依舊欠缺的,我簡單羅列羅列我的看法。
目前,原生 CSS 依舊不支持循環(huán)函數(shù)。
但是其實(shí)在預(yù)處理器中,循環(huán)還算是比較常用的一個功能??紤]下面這種布局:
ul 下面有多個 li,每個 li 的高度遞增 20px,一個一個寫當(dāng)然也可以,但是有了循環(huán)其實(shí)能極大減少工作量:
如果沒有預(yù)處理器,我們的 CSS 可能是這樣的:
- ul {
- display: flex;
- align-items: baseline;
- justify-content: space-between;
- }
- li {
- width: 50px;
- background: #000;
- }
- li:nth-child(1) {
- height: 20px;
- }
- li:nth-child(2) {
- height: 40px;
- }
- // ... 3~9
- li:nth-child(10) {
- height: 200px;
- }
如果利用 SASS 預(yù)處理器,可以簡化成:
- ul {
- display: flex;
- align-items: baseline;
- justify-content: space-between;
- }
- li {
- width: 50px;
- background: #000;
- }
- @for $i from 1 through 10 {
- li:nth-child(#{$i}) {
- height: calc(#{$i} * 20px);
- }
- }
當(dāng)然,除此之外,在非常多的復(fù)雜 CSS 動畫效果中,循環(huán)是非常非常常用的功能。
譬如一些粒子動畫,我們通??赡苄枰ゲ倏v 50~100 個粒子,也就是 50~100 個 div 的樣式,甚至更多,如果沒有循環(huán),一個一個去寫效率會大打折扣。
下面我簡單羅列一些我實(shí)現(xiàn)過的,運(yùn)用到了 CSS 預(yù)處理器循環(huán)功能的動畫效果。
像上面這個使用純 CSS 實(shí)現(xiàn)的火焰效果,其中的火焰的動態(tài)燃燒效果。其實(shí)是通過大量的細(xì)微粒子的運(yùn)動,配合濾鏡實(shí)現(xiàn)。
其中使用到了 SASS 的循環(huán)函數(shù)的片段:
- @for $i from 1 to 200 {
- .g-ball:nth-child(#{$i}) {
- $width: #{random(50)}px;
- width: $width;
- height: $width;
- left: calc(#{(random(70))}px - 55px);
- }
- .g-ball:nth-child(#{$i}) {
- animation: movetop 1s linear -#{random(3000)/1000}s infinite;
- }
- }
嗯哼,上面的循環(huán)是循環(huán)了 200 次之多,如果真要一個一個寫,工作量還是非常巨大的。上述效果的完整代碼,你可以戳這里:
CodePen Demo -- CSS Candles[3]
接下來一個就是 if() 條件語句。
其實(shí),CSS 中有一類非常類似條件語句的寫法,也就是媒體查詢 @media 以及 特性檢測 @supports 語句,目前 CSS 中支持的類似條件選擇的一些寫法如下:
CSS @supports 通過 CSS 語法來實(shí)現(xiàn)特性檢測,并在內(nèi)部 CSS 區(qū)塊中寫入如果特性檢測通過希望實(shí)現(xiàn)的 CSS 語句。
- div {
- position:fixed;
- }
- @supports (position:sticky) {
- div {
- position:sticky;
- }
- }
上述 CSS 語句的意思是如果客戶端支持 position:sticky,則采用 position:sticky,否則,就是 position:fixed。
關(guān)于 CSS 特性檢測的深入講解,你可以看看我的這篇文章:深入探討 CSS 特性檢測 @supports 與 Modernizr[4]
另外一種常見的條件語句就是媒體查詢,這個大家還是比較熟悉的。
如果當(dāng)前設(shè)備滿足一種什么條件,則怎么樣怎么樣。
- article {
- padding: 4rem;
- }
- @media screen and (min-width: 900px) {
- article {
- padding: 1rem 3rem;
- }
- }
嗯,并且,上述的兩種條件語句可以互相嵌套使用:
- @supports (display: flex) {
- @media screen and (min-width: 900px) {
- article {
- display: flex;
- }
- }
- }
不過,上述兩種畢竟不是嚴(yán)格意義上的我們期待的 if() 語句。
很久之前,社區(qū)就有聲音(css-values - if() function[5]),提議 CSS 規(guī)范中實(shí)現(xiàn) if() 條件語句,類似于這樣:
- .foo {
- --calc: calc(10 * (1vw + 1vh) / 2);
- font-size: if(var(--calc) < 12px, 12px, var(--calc));
- }
可以看到這一語句 if(var(--calc) < 12px, 12px, var(--calc)) 類似于一個三元語句,還是比較好理解的。
然而,上述的條件語句一直沒得到支持的原因,在 scss-values - if() function[6] 可以略窺一二。
原因是 CSS 一直在盡量避免在屬性當(dāng)中產(chǎn)生任意依賴。在 CSS 中,屬性之間本身存在一些隱式依賴,譬如 em 單位長度受到父元素的 font-size 的影響,如果作者能夠添加任意依賴關(guān)系(通過 if() 條件語句),那么將會導(dǎo)致一些問題。
所以,CSS 中的直接 if() 語句一直沒有得到實(shí)現(xiàn)。
最后,我們來看看預(yù)處理器中對 if() 的運(yùn)用,由于 SASS 等預(yù)處理器最終還是要編譯成 CSS 文件,所以 if() 其實(shí)并不太常用。因?yàn)?SASS 中的 if() 也無法實(shí)現(xiàn)類似上述說的 font-size: if(var(--calc) < 12px, 12px, var(--calc)) 這種功能。
在 SASS 中,我認(rèn)為最常用的 if() 可能也就是這種場景:
- @mixin triangle($size, $color, $direction) {
- height: 0;
- width: 0;
- border-color: transparent;
- border-style: solid;
- border-width: $size;
- @if $direction == up {
- border-bottom-color: $color;
- } @else if $direction == right {
- border-left-color: $color;
- } @else if $direction == down {
- border-top-color: $color;
- } @else if $direction == left {
- border-right-color: $color;
- } @else {
- @error "Unknown direction #{$direction}.";
- }
- }
- .next {
- @include triangle(5px, black, right);
- }
上述代碼是對 CSS 實(shí)現(xiàn)三角形的一個封裝,通過傳入的參數(shù),實(shí)現(xiàn)不同方向、顏色、大小的三角形。也就是預(yù)處理器中 if() ,更多的完成一些函數(shù)功能的封裝,方便復(fù)用。
實(shí)際上述的代碼會被編譯成:
- .next {
- height: 0;
- width: 0;
- border-color: transparent;
- border-style: solid;
- border-width: 5px;
- border-left-color: black;
- }
OK,接下來這個是隨機(jī)函數(shù),是我個人在 SASS 等預(yù)處理器中最常用的一個函數(shù)。目前原生 CSS 不支持任意形式的隨機(jī)。
在 CSS 動畫效果中,非常多的因素我們不希望是一成不變的,我們希望的是,一些屬性的值的產(chǎn)生由我們設(shè)定一個基礎(chǔ)規(guī)則,一個范圍中得到,這樣每次刷新都能產(chǎn)生不同的效果。
最常見的莫過于不同的顏色、不同的長度、不同的數(shù)量等等等等。
譬如下面這個使用 CSS 實(shí)現(xiàn)的效果:夏日夕陽圖[7]。
我們通過隨機(jī),每次刷新都可以得到高度/寬度不一樣,位置不一樣的 div 塊,利用隨機(jī)的特性,繪制一幅幅不一樣的效果圖:
DEMO -- 夏日夕陽圖[8]
目前原生 CSS 不支持任意形式的隨機(jī)。使用預(yù)處理器,也只能是在編譯前編寫隨機(jī)函數(shù),SASS 中比較常用的隨機(jī)函數(shù)的一些寫法:
- $r: random(100);
random() 是 SASS 支持的一種函數(shù),上述 $r 就能得到一個 0 ~ 100 的隨機(jī)整數(shù)。
利用 random(),就能封裝出各種隨機(jī)函數(shù),譬如隨機(jī)顏色:
- @function randomNum($max, $min: 0, $u: 1) {
- @return ($min + random($max)) * $u;
- }
- @function randomColor() {
- @return rgb(randomNum(255), randomNum(255), randomNum(255));
- }
- div {
- background: randomColor();
- }
下面這個是社區(qū)對原生 CSS 實(shí)現(xiàn) random() 函數(shù)的一些思考,感興趣的可以猛擊:
[css-values] random() function[9]
簡單搬運(yùn)其中一些比較有意思的觀點(diǎn)。
假設(shè) CSS 原生實(shí)現(xiàn)了 random() 函數(shù),譬如下述這個寫法:
123
456
789
- .foo:hover {
- color: rgb(random(0, 255), 0, 0);
- }
假設(shè)其中 ramdom() 是原生 CSS 實(shí)現(xiàn)的隨機(jī)函數(shù),有一些事情是需要被解決或者得到大家的認(rèn)可的:
上述的問題可以歸結(jié)于如果 CSS 原生支持隨機(jī),隨機(jī)值的持久化和更新是必須要解決的問題??傊?,目前看來,未來 CSS 原生支持隨機(jī)的可能性還是很大的。
工具函數(shù):顏色函數(shù)、數(shù)學(xué)函數(shù)
最后,我們再來看看一些有意思的工具函數(shù)。目前原生 CSS 暫時不支持一些比較復(fù)雜的顏色函數(shù)和數(shù)學(xué)函數(shù)。但是預(yù)處理器都帶有這些函數(shù)。
在我之前的一篇關(guān)于陰影的文章中 --你所不知道的 CSS 陰影技巧與細(xì)節(jié)[10],介紹過一種利用多重陰影實(shí)現(xiàn)立體陰影的效果,譬如我們要實(shí)現(xiàn)下面這個效果:
其中的陰影的顏色變化就借助了 SASS 的顏色函數(shù):
- @function makelongrightshadow($color) {
- $val: 0px 0px $color;
- @for $i from 1 through 50 {
- $color: fade-out(desaturate($color, 1%), .02);
- $val: #{$val}, #{$i}px #{$i}px #{$color};
- }
- @return $val;
- }
- p{
- text-shadow: makelongrightshadow(hsla(14, 100%, 30%, 1));
- }
當(dāng)然,除了上述的兩個顏色函數(shù),SASS 還提供了非常多類似的顏色相關(guān)的函數(shù),可以看看這里:Sass基礎(chǔ)—顏色函數(shù)[11]。
除了顏色,數(shù)學(xué)函數(shù)也是經(jīng)常在 CSS 效果中會需要用到的。
我在這篇文章中 --在 CSS 中使用三角函數(shù)繪制曲線圖形及展示動畫[12],專門講了如何利用 SASS 等預(yù)處理器實(shí)現(xiàn)三角函數(shù),以實(shí)現(xiàn)曲線線條,實(shí)現(xiàn)一些有意思的效果,像是這樣:
當(dāng)然,目前 SASS 也不支持三角函數(shù),但是我們可以利用 SASS function,實(shí)現(xiàn)一套三角函數(shù)代碼:
- @function fact($number) {
- $value: 1;
- @if $number>0 {
- @for $i from 1 through $number {
- $value: $value * $i;
- }
- }
- @return $value;
- }
- @function pow($number, $exp) {
- $value: 1;
- @if $exp>0 {
- @for $i from 1 through $exp {
- $value: $value * $number;
- }
- }
- @else if $exp < 0 {
- @for $i from 1 through -$exp {
- $value: $value / $number;
- }
- }
- @return $value;
- }
- @function rad($angle) {
- $unit: unit($angle);
- $unitless: $angle / ($angle * 0 + 1);
- @if $unit==deg {
- $unitless: $unitless / 180 * pi();
- }
- @return $unitless;
- }
- @function pi() {
- @return 3.14159265359;
- }
- @function sin($angle) {
- $sin: 0;
- $angle: rad($angle);
- // Iterate a bunch of times.
- @for $i from 0 through 20 {
- $sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
- }
- @return $sin;
- }
- @function cos($angle) {
- $cos: 0;
- $angle: rad($angle);
- // Iterate a bunch of times.
- @for $i from 0 through 20 {
- $cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
- }
- @return $cos;
- }
- @function tan($angle) {
- @return sin($angle) / cos($angle);
- }
就目前原生 CSS 而言,在數(shù)學(xué)函數(shù)等方面其實(shí)已經(jīng)做出了非常多的努力,譬如:
等兼容性已經(jīng)逐漸鋪開,可以開始大規(guī)模使用,而類似于
也在規(guī)范CSS Values and Units Module Level 4[13]中被提及定義,相信不久的將來也會逐漸落地。
關(guān)于社區(qū)對數(shù)學(xué)函數(shù)的一些討論,感興趣的也可以看看這里:Mathematical Expressions[14]
好了,綜上總結(jié)一下,就目前而言,我覺得 SASS/LESS 等預(yù)處理器在很多方面還是有有用武之地的,在上述的一些功能原生 CSS 沒有完全落地之前,預(yù)處理器能一定程度上彌補(bǔ) CSS 的不足。
并且,除去上述說的一些我個人認(rèn)為比較重要有意思的功能、函數(shù)之外,預(yù)處理器其它一些核心功能,譬如 extend、mixins 等也能有效的提升開發(fā)時的效率。
所以,在未來的一段時間內(nèi),我認(rèn)為預(yù)處理器還是能和 CSS 友好共存~
好了,本文到此結(jié)束,希望對你有幫助 ????
[1]Agenda+ to publish FPWD of Nesting:
https://lists.w3.org/Archives/Public/www-style/2021Mar/0019.html
[2]CSS Nesting Module:
https://drafts.csswg.org/css-nesting/
[3]CodePen Demo -- CSS Candles:
https://codepen.io/Chokcoco/pen/jJJbmz
[4]深入探討 CSS 特性檢測 @supports 與 Modernizr:
https://www.cnblogs.com/coco1s/p/6478389.html
[5]css-values - if() function:
https://github.com/w3c/csswg-drafts/issues/3455
[6]scss-values - if() function:
https://github.com/w3c/csswg-drafts/issues/3455
[7]夏日夕陽圖:
https://csscoco.com/inspiration/#/./cssdoodle/sunset
[8]DEMO -- 夏日夕陽圖:
https://csscoco.com/inspiration/#/./cssdoodle/sunset
[9][css-values] random() function:
https://github.com/w3c/csswg-drafts/issues/2826
[10]你所不知道的 CSS 陰影技巧與細(xì)節(jié):
https://github.com/chokcoco/iCSS/issues/39
[11]Sass基礎(chǔ)—顏色函數(shù):
https://www.sass.hk/skill/sass25.html
[12]在 CSS 中使用三角函數(shù)繪制曲線圖形及展示動畫:
https://github.com/chokcoco/iCSS/issues/72
[13]CSS Values and Units Module Level 4:
https://drafts.csswg.org/css-values-4/#exponent-funcs
[14]Mathematical Expressions:
https://drafts.csswg.org/css-values/#math

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流