1. 程式人生 > >前端入門23-CSS預處理器(Less&Sass)

前端入門23-CSS預處理器(Less&Sass)

lease 語言 npm 基礎上 應該 過程 tst bst web

聲明

本篇內容梳理自以下幾個來源:

  • Github:smyhvae/web
  • Bootstrap網站的 less 文檔
  • Sass中文網

感謝大佬們的分享。

正文-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),公眾號中有我的聯系方式,歡迎有事沒事來嘮嗑一下,如果你覺得本篇內容有幫助到你,可以轉載但記得要關註,要標明原文哦,謝謝支持~
技術分享圖片

前端入門23-CSS預處理器(Less&Sass)