TechBridge 技術共筆部落格

var topics = ['Web前後端', '行動網路', '機器人/物聯網', '數據分析', '產品設計', 'etc.']

Sass/SCSS 簡明入門教學


Sass/SCSS 簡明入門教學

Sass/SCSS 簡介

Sass is an extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more. It’s translated to well-formatted, standard CSS using the command line tool or a web-framework plugin.

Sass(Syntactically Awesome StyleSheets)是一種 CSS 的擴充,是為 CSS 的超集合(透過編譯會 compiled 成傳統 CSS,讓瀏覽器可以閱讀)。使用 Sass 的出現是為了解決在大型專案時傳統 CSS 會遇到的重複、可維護性差等問題(新增了 nested rules, variables, mixins, selector inheritance 等特性)。讓開發者可以撰寫簡潔、富語意(expressive)、重複性佳(reusable)、可維護性佳和可延展性佳的 CSS 程式碼。
gem install sass

Sass 的語法分為新的 SCSS (Sassy CSSSass 3,檔案名稱為 *.scss) 和舊的 SASS(向 Haml取經,具備不使用大括弧格式、使用縮排,不能直接使用 CSS 語法、學習曲線較高等特性,檔案名稱為 *.sass)。由於新的 SCSS 語法是 CSS3 的超集合,所以傳統的 CSS3 檔案就算直接複製過來也不會出錯,學習曲線相對較緩,因此我們將使用 SCSS 語法。

關於兩者比較的補充可以參考這篇文章 What’s the difference between SCSS and Sass?

SASS 初體驗

在開始介紹 SASS 特性之前,我們先來學習如何將 Sass 轉譯成 CSS。

首先,先按照官網先行安裝 Sass,接著在專案資料夾建立一個 main.scss 檔案,檔案內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 引用
@import url(https://fonts.googleapis.com/css?family=Pacifico);
//Add variables here:

h1 {
font-family: Roboto, sans-serif;
text-align: center;
}

.banner {
font-family: 'Pacifico', cursive;
height: 400px;
background-image: url("lemonade.jpg");
}

.container {
text-align: center;
font-family: 'Pacifico', cursive;
}

在終端機下以下指令進行轉譯:

1
2
// sass 指令 欲轉譯檔案 輸出的檔案
sass main.scss main.css

此時你就會看到資料夾中多了 main.cssmain.css.map 兩個檔案,前者是轉譯過後的 CSS 檔案,後者是方便使用瀏覽器除錯工具除錯時連結原檔案和轉譯檔案,方便除錯。

  1. Variables:變數可以用來儲存值,方便重複利用

    有些時候 Variables,這時候若能使用變數儲存重複使用的值可以增加重用性。在 Sass 中我們使用 $ 來表示變數,變數的資料型態可以是 Numbers(可以有單位或無單位)、Strings、Booleans、null 值(視為空值),甚至可以使用 Lists、Maps 來。

    變數的使用:

    1
    2
    3
    4
    $translucent-white: rgba(255,255,255,0.3);
    p {
    background-color: $translucent-white;
    }

    Lists 可以空格或加逗號分隔屬性值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $font-style-2: Helvetica, Arial, sans-serif;
    $standard-border: 4px solid black;

    p {
    border: $standard-border;
    }

    // maps key:value
    $font-style-2: (key1: value1, key2: value2);
  2. Nesting:降低父元素重複性

    轉譯前:

    1
    2
    3
    4
    5
    6
    .parent {
    color: blue;
    .child {
    font-size: 12px;
    }
    }

    轉譯後:

    1
    2
    3
    4
    5
    6
    7
    .parent {
    color: blue;
    }

    .parent .child {
    font-size: 12px;
    }

    在 Nesting 中不僅只有 child selectors 可以使用,還可以使用在相同的 Properties 上:

    1
    2
    3
    4
    5
    6
    7
    .parent {
    font : {
    family: Roboto, sans-serif;
    size: 12px;
    decoration: none;
    }
    }

    轉譯後:

    1
    2
    3
    4
    5
    .parent {
    font-family: Roboto, sans-serif;
    font-size: 12px;
    font-decoration: none;
    }
  3. Mixins:降低 pseudo 元素撰寫的重複性,如:::before::after:hover,在 Sass 中使用 & 代表父元素

    轉譯前:

    1
    2
    3
    4
    5
    .notecard{ 
    &:hover{
    @include transform (rotatey(-180deg));
    }
    }

    轉譯後:

    1
    2
    3
    .notecard:hover {
    transform: rotatey(-180deg);
    }

    重用群組的 CSS,例如跨瀏覽器的 prefix,使用 @include 加入群組:

    轉譯前:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @mixin backface-visibility {
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    }
    .notecard {
    .front, .back {
    width: 100%;
    height: 100%;
    position: absolute;

    @include backface_visibility;
    }
    }

    轉譯後:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .notecard .front, .notecard .back {
    width: 100%;
    height: 100%;
    position: absolute;

    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    }

    @mixin 也可以透過 @include 使用參數,也可以使用預設值:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @mixin backface-visibility($visibility:hidden) { //Add an argument
    backface-visibility: $visibility;
    -webkit-backface-visibility: $visibility;
    -moz-backface-visibility: $visibility;
    -ms-backface-visibility: $visibility;
    -o-backface-visibility: $visibility;
    }

    .front, .back {
    @include backface-visibility(hidden);
    }

    有時我們也需要處理參數複雜的情形,此時可以使用 Lists、Maps 資料型態當輔助:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @mixin stripes($direction, $width-percent, $stripe-color, $stripe-background: #FFF) {
    background: repeating-linear-gradient(
    $direction,
    $stripe-background,
    $stripe-background ($width-percent - 1),
    $stripe-color 1%,
    $stripe-background $width-percent
    );
    }

    使用 Maps 資料格式存欲傳入變數:

    1
    2
    3
    4
    5
    6
    $college-ruled-style: ( 
    direction: to bottom,
    width-percent: 15%,
    stripe-color: blue,
    stripe-background: white
    );

    變數使用 ... 進行傳遞:

    1
    2
    3
    4
    5
    .definition {
    width: 100%;
    height: 100%;
    @include stripes($college-ruled-style...);
    }

    還有種情況是參數傳入當作字串(String interpolation):

    轉譯前:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 使用 #{$file} 接收
    @mixin photo-content($file) {
    content: url(#{$file}.jpg); //string interpolation
    object-fit: cover;
    }

    .photo {
    @include photo-content('titanosaur');
    width: 60%;
    margin: 0px auto;
    }

    轉譯後:

    1
    2
    3
    4
    5
    .photo { 
    content: url(titanosaur.jpg);
    width: 60%;
    margin: 0px auto;
    }

    更可以搭配 Nesting 使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @mixin hover-color($color) {
    &:hover {
    color: $color;
    }
    }

    .word {
    @include hover-color(red);
    }
  4. Functions

    在 Sass 內建一些好用 functions 可以簡單設定色相、漸層,例如:adjust-hue($color, $degrees)fade-out

    1
    $lagoon-blue: fade-out(#62fdca, 0.5);

    更多內建 Functions 可以參考這邊

  5. Operations:透過加減乘除和取餘數等運算子可以方便運算所需的屬性值

    顏色加法:

    1
    2
    3
    4
    5
    6
    7
    $color: #010203 + #040506;
    /*
    01 + 04 = 05
    02 + 05 = 07
    03 + 06 = 09
    color: #050709;
    */

    // 使用上需要注意:

    1
    2
    3
    4
    width: $variable/6; //division
    line-height: (600px)/9; //division
    margin-left: 20-10 px/ 2; //division
    font-size: 10px/8px; //not division

    也可以使用 @each 語法迭代 list 內容:

    1
    2
    3
    4
    5
    6
    7
    $list: (orange, purple, teal);

    @each $item in $list {
    .#{$item} {
    background: $item;
    }
    }

    使用 @for 迭代,並加入條件判斷:

    1
    2
    3
    4
    5
    6
    7
    8
    @for $i from 1 through $total {
    .ray:nth-child(#{$i}) {
    background: adjust-hue(blue, $i * $step);
    //
    width: if($i % 2 == 0, 300px, 350px);
    margin-left: if($i % 2 == 0, 0px, 50px);
    }
    }
  6. @include 引用:可以引入其他 Sass、SCSS 檔案:

    我們通常使用 Partials 去處理特定功能,方便管理和維護。以下是引用 _variables.scss 檔案範例,其中檔名前的 _ 表示引用前要先 compile:

    1
    @import "variables";
  7. @extend 共用:

    編譯前:

    1
    2
    3
    4
    5
    6
    7
    8
    .lemonade {
    border: 1px yellow;
    background-color: #fdd;
    }
    .strawberry {
    @extend .lemonade;
    border-color: pink;
    }

    轉譯後:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .lemonade, .strawberry {
    border: 1px yellow;
    background-color: #fdd;
    }

    .strawberry {
    @extend .lemonade;
    border-color: pink;
    }

    搭配 Placeholders 使用:

    轉譯前:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a%drink {
    font-size: 2em;
    background-color: $lemon-yellow;
    }

    .lemonade {
    @extend %drink;
    //more rules
    }

    轉譯後

    1
    2
    3
    4
    5
    6
    7
    8
    a.lemonade {
    font-size: 2em;
    background-color: $lemon-yellow;
    }

    .lemonade {
    //more rules
    }
  8. @mixin@extend 比較

    轉譯前:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @mixin no-variable {
    font-size: 12px;
    color: #FFF;
    opacity: .9;
    }

    %placeholder {
    font-size: 12px;
    color: #FFF;
    opacity: .9;
    }

    span {
    @extend %placeholder;
    }

    div {
    @extend %placeholder;
    }

    p {
    @include no-variable;
    }

    h1 {
    @include no-variable;
    }

    轉譯後:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    span, div{
    font-size: 12px;
    color: #FFF;
    opacity: .9;
    }

    p {
    font-size: 12px;
    color: #FFF;
    opacity: .9;
    //rules specific to ps
    }

    h1 {
    font-size: 12px;
    color: #FFF;
    opacity: .9;
    //rules specific to ps
    }
  9. Sass 資料夾結構

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    sass/
    components/
    _buttons.scss
    helpers/
    _variables.scss
    _functions.scss
    _mixins.scss
    layout/
    _grid.scss
    _header.scss
    _footer.scss
    pages/
    _home.scss
    _contact.scss

總結

以上就是 Sass/SCSS 簡明入門教學,在這篇文章中我們大致上介紹了 Sass 使用語法。除了 Sass 外,目前市面上還有許多 CSS 的變形,包括語法較易學的 LESS、元件化思考的 CSS in JS、主要解決全域問題和模組引用的 CSS Modules,取經於 JavaScript Task Runner 的 PostCSS 、網格樣式表單 GSS 等,這些最終都是要解決傳統 CSS 維護不易、重用性低下等問題。事實上,有些人覺得使用 preprocessor 較好維護,有些人認為每次都要編譯很麻煩,至於要選擇哪一種 CSS preprocessor 或是根本不使用,取決於團隊的內部規範和討論。俗話說後端一天,前端一年,說不定現在選邊站的技術,下個月就不流行了呢。

延伸閱讀

  1. Sass & Susy教學手冊
  2. learn-sass
  3. CSS Modules 用法教程
  4. 如何從 SASS 無痛轉移到 POSTCSS
  5. Using PostCSS Together with Sass, Stylus, or LESS
  6. [心得] 什麼是 postcss?
  7. 聊聊 CSS 預處理器,LESS、Sass、Stylus 及 postCSS

關於作者:
@kdchang 文藝型開發者,夢想是做出人們想用的產品和辦一所心目中理想的學校。A Starter & Maker. JavaScript, Python & Arduino/Android lover.:)

喜歡我們的文章嗎?歡迎分享按讚給予我們支持和鼓勵!





訂閱 TechBridge Weekly 技術週刊,每週發送最精華的技術開發、產品設計的資訊給您



TechBridge Weekly 技術週刊編輯團隊

TechBridge Weekly 技術週刊團隊是一群對用技術改變世界懷抱熱情的團隊。本技術共筆部落格初期專注於Web前後端、行動網路、機器人/物聯網、資料科學與產品設計等技術分享。This is TechBridge Weekly Team Tech Blog, which focus on web, mobile, robotics, IoT, Data Science technology sharing.

關於我們 / 技術日報 / 技術週刊 / 粉絲專頁 / 訂閱RSS

留言討論