聲明 本篇內容梳理自以下幾個來源: "Github:smyhvae/web" "Bootstrap網站的 less 文檔" "Sass中文網" 感謝大佬們的分享。 正文 CSS預處理(less&Sass) CSS預處理 什麼是 CSS 預處理?為什麼要有 CSS 預處理? 這裡就講講這兩個問題,寫過 ...
聲明
本篇內容梳理自以下幾個來源:
感謝大佬們的分享。
正文-CSS預處理(less&Sass)
CSS預處理
什麼是 CSS 預處理?為什麼要有 CSS 預處理?
這裡就講講這兩個問題,寫過 CSS 應該就會比較清楚,雖然我才剛入門,但在寫一些練手時就已經有點感覺了:寫 CSS 後,很難維護,維護基本要靠註釋來,而且由於 HTML 文檔中標簽的嵌套層次複雜,導致寫 CSS 的選擇器時也很費勁,尤其是在後期為某部分標簽新增樣式時,總會不知道到底應該在 CSS 文件中哪裡寫這個選擇器,這個選擇器是否會與前面衝突。
最有感覺的一點是,CSS 代碼基本沒法復用,一個頁面一份 CSS,每次都需要重寫,只是很多時候,可以直接去舊的裡面複製粘貼。
有這麼些問題是因為 CSS 本身並不是一門編程語言,它只是一個標記語言,靜態語言,不具備編程語言的特性,所以寫容易,但維護會比較難。
這個時候,CSS 預處理器就出現了,其實應該是說 Sass 和 Less 這類語言出現了。
Sass 和 Less 這類語言,其實可以理解成 CSS 的超集,也就是它們是基於 CSS 原本的語法格式基礎上,增加了編程語言的特性,如變數的使用、邏輯語句的支持、函數等。讓 CSS 代碼更容易維護和復用。
但瀏覽器最終肯定是只認識 CSS 文件的,它並無法處理 CSS 中的那些變數、邏輯語句,所以需要有一個編譯的過程,將 Sass 或 Less 寫的代碼轉換成標準的 CSS 代碼,這個過程就稱為 CSS 預處理。
所以,CSS 預處理器其實只是一個過程的稱呼,主要工作就是將源代碼編譯並輸出標準的 CSS 文件,而這個源代碼可以用 Sass 寫,也可以用 Less,當然還有其他很多種語言。
那麼,到底哪一種語言好,我還沒能力來討論,反正存在即有理,每種語言總它的優缺點、總有它的適用場景。
下麵,主要就來介紹下其中的兩種語言:Less 和 Sass。
我覺得,掌握 CSS 預處理的關鍵,其實也就兩點,一是掌握語言的語法、二是清楚怎麼編譯成標準的 CSS 文件;語法基本都不會很難,編譯一般需要配置一些環境,因為我使用的開發工具是 WebStrom,所以會介紹下 WebStrom 上的配置。
Less
使用
Less 寫的 CSS 文件尾碼名為 .less
,但瀏覽器並不認識 less 文件,所以最後需要轉換成 css 文件,有兩種方式:
- 藉助 less.js,程式運行期間,瀏覽器會自動藉助 less.js 來解析 less 文件內的代碼,轉成 css 標準語法
這種方式,不需要配置任何其他環境,只需要下載 less.js,併在項目中使用即可,但有幾點需要註意:
<head>
<!--link標簽需要設置 rel=stylesheet/less, less.js的載入需要放在所有 link 標簽後面-->
<link rel="stylesheet/less" type="text/css" href="css/src/main.less"/>
<link rel="stylesheet/less" type="text/css" href="css/src/test.less"/>
<script src="js/lib/less.js"></script>
</head>
HTML 文檔通過 link 標簽引入 less 文件時,需要將 link 標簽的 rel 屬性設置為 stylesheet/less,否則無效;
而且,用 <script> 標簽載入 less.js 的代碼需要放在最後,即所有用 link 標簽引入 less 文件的後面,因為 less.js 文件載入成功後就會去將 less 轉成 css 標準樣式,在 <script> 標簽後面才用 link 標簽引入的那些 less 文件就無法被轉換了。
less.js 下載地址:https://github.com/less/less.js/releases
- 藉助 node.js 環境,安裝完 less 後,執行 lessc 命令
第一種方式,雖然便捷,但會讓頁面的渲染多了一個轉換步驟,延長頁面渲染時長,所以,還可以用第二種方式,直接在本地將 less 轉成 css 文件後,項目直接使用轉換後輸出的 css 文件。
假設你已經在電腦上安裝了 node.js 了,如果還沒有,先去網上自行搜索下教程,很多,也很快。
首次使用需要先安裝 less,打開終端,執行下述命令:
npm install -g less
安裝完後,就可以使用 lessc 命令,如:
lessc main.less main.css
這是最簡單的用法,將 main.less 文件編譯輸出 main.css;還有其他高級的用法,比如順便壓縮 css 文件,輸出 .min.css 文件等等。
WebStorm配置
我是比較習慣使用第二種方式,也就是在本地就將 less 文件轉成 css 文件,項目里是直接使用轉換後輸出的 css 文件了,而且我用的開發工具是 WebStrom,所以可以藉助它,省去了每次自己輸命令的操作:
第一步:在項目根目錄下執行 npm init -y
初始化項目,初始化完項目後,根目錄會生成 package.json 文件;
第二步:打開 package.json,在裡面的 scripts 欄位,根據你的項目結構,輸入腳本命令;
第三步:點擊 scripts 旁邊的三角形按鈕,就可以自動執行腳本命令,完成轉換工作;
第四步:(可選)如果嫌每次都需要自己手動點擊按鈕麻煩,可以將這項工作添加進 File Watcher 功能中,每次文件改動就會自動執行腳本命令,完成轉換,具體參考上一篇,或者自行搜索,很簡單。
這是例子的項目結構:
src 目錄中存放 less 文件,dist 目錄中存放轉換後輸出的 css 文件,所以,我的 package.json 里的腳本命令如下:
具體的腳本命令可根據實際需求,實際項目結構,自行決定。
語法
好了,清楚了 less 文件的兩種使用方式後,就可以來學習語法了,這樣在學習語法過程中,就可以隨時進行轉換,查看 less 書寫的代碼,最終轉換的 css 代碼是什麼樣的,這樣比較著學習比較容易掌握。
- 變數
通過 @變數名:
來定義變數,通過 @變數名
使用變數,其實本質上是常量了,如:
@width: 10px; /*定義變數*/
@height: @width + 10px; /*使用變數,和邏輯語句*/
#header {
width: @width; /*使用變數*/
height: @height;
}
轉換成 CSS 文件:
/*定義變數*/
/*使用變數,和邏輯語句*/
#header {
width: 10px;
/*使用變數*/
height: 20px;
}
- 註釋
上個例子中,轉換後的註釋也還保留著,這是因為 less 和 css 都支持 /* */
的註釋方式,所以這種會保留,但如果是 //
,這種只有在 less 中支持,css 不支持,那麼這種註釋就不會保留,驗證下:
/*這是註釋1*/
//這是註釋2
轉換成 css 文件:
/*這是註釋1*/
所以,在 less 中使用註釋時,需要註意下,哪些是想保留,哪些是不想保留的。
- Mixins(混合)
也有的文章里翻譯成混入,還有的文章直接保留單詞,不做翻譯,可能是覺得中文翻譯不能夠很好的表達意思吧。
先說有這麼種場景:有時候寫在某個選擇器中的屬性樣式,在其他選擇器中也需要,所以通常是直接將那部分複製粘貼過來使用。
而 less 的 Mixins 允許你在某個選擇器內,直接使用其他選擇器內的屬性樣式,所以中文翻譯才有混合,或混入之說,其實也就是將其他的屬性樣式混合到當前選擇器中。
看個例子就明白了:
.class1 { //類選擇器 class1 的屬性樣式
width: 10px;
height: 20px;
}
.class2(@color: #fff) { //定義了一個模板樣式,類似於函數的作用
background-color: @color;
}
#id1() { //定義了一個模板樣式,類似於函數作用
border: 1px solid #ff22ff;
}
.mian {
.class1; //直接使用其他選擇器定義的屬性樣式
.class2(#f2f); //使用模板樣式,傳入參數
#id1; //使用模板樣式,不傳參時,括弧可省略
}
轉換後的 CSS 文件:
.class1 {
width: 10px;
height: 20px;
}
.mian {
width: 10px;
height: 20px;
background-color: #f2f;
border: 1px solid #ff22ff;
}
可以註意對比源代碼和轉換後的代碼,原本就定義好的基本選擇器,如 .class1
,可直接在其他選擇器內通過 .calss1
將它內部的屬性樣式都複製過來。
也可以在基本選擇器後面加上 ()
括弧,這樣一來,這個就會被當做模板處理,作用類似於函數,可接收參數,使用時就類似於調用函數那麼使用,如果不傳參,調用時也可以將括弧省略。既然是作為函數使用,那麼它們存在的意義就只是被調用,所以轉換後的 CSS 中並不會存在這個函數。
另外,有的文章中,對 Mixins 的解釋是說,在 class 中使用 class,但上面的例子中也測試了,class 中也是可以使用其他 id 選擇器的屬性樣式的,所以應該不僅限於 class 類選擇器,但不能用於組合選擇器中。
- 命名空間
我對於命名空間的理解:屬於 less 自己的命名空間,也就是這些代碼並不會在轉換後的 CSS 文件中出現,因為它只屬於 less。
所以,其實也就是上述例子中,類似函數存在的那些模板選擇器,當在書寫選擇器時,在其後面增加 ()
括弧,則表示這個選擇器只屬於 less 的命名空間,轉成 CSS 後並不會出現。k
- 嵌套
在寫 CSS 時,組合選擇器經常寫得很複雜,因為 HTML 里的標簽嵌套層次本身就很複雜,而且組合選擇器寫完也不是能夠很明顯的表示出它的目的,所以 less 允許依據 HTML 中的嵌套層次來書寫,不用去記那麼多組合選擇器的規則,如:
body {
font-size: 16px;
.content {
.banner {
ul {
img {
width: 700px;
height: 300px;
&:hover {
width: 800px;
height: 300px;
}
}
}
}
}
}
轉換成 CSS 文件:
body {
font-size: 16px;
}
body .content .banner ul img {
width: 700px;
height: 300px;
}
body .content .banner ul img:hover {
width: 800px;
height: 300px;
}
也就是,子孫後代的組合選擇器規則可以不用去記,直接根據 HTML 文檔中標簽的嵌套層次來書寫即可,這樣便於後期維護,如果要對某個標簽新增某些樣式,也知道該去哪裡找。
有一點需要註意的是,類似 a:hover
這種偽類選擇器,需要加一個 &
符號。
- 運算
less 允許在代碼中進行一些簡單的加、減、乘、除基本運算,結合變數的使用,可進行一些字體、顏色等的動態運算效果。
@border: 1px;
@color: #fff;
#header {
color: @color * 0.5;
border-width: @border @border*2 @border*3 @border*4;
}
轉換成 CSS 後:
#header {
color: #808080;
border-width: 1px 2px 3px 4px;
}
通常,變數和運算都是用於對顏色、大小等進行計算。
- 內置函數
less 內置了一些基礎函數,可用於轉換顏色、處理字元串、算術運算等,這裡列舉一些函數:
color("#aaa"); //輸出 #aaa, 將字元串的顏色值轉換為顏色值
image-size("file.png"); //輸出 => 10px 10px,獲取圖片文件的寬高信息
//image-with("file.png"); image-height("file.png"); 獲取圖片文件寬高
convert(9s, "ms"); //輸出 => 9000ms,單位換算,例如對 m,cm,mmin,pt,pc的換算
@size: if((true), 1px, 0px); //if函數,第一個參數為條件,滿足則返回第二個參數,不滿足返回第三個參數
if(not (true), 1px, 0px); //非語句, not
if((true) and (true), 1px, 0px); //邏輯與語句, and
if((false) or (true), 1px, 0px); //邏輯或語句, or
//處理數組
@list: "banana", "tomato", "potato", "peach";
length(@list); // 輸出 => 4
extract(@list, 3); //輸出 => potato,註意第一個不是從 0 開始計算
//類型判斷
isnumber(#ff0); // false
isstring("234"); // true
iscolor(#ff0); // true
isXXX
...
內置函數很多,用途也很多,覆蓋了基本算術運算、邏輯語句、顏色計算、字元串處理等等,需要用時再查手冊吧。
- 作用域
作用域很好理解,就是類似 JavaScript 中的變數作用域,因為在 less 中都是通過 @變數名:
來定義變數的,後定義的會覆蓋掉前定義的,但當在不同嵌套層次中定義同一變數時,就存在局部變數和外部變數之分,內部變數並不會覆蓋掉外部變數。
而且,less 的變數定義也有類似 JavaScript 中的提前特性,如:
@var: red;
#aaa {
color: @var; // yellow,因為後面定義的 @var:yellow 將 @var:red 覆蓋掉了
}
#page {
#header {
color: @var; // white,內部變數不影響外部變數
}
@var: white;
}
@var: yellow;
#ppp {
color: @var; //yellow
}
看看轉換成 CSS 後:
#aaa {
color: yellow;
}
#page #header {
color: white;
}
#ppp {
color: yellow;
}
- import(導入)
如果某份 less 文件是可以復用的,那麼可以使用 @import
命令將其全部引入使用。
@import "main";
最後在 test.css 里會匯合 main.less 里的代碼。
以上,只是介紹 less 的基礎語法,還有更多詳細、複雜的語法用途,需要時再翻閱文檔吧。
Sass(Scss)
Sass 相比於 Less 功能會更強大,但也更複雜。
Sass 和 Scss 本質是一家,Sass 早期版本的文件尾碼名是 .sass
,從 Sass 3 之後,因為修改了一些特性語法,Sass 更加強大且易使用,從這個版本之後的文件尾碼名改成了 .scss
,所以 Scss 其實 Sass 的新版本的稱呼,但兩者本質上沒太大區別。
Scss 是基於 Sass 的語法基礎上,修改了一部分的語法。比如早期的 Sass 是通過換行和縮進如:
#sidebar
width: 30%
background-color: #faa
這種語法格式跟 CSS 不一致,讓使用者會很不習慣,Scss 之後就換成用分號和括弧了:
#sidebar {
width: 30%;
background-color: #faa;
}
使用
Sass 不像 Less 一樣可以直接藉助 less.js 來進行轉換,它是基於 Ruby 運行環境,所以電腦上需要先安裝 Ruby,然後才能有辦法將 Sass 文件轉成 CSS。
Ruby 下載地址:https://rubyinstaller.org/downloads/
因為是 exe 文件,下載完直接按提示安裝就可以了,安裝後打開終端,執行 gem 命名安裝 Sass:
gem install sass
安裝完 Sass 後,就可以通過 scss 命令來進行轉換工作了,如:
scss main.scss main.css
上述命令中,scss 換成 sass 也可以,但註意,scss 或 sass 命令是基於 Ruby 環境下運行的命令,因為電腦上已經安裝過 Ruby 了,也通過 Ruby 安裝了 Sass,所以才可以在終端里直接執行 scss 命令。
而類似於 Less 中說到的,WebStrom 可以藉助 package.json 里的 scripts 來手動運行腳本命令,這有個前提,就這些腳本命令是運行在 node.js 環境上的,所以如果你直接將上述 scss 命令配置到 package.json 的 script 里,你會發現,是運行不了的。
要解決這個問題,讓 WebStrom 能夠運行 sass 命令來處理轉換工作有兩種方式:
- 直接去 WebStrom 配置 File Watcher,program 選擇 Ruby 目錄中的 sass.bat 或 scss.bat
這種方式下,每次配置的文件變動時,會自動生成對應的 css 文件,轉換工作會自動實時進行。但如果不習慣這種方式,想要每次編寫完 scss 代碼後,手動來觸發轉換工作,那麼可以選擇第二種方式:
- 通過 npm 命令安裝 sass
在終端里執行 npm install -g sass
,這樣就可以類似配置 less 那樣的步驟來使用 sass 命令了,在 package.json 里配置相關命令,然後手動點擊腳本的運行即可。
但 npm 安裝的 sass 跟在 Ruby 下安裝的 sass 是否有和區別,我不清楚,用段時間,如果有啥問題再來說說。
而且,對於選擇使用 Sass,剛接觸可能會有些困惑,是應該使用哪個尾碼名的文件,命令是該用 sass 還是 scss 來進行轉換,我也有這個困惑,但感覺好像並沒有什麼區別,先試著用段時間,以後熟悉了再來講講。
最後,Sass 雖然有 .sass
和 .scss
兩種尾碼名的文件,但建議使用 .scss
,因為前者的語法跟 CSS 很不一樣,使用起來會有些不習慣,當然如果你有 Ruby 基礎的話,可能會比較喜歡這種。我個人會選擇後者。
語法
語法方面,大部分類似於 Less,但就細節方面可能有些不一樣,還有,支持更多更強大的功能吧。
上面介紹的 Less 的基礎語法、基礎功能,Sass 也基本全部支持,也差不了多少,所以下麵就不一個個來介紹了,詳細的到開頭聲明部分給的中文網鏈接中去查閱即可。
下麵就主要列一些不同的地方:
- 變數
Sass 中的變數用 $變數名:
定義,用 $變數名
使用,其餘跟 Less 差不了多少。
- 作用域
Less 中的變數分局部作用域和全局作用域,但在 Sass 中,不同版本,作用域範圍並不一樣,摘抄一段原文中描述:
Sass 中變數的作用域在過去幾年已經發生了一些改變。直到最近,規則集和其他範圍內聲明變數的作用域才預設為本地。如果已經存在同名的全局變數,則局部變數覆蓋全局變數。從 Sass 3.4 版本開始,Sass 已經可以正確處理作用域的概念,並通過創建一個新的局部變數來代替。
- 條件語句
Less 中並不支持條件語句,當然,可以通過內置函數 if 以及 and,or,not 這些來模擬條件語句。
在 Sass 中是支持條件語句的,但也不是像其他編程語言直接 if 這樣通過保留字來編寫,需要加個 @
符合,如:
@if $support-legacy {
// …
} @else {
// …
}
教程中給了幾條準則要求:
- 除非必要,不然不需要括弧;
- 務必在
@if
之前添加空行; - 務必在左開大括弧(
{
)後換行; @else
語句和它前面的右閉大括弧(}
)寫在同一行;- 務必在右閉大括弧(
}
)後添加空行,除非下一行還是右閉大括弧(}
),那麼就在最後一個右閉大括弧(}
)後添加空行。
另外,教程中也說了:
除非你的代碼中有偏複雜的邏輯,否則沒必要在日常開發的樣式表中使用條件語句。實際上,條件語句主要適用於庫和框架。
其他區別,等用段時間,熟悉了再來講講。
框架-Compass
Sass 有一點比 Less 有優勢的就是,目前有很多穩定且熱門的基於 Sass 編寫的框架庫,比如:Compass、Bourbon 和 Susy 等。
這些框架庫就類似於 jQurey 和 JavaScript 關係,對 Sass 進行了一層封裝,讓編寫 Sass 代碼的人,可以極為簡便的開發,我還沒用過,就不過多介紹了。
大家好,我是 dasu,歡迎關註我的公眾號(dasuAndroidTv),公眾號中有我的聯繫方式,歡迎有事沒事來嘮嗑一下,如果你覺得本篇內容有幫助到你,可以轉載但記得要關註,要標明原文哦,謝謝支持~