[FE201] SASS 結構化、模組化


Posted by s103071049 on 2021-07-09

CSS 開發上的問題

  1. CSS 全域,會互相干擾。舉例來說 : style.css ,與 normalize.css 同時引入 index.html 會無法清楚區辨是誰造成的效果。
  2. 沒有變數(現在有 css variable),沒有變數的時候就必須透過搜尋替代進行調整。
  3. 沒有辦法組合,只能透過不同選擇器來做到共用樣式的部分。

因為上述的問題,會讓樣式維護變得很複雜,所以可以將寫程式的方式用在處理樣式嗎 ?

可以的,透過 css 預處理器

甚麼是 css 預處理器

css 預處理器使開發者可以撰寫一個類似 css 的語言,透過這個語言保留了程式語言的特色(變數、函式),寫好後透過預處理器編譯成瀏覽器看得懂的 css。如此一來,就不用在乎 css 原先的樣式,因為預處理器就像翻譯機一樣,會幫我們翻成 css。

在 css 之前發生的事情叫做預處理器,在有了 css 之後發生的事情叫做後處理器。可以同時使用,兩者的區別在於流程上一前一後。

後處理器通常是加工既有的 css,我們可能有些特別的屬性,因為瀏覽器不支援等等的,需要被加上一些東西進行加工。

Sass 提供的功能

一、參數與結構化

1. 巢狀
2. 變數

二、模組化

1. import
2. extend
3. function
4. mixin

三、自動化

1. condition
2. loop

Sass 環境設置

不要在全域安裝,就將 g 拿掉 npm install -g sass,雖然是 sass 但也支援 scss。差別主要在 scss 有大括號、分號,sass 則是靠縮排、空格去做辨識。

sass 不是 css,我們將它編譯成 css,所以在 index.html 引入的還是 css。

h1
  color:red

一次性的編譯 : sass input.sass output.css,編譯過後除了 css 檔案外還有 css.map 檔 (source map 的功能就是將產生出的檔案對應到我們開發的檔案,他會將 input.sass 跟 output.css 去做對應)

sass --watch input.sass output.css,watch 模式類似監視,當我監視到 input.sass 有修正(存檔),我就再做一次編譯的動作。

開發完進行壓縮,compress 在 production 模式下再使用。npx sass --style=compressed input.sass output.css

Note

npx 的語法 : 在專案資料夾找套件,而非到全域找。

一、Sass 結構化 - 變數與巢狀

每次開發,先執行 sass 的 watch 模式。

html 原本就有結構存在,dom tree

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="output.css">
  <title>Document</title>
</head>
<body>
  <section class="section">
    <h1 class="section__title">色票</h1>
    <div class="section__wrapper">
      <div class="color color-primary"></div>
      <div class="color color-secondary"></div>
      <div class="color color-warning"></div>
      <div class="color color-text"></div>
      <div class="color color-background"></div>
    </div>
  </section>
</body>
</html>

css 的寫法看不太出結構

.section .section__title {}
.section .section__wrapper {}

透過 sass,結構一清二楚

.section 
  width: 100%
  height: 50%
  padding: 2rem
  border-bottom: 1px solid blue
  .section__title
    text-align: center
  .section__wrapper
    display: flex
    justify-content: center
    align-items: center

& 表示重複上一層選擇器的字串,結合 bem 我們可以從命名上就看出結構。以顏色命名為例,命名方式可以從功能面或是從色彩面著手,最好的命名方式是與設計部門進行協調。

sass 編寫

$primary: blue
$secondary: red
$warning: yellow
$text: green
$background: orange
.section 
  width: 100%
  height: 50%
  padding: 2rem
  border-bottom: 1px solid blue
  &__title
    text-align: center
  &__wrapper
    display: flex
    justify-content: center
    align-items: center
.color 
  width: 50px
  height: 50px
  margin: 10px
  background: black
  &-primary
    background: $primary
  &-secondary
    background: $secondary
  &-warning
    background: $warning
  &-text
    background: $text
  &-background
    background: $background

二、Sass 模組化 - import, extend, mixin 與 function

import

可以將 sass 拆裝成很多檔案,他們之間不會互相影響

模組化就是將一些常見的功能打包起來,封裝引入或組合。

第一個最常用來管理的部分就是變數,如 : _variables.sass,加底線是 sass 的命名慣例。

@import 路徑(可以不加 .sass)

extend and mixin

可以想像成 object 或是大一點的變數,現在不想用共同的 class 做管理。

  <section>
    <h1 class="section__title">按鈕</h1>
    <div class="section__wrapper">
      <div class="btn-primary">click me</div>
      <div class="btn-secondary">click me</div>
      <div class="btn-warning">click me</div>
    </div>
  </section>

一、extend

先用 % 將他變成模板 template

%btn
  padding: 1rem 2rem
  color: $background
  font-size: 1.2rem
  margin: 1rem
  transition: .1s

.btn
  &-primary
    @extend %btn
  &-secondary
    @extend %btn
  &-warning
    @extend %btn

會發現他都以逗號分隔且套入 btn 的樣式

.btn-warning, .btn-secondary, .btn-primary {
  padding: 1rem 2rem;
  color: orange;
  font-size: 1.2rem;
  margin: 1rem;
  transition: 0.1s;
}

二、mixin

也可以用 mixin 做到上述相同的事情。

%btn
  padding: 1rem 2rem
  color: $background
  font-size: 1.2rem
  margin: 1rem
  transition: .1s

@mixin btn
  padding: 1rem 2rem
  color: $background
  font-size: 1.2rem
  margin: 1rem
  transition: .1s

.btn
  &-primary
    +btn
  &-secondary
    +btn
  &-warning
    +btn

會發現他幫我們重複貼上三次

.btn-primary {
  padding: 1rem 2rem;
  color: orange;
  font-size: 1.2rem;
  margin: 1rem;
  transition: 0.1s;
}
.btn-secondary {
  padding: 1rem 2rem;
  color: orange;
  font-size: 1.2rem;
  margin: 1rem;
  transition: 0.1s;
}
.btn-warning {
  padding: 1rem 2rem;
  color: orange;
  font-size: 1.2rem;
  margin: 1rem;
  transition: 0.1s;
}

extedn 是用逗號,用 and 的方式告訴 css,這個 class 那個 class 要用甚麼方式去做 render;mixin 就是把這一串複製貼上三次,除此之外 mixin 還可以帶變數,所以因應不同的 class 進行微調就很適合帶 mixin。

舉例來說,我希望按鈕滑過去有一個我指定的顏色,那麼這個功能可以這麼做 :

%btn
  padding: 1rem 2rem
  color: $background
  font-size: 1.2rem
  margin: 1rem
  transition: .1s

@mixin hover-btn($color)
  &:hover
    background: $color

.btn
  &-primary
    @extend %btn
    +hover-btn($primary)
  &-secondary
    @extend %btn
    +hover-btn($secondary)
  &-warning
    @extend %btn
    +hover-btn($warning)
.btn-warning, .btn-secondary, .btn-primary {
  padding: 1rem 2rem;
  color: orange;
  font-size: 1.2rem;
  margin: 1rem;
  transition: 0.1s;
}

.btn-primary:hover {
  background: blue;
}
.btn-secondary:hover {
  background: red;
}
.btn-warning:hover {
  background: yellow;
}

另外,一些常見的功能也可以透過 mixin 進行管理,但是宣告的東西要放在前面,比較常見的做法是開一個檔案叫做 _mixin.sass 將一些常見的 mixin 放到這,再 import 進來做管理。

@mixin flex-center
  display: flex
  justify-content: center
  align-items: center

.section 
  &__wrapper
    +flex-center
.section__wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

小結、

extend 是用來處理共同的樣式,mixin 的變數的局部置換可以很好地來打包功能

function

function 跟 mixin 很像,但 function 可以回傳數值。

@function letter-spacing($font-index)
  @return $font-index/10 * 0.2 rem

@mixin hover-btn($color, $font-index)
  &:hover
    background: $color
    letter-spacing: letter-spacing($font-index)

.btn
  &-primary
    @extend %btn
    +hover-btn($primary, 1)
  &-secondary
    @extend %btn
    +hover-btn($secondary, 3)
  &-warning
    @extend %btn
    +hover-btn($warning, 100)

mixin 適用在一組的功能下,function 適合在一堆屬性下做運算。function 很多時也會獨立成一個檔案引入,我們也會將 function 放在 mixin。


#sass-結構化與模組化







Related Posts

[Note] Node.js + express: Server & Routing

[Note] Node.js + express: Server & Routing

Javascript - Object vs Map

Javascript - Object vs Map

ES5 沒有 class 那替代方法是?

ES5 沒有 class 那替代方法是?


Comments