記得剛碰見css的時候,咱像是見了美人兒同樣,簡直是愛不釋手啊,簡簡單單寫幾行算不上代碼的代碼,就能作出這麼漂亮的東西,這也成了咱前端之路的最初動力。css
然而,隨着項目體量和頁面複雜度的增長,咱很快就發現這美人兒非但不漂亮,並且缺胳膊少腿兒的:html
.page .content .left-side .profile .name{};
.page .content .left-side .profile .age{};
CSS 沒有模塊系統,你當我 @import 是空氣?
CSS 的 @import 規則是能夠在一個 css 文件導入其餘 css 文件,但這貨須要執行到它時才能觸發瀏覽器去下載它所 import 來的 css 文件,致使頁面加載起來特別慢,還不如直接在 裏寫一大坨
標籤的引入效率高,是名副其實的雞肋功能,演員通常的存在,用你一次算我輸。前端
有需求就會有市場,Sass(Syntactically Awesome Style Sheets) 應運而生。程序員
老規矩,先來看看 Sass 官網的原話:編程
Sass 是世界上最成熟、最穩定、最強大的專業級 CSS 擴展語言!瀏覽器
這貨還真是一點也不謙虛,「最成熟,最穩定,最強大」。sass
經過這幾年項目中的實際運用,咱發現這句簡短霸氣的描述其實並無絲毫的浮誇,Sass 的確厲害,徹底能夠 hold 住這三個「最」字,實至名歸。編程語言
什麼是預處理器
預處理器是在程序源文件被編譯以前根據預處理指令對程序源文件進行處理的程序。說白了,預處理器只不過是一個文本替換工具而已。CSS 預處理器則是經過將有特殊語法和指令的源代碼處理成瀏覽器可以使用的 CSS 文件的程序。
是 Sass 仍是 SCSS?
SCSS 是 Sass 3 引入的新語法,語法上徹底兼容原生 CSS,功能上徹底繼承 Sass,能夠說是 CSS 和 Sass 的完美融合。SCSS 之於 Sass 猶如 CSS3 之於 CSS,ES6 之於 JS。因此別糾結,實際上是一個東西啦。ide
接下來就細數 Sass 帶給我們的四大實用特性,想必你必定已經使用過它們中的一個或幾個。模塊化
想一想以前我們是怎樣寫原生 css 的:
.page .content .left-side .profile .name{ font-size: 2rem; } .page .content .left-side .profile .age{ color: red; }
如今使用 scss 能夠這樣寫:
.page{ .content{ .left-side{ .profile{ .name{ font-size: 2rem; } .age{ color: red; } } } } }
編譯後
.page .content .left-side .profile .name{font-size: 2rem;} .page .content .left-side .profile .age{color: red;}
這種嵌套寫法的好處是顯然的:
變量一直是全部編程語言的標準配置。然而 CSS 就沒有,再次證實 CSS 多是一門假語言。好在 Sass 補上了這個短板。
沒有變量以前的代碼(這裏以定義一系列表示成功風格的樣式組件爲例):
.success-bg{ background: #dff0d8; } .success-panel{ .panel-heading{ background: #dff0d8; } .panel-body{ border: 1px solid #dff0d8; } }
使用了變量後的代碼:
$success-color: #dff0d8; .success-bg{ background: $success-color; } .success-panel{ .panel-heading{ background: $success-color; } .panel-body{ border: 1px solid $success-color; } }
使用變量的好處是顯而易見的:
模塊化是軟件工程的第一要務,是大型項目的必需建築。軟件工程的主要目標就是控制複雜度,這也正是模塊化的目的。經過將一個大型複雜的工程拆解成一個個的小模塊,使得校驗、調試、測試都垂手可得。
CSS原生的 @import
提供了一個並無卵用的假模塊系統。Sass 對 @import
進行了拓展,實現了一個真正意義上甚至功能更強大的模塊系統。Sass 選擇對 @import
進行擴展,而不是新建一個指令,可見 import 這個關鍵字的語義之強,JavaScript 模塊系統的關鍵字也是 import
。
沒有模塊系統以前:
<!-- index.html --> <link rel="stylesheet" href="/your/site/common.css"> <link rel="stylesheet" href="/your/site/popup.css"> <link rel="stylesheet" href="/your/site/module_a.css"> <link rel="stylesheet" href="/your/site/site.css">
有了模塊系統以後:
/* site.scss */ @import "common"; @import "popup"; @import "module_a";
<!-- index.html --> <link rel="stylesheet" href="/your/site/site.css">
好處嘛天然不用多說了:
混合(mixin)特別相似於 JavaScript 中的函數,然而 Sass 提供了用於表達式計算的 @function
函數指令,這裏就很差這麼類比了。但其實就是這麼個東西,調用的時候會返回一段樣式。
好比下面一段存在重複樣式的代碼。
複用以前:
.description{ color: red; border: 1px solid #e3e3e3; border-radius: 2px; } .article{ color: #444; border: 1px solid #e3e3e3; border-radius: 2px; }
稍做優化:
.description, .article{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ color: red; } .article{ color: #444; }
彷佛不錯,可是以後再新加相似樣式時,
.description, .article, .style01, .style02{ border: 1px solid #e3e3e3; border-radius: 2px; } . . . .style01{} .style02{}
每次都要改兩個地方,很麻煩,很容易漏,尤爲是將通用樣式分離出來的話更容易出錯。
再作優化:
.grey-border-radius{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ color: red; } .article{ color: #444; }
彷佛好了一點,但這樣的話,html 每一個使用的標籤都須要多加上一個 .grey-border-radius 類。很顯然這是多餘的。這種作法能夠說是「湊合」。
使用 Sass 複用以後:
@mixin grey-border-radius{ border: 1px solid #e3e3e3; border-radius: 2px; } .description{ @include grey-border-radius; color: red; } .article{ @include grey-border-radius; color: #444; }
編譯後的 css 輸出:
.description { border: 1px solid #e3e3e3; border-radius: 2px; color: red; } .article { border: 1px solid #e3e3e3; border-radius: 2px; color: #444; }
看到了吧,這種作法簡直「完美」:
若是熟練合理地運用上面的四大特性,你已是CSS代碼工程化方面的磚家了,所寫出來的代碼必是清晰易維護的。Sass 提供了更多的功能,但對普通開發者來說,上面的四點只要使用熟練,已經徹底夠用了,其餘的可看可不看。下面提供的功能但願你們慎用,有的是出於性能考慮,有的則是從開發維護的角度考慮。尤爲不要爲了秀技術而去使用它們,過猶不及,事緩則圓,此爲中庸之道。
繼承是面向對象程序設計的三大特性之一,這也是爲何說它是語義層複用的緣由。你能夠說一個錯誤信息框繼承了一個信息框,而不能說一個錯誤信息框繼承了一個灰色圓角,雖然也是能夠強行這麼說,但不免有些彆扭哈哈。
好比說下面定義一組信息框的樣式,包括默認,成功和錯誤的樣式。
使用繼承以前:
.msg{ border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success{ color: #4cae4c; } .msg-error{ color: #d43f3a; }
一樣是上面說到的問題,編寫 html 時每一個使用的標籤都須要多加上一個 .msg 類,不少餘。
使用繼承以後:
.msg{ border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success{ @extend .msg; color: #4cae4c; } .msg-error{ @extend .msg; color: #d43f3a; }
編譯後
.msg, .msg-success, .msg-error { border: 1px solid #e3e3e3; background: #dff0d8; } .msg-success { color: #4cae4c; } .msg-error { color: #d43f3a; }
能夠看出,上面的效果使用混合(mixin)也能夠完成。但不一樣的是:繼承拷貝的是選擇器,而混合(mixin)拷貝的是樣式片斷。
使用混合(mixin)仍是繼承(extend)?
你確定覺得既然繼承拷貝的是選擇器,而混合拷貝的是大段的樣式,那固然是優先選擇繼承了。然而偏偏相反,推薦作法是 儘量使用混合(mixin),具體緣由 戳這裏。
這個功能主要用於值的計算,和 JavaScript 中的函數相似。
好比移動端開發時能夠封裝成一個函數用於把 px 轉成 rem。
$baseFontSize: 20; @function px2rem($val) { @return $val/$baseFontSize + rem; } .big-text{ font-size: px2rem(30); }
編譯後:
.big-text { font-size: 1.5rem; }
這樣在拿到設計MM給的視覺稿以後就能夠直接使用 px 進行測量使用了。
控制流即程序語言中的 if/else
,for
,while
等控制語句。Sass 一樣提供了指令實現:
@if
@for
@each
@while
它們一般配合 @function
指令使用,然而功能雖強,卻不經常使用到。畢竟樣式表的功用主要是描述頁面樣式,而不是提供更多控制。所以在這裏不展開研究,感性趣的 戳這裏。
Sass 完美彌補了上面原生 CSS 暴露的幾個短板,同時新語法 SCSS 使 CSS 開發者能夠無縫過渡,是 CSS 預處理器中當之無愧的佼佼者。使用 Sass 容易編寫出結構清晰,可複用,易維護的工程樣式文件,這正是工程化的指望。這麼好的東西,速速用起來。
本文主要參考了 Sass 中文網。