前端CSS的工程化——掌握Sass這四大特性就夠了

初遇 CSS,一見鍾情

記得剛碰見css的時候,咱像是見了美人兒同樣,簡直是愛不釋手啊,簡簡單單寫幾行算不上代碼的代碼,就能作出這麼漂亮的東西,這也成了咱前端之路的最初動力。css

然而,隨着項目體量和頁面複雜度的增長,咱很快就發現這美人兒非但不漂亮,並且缺胳膊少腿兒的:html

  • 缺乏模塊系統。模塊系統是軟件工程化的基石,CSS 的這個缺陷對前端項目的工程化管理形成了很大阻力,致使開發大型應用時編碼和維護都異常困難。js 一開始也沒有模塊系統,後來各類輪子頻出,什麼CMD,AMD,UMD全蹦出來了,亂哄哄的,好在 ES6 從語言層面引入了模塊系統才終結了這種亂象,之後 js 的模塊化終於能夠統一了。css 你怎麼很差好向你的好基友 js 學習呢,人家都有了,你還傻了吧唧的一點動靜都沒有。
  • 沒有變量機制。這對控制多個地方會引用到的屬性值很不方便。好比一個顏色值,頁面好多地方用到,設計MM忽然心血來潮把這個值換成了另外一個顏色,我們怎麼辦,ctrl+f 全局替換?萬一換掉了不應換的,或者漏掉了幾個怎麼辦。
  • 嵌套的層級寫法很是蛋疼。常常會出現
    .page .content .left-side .profile .name{};
    .page .content .left-side .profile .age{};

    這種看起來很不爽,寫起來更不爽的寫法。這是程序員最不能忍受的——重複。
  • 複用困難。複用是軟件工程的核心思想,css 不只沒提供模塊系統,並且巧妙地避開了工程化的諸多實踐。更加以爲 css 這門語言設計的跟鬧着玩兒似的。
  • blabla.. 其它的都不是很嚴重啦。

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 帶給我們的四大實用特性,想必你必定已經使用過它們中的一個或幾個。模塊化

1、嵌套寫法

想一想以前我們是怎樣寫原生 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;}

這種嵌套寫法的好處是顯然的:

  • 結構清晰簡潔,而且可與 html 文檔結構對應起來;
  • 減小了大量冗餘重複的選擇器編碼;

2、屬性值的複用——定義變量

變量一直是全部編程語言的標準配置。然而 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值容易的多;
  • 極大地加強了代碼的可維護性,便於局部和全局的樣式風格統一控制;

3、文件級的複用——模塊系統

模塊化是軟件工程的第一要務,是大型項目的必需建築。軟件工程的主要目標就是控制複雜度,這也正是模塊化的目的。經過將一個大型複雜的工程拆解成一個個的小模塊,使得校驗、調試、測試都垂手可得。

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">

好處嘛天然不用多說了:

  • 增刪改模塊之後是 css 本身家的事,別麻煩別人,不用再去動 html 了吼;-
  • 模塊系統使得項目並不會隨着業務複雜度增長而變得更加複雜。增長功能時只須要橫向擴展就好了,不會縱向延伸,從而能始終保證每一個模塊完整而簡單;-

4、展現層的複用——混合指令

混合(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;
}

看到了吧,這種作法簡直「完美」:

  • 抽離公共的樣式片斷,便於多處複用;
  • 將公共的樣式片斷放在單獨的文件裏,便於項目的多個文件複用;
  • 對 html 的使用沒有任何要求,css 本身家的事本身關起門來解決,毫不麻煩別人;

其餘不經常使用且慎用的強大特性

若是熟練合理地運用上面的四大特性,你已是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/elseforwhile 等控制語句。Sass 一樣提供了指令實現:

  • @if
  • @for
  • @each
  • @while

它們一般配合 @function 指令使用,然而功能雖強,卻不經常使用到。畢竟樣式表的功用主要是描述頁面樣式,而不是提供更多控制。所以在這裏不展開研究,感性趣的 戳這裏

小結

Sass 完美彌補了上面原生 CSS 暴露的幾個短板,同時新語法 SCSS 使 CSS 開發者能夠無縫過渡,是 CSS 預處理器中當之無愧的佼佼者。使用 Sass 容易編寫出結構清晰,可複用,易維護的工程樣式文件,這正是工程化的指望。這麼好的東西,速速用起來。

本文主要參考了 Sass 中文網

相關文章
相關標籤/搜索