CSS 開發上的問題
- CSS 全域,會互相干擾。舉例來說 : style.css ,與 normalize.css 同時引入 index.html 會無法清楚區辨是誰造成的效果。
- 沒有變數(現在有 css variable),沒有變數的時候就必須透過搜尋替代進行調整。
- 沒有辦法組合,只能透過不同選擇器來做到共用樣式的部分。
因為上述的問題,會讓樣式維護變得很複雜,所以可以將寫程式的方式用在處理樣式嗎 ?
可以的,透過 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。