這幾天摸索了 SASS+SCSS 的寫法,發現有許多的 GitHub 專案,使用它進行開發。
自己進行幾個專案後,編寫速度確實有提升,於是整理出這篇 SASS+SCSS 教學,從 SASS+SCSS 介紹 → 安裝+執行 → 語法 SASS教學 ,進行文章編寫。
不敢說可以從入門到進階,但對 SASS 主觀念的掌握,應該是沒問題的,那我們開始囉 😀 😀
1. SASS+SCSS 介紹
SASS 是一個成熟且穩定的 CSS 預處理器,除了把普通的 CSS 語法強化,它還使用了 SassScript 增加了許多功能,如:變量、嵌套、混合、導入等 .. 功能,在一般專案的編寫或是中大型的專案上,都可以編寫的更加快速。
SASS 會編譯(compiled)程式碼,轉成一般 CSS 形式,讓瀏覽器可以解讀輸出,把頁面呈現出來。
主要包含兩種寫法:分別是舊版的 SASS(縮排語法,副檔名.sass,使用縮排來區分程式碼塊,與 Haml 類似)和新版的 SCSS(塊語法,副檔名.scss,使用和 CSS 相同方式,用大括號分開)。
SCSS 的原型是 SASS,所以都通稱 SASS 也沒問題,只是寫法有些許不同,我們先來看一下:
/** 一般 css 寫法 **/
.nav{
background: #ccc;
}
.nav li {
display: inline-block;
}
.nav li a{
display: block;
padding: 15px;
text-decoration: none;
color: #000;
}
.nav li img{
width: 100%;
}
SASS寫法:採用「 縮進語法(TAB)」的方式,去除了一般 CSS 的括號、分號等 .. 加快編寫流程,有一部分的人喜歡這樣的編寫方式而採用,如下:
/** sass寫法 **/
.nav
background: #ccc
li
display: inline-block
a
display: block
padding: 15px
text-decoration: none
color: #000
img
width: 100%
SCSS寫法:採用「 塊語法(Block)」,一般從 CSS 轉為 SCSS 開發比較無痛,保留了括號、分號等 .. 元素,相對於上面的 SASS 是比較新的編寫方式,學習成本比較低,是目前主流的方式,如下:
/** scss寫法 **/
.nav{
background: #ccc;
li {
display: inline;
a {
display: block;
padding: 15px;
text-decoration: none;
color: #000;
}
img {
width: 100%;
}
}
}
看完上面的程式碼,會發現 SASS 可以協助解決編寫 CSS 常遇到的幾個問題,如:「 重複編寫 」、「 後續維護 」、「 漏寫問題 」等問題 ..,然後加快開發流程,如下:
- 父選擇器,重複編寫:如要擴充頁面樣式,就會不斷的加上 .nav li .. 等父級 class 名稱,比較費工!
- 屬性樣式,重複編寫:常會看到許多 CSS 屬性,是許多區塊都需要用到,在 SASS 沒出來前,每個區塊都需特別寫一遍,現在直接引用即可。
- 後續維護:若哪天需要把 .nav 這個 class 名稱更換,就需全部替換,比較麻煩。
- 漏寫問題:SASS / SCSS 有條理的節省了許多代碼編寫,降低漏寫的Bug。
若想了解更多 SASS & SCSS 差異,也可以 看這篇 stack oveflow 的討論:)
2. 安裝+執行
安裝+執行 SASS 的方式有滿多種,有使用第三方應用程式的,也有直接安裝在本機上的,這邊會建議直接安裝在本機上,比較一勞永逸,這邊列出幾種安裝方式,如下:
1. 使用 Node.js 安裝 $ npm install -g sass
2. 使用 Ruby 安裝 $ gem install compass
3. 使用 Brew 安裝(Mac專用)$ brew install sass
指令執行完成,基本上就安裝好了,若想測試是否安裝成功,可以輸入 $sass -v
看是否有顯示 SASS 版本號,若有的話代表安裝完成 😆 😆
首先在專案資料夾下,生成 index.html 和兩個資料夾 css、sass ,然後在 sass 下面新增一個 style.scss,這支檔是我們開發,主要編寫樣式的檔案。
我們現在要試著把 sass 資料夾裡的 style.scss ,編譯成瀏覽器看的懂的 .css 副檔名型式。
所以下指令把 style.scss 檔案轉譯生成 style.css,並放置在 css 資料夾裡,如下:
$ sass sass/style.scss:css/style.css
如果順利的話,應該會看到「 css 」檔案夾裡,新增了兩個檔案,分別是「 style.css 」和「 style.css.map 」,這邊比較要留意的是 style.css(瀏覽器主要解讀這隻檔)。
- 需留意「 當前路徑 」,這會影響到 style.scss 檔案編譯生成 style.css 的路徑,若不對會報錯唷 😯 😯
- 在 index.html 裡面,記得引入 style.css 檔案( style.scss 不需引入 ),才會有樣式出現唷!
若持續有樣式需新增,每次一編寫完 style.scss 就得執行一次 $ sass sass/style.scss:css/style.css
指令,才能在瀏覽器上看到變化,相信一定會很想撞牆 🙁 🙁
所以這時可以改下另一個指令(加上 --watch
參數,若原有的 style.css / style.css.map 已存在,會自動覆蓋,不存在的話會自動生成新的),如下:
$ sass --watch sass/style.scss:css/style.css
執行後,會發現 sass 已經開始在監聽 style.scss ,若這隻檔案有修改,style.css 變會即時的進行編譯,給瀏覽器做使用,如下影片:
在開發過程中,一個專案可能不只有一個樣式檔,假如有多個檔案需同時進行監聽,這邊提供幾個方式給大家:
1. 重複執行:看有幾個檔案需監聽,就輸入幾次。
$ sass --watch path/to/filename.scss:path/filename.css
2. 一次執行:看有幾個檔案需監聽,一次下指令。
$ sass --watch path/filename1.scss:path/filename1.css path/filename2.scss:path/filename2.css path/filename3.scss:path/filename3.css
3. 指定目錄下全部監聽:監聽 sass 目錄下的 sass/scss 檔案到指定的 css 目錄下(下面指令為兩個資料夾在同一層)
$ sass --watch sass:css
4. 當前目錄下全數監聽,並直接生成 css 檔案。
$ sass --watch .
到了這一步,若順利的話,相信你也學會,如何在編寫 sass/scss 檔案時,指定的 css 檔案可以同步的進行編譯,並讓瀏覽器能夠順利的出現畫面。
個人覺的 sass 學習比較麻煩的就是安裝+執行這個章節,後面就是語法部分,語法就相對簡單明瞭了,原來就有 css 開發經驗的捧有們,相信也可以很快就入手的 😀 😀
接下來,我們開始前進到語法部分囉:)
3. 嵌套
SASS 提供 CSS 語法擴展,如:嵌套功能( Nested Rules ),主要是解決 CSS 編寫過程中,父元素重複編寫問題,可以縮短開發流程、方便後續維護、樣式模組化等.. 優點 🙂 🙂
這是容易入門 SASS教學 的第一步,直接上代碼,我們使用 SASS 編寫樣式,並對比編譯後的 CSS ,如下:
/** 編譯前( sass 語法 ) **/
#main {
width: 200px;
height: 100px;
background: #ddb92a;
.greenbox{
width: 100px;
height: 50px;
background: green;
p, a {
font-size: 20px;
}
}
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
#main {
width: 200px;
height: 100px;
background: #ddb92a;
}
#main .greenbox{
width: 100px;
height: 50px;
background: green;
}
#main .greenbox p, #main .greenbox a{
font-size: 20px;
}
除此之外,常用的屬性也可以進行 CSS「 嵌套屬性 」,比如: font-family
、font-size
、font-weight
,會發現 font
多次出現。
還有常見的 background
系列,比如:background-color
、background-position
、background-size
、background-image
,都可以用嵌套功能,來節省開發時間唷,這邊上代碼,如下 🙂 🙂
/** 編譯前( sass語法 ) **/
.main {
font: {
family: Helvetica, sans-serif;
size: 15em;
weight: bold;
}
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.main {
font-family: Helvetica, sans-serif;
font-size: 15em;
font-weight: bold;
}
到目前,對嵌套功能應該有初步認識了,若之前有看過別人寫的 SASS / SCSS 檔,應該會有種似曾相似的感覺吧 😉 😉
理解了它,接下來我們繼續看 SASS 還有什麼特別的地方,可以讓我們學習的 ..
4. 引用父選擇器 &
如果想在嵌套狀態下,取得外層的父選擇器,那可以使用「 & 」,它會直接抓父選擇器給你用。
常會把它用在,如 CSS 元件狀態: :hover
、:focus
、:hover
、:link
、:visited
等 ..,或是 :before
、:after
,這邊上個代碼,如下:
/** 編譯前( sass語法 ) **/
#main {
display: block;
a {
color: #d0b95b;
&:hover, &:active, &:focus {
color: #a08106;
outline: none;
text-decoration: none !important;
}
}
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
#main {
display: block;
}
#main a {
color: #d0b95b;
}
#main a:hover, #main a:active, #main a:focus {
color: #a08106;
outline: none;
text-decoration: none !important;
}
還有另一種用法,也常常看到,如下:
/** 編譯前( sass語法 ) **/
#main{
&.color-2{
background: red;
&:before{
border: 1px solid #ccc;
}
}
&.color-3{
background: yellow;
&:before{
border: 1px solid blue;
}
}
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
#main.color-2 {
background: red;
}
#main.color-2:before {
border: 1px solid #ccc;
}
#main.color-3 {
background: yellow;
}
#main.color-3:before {
border: 1px solid blue;
}
能抓到父選擇器,是不是開發起來也方便多了呢?
一開始看到別人編寫的 SASS 時,覺得「 & 」的寫法滿酷的,後來才懂 .. 原來是這樣運作呀 😀 😀
5. 變量
在我們實際編寫 CSS 的過程中,常會遇到多次相同的顏色、字型、字體大小等 .. 重複出現。
重複出現是好事,因為只要複製+貼上就好了 .. 但假如遇到哪天設計師 / 客戶,需要修改就 ..(因為全都需要更改 😯 😯 )
所以 SASS 可以協助我們解決這問題,就如同 JS 變量邏輯一樣,只需改最源頭的變量即可,其他所有引用該變量的地方,值都會自動更改。
SASS 中使用 $
進行變量聲明,支持 7 種主要數據類型:
- 數字(如:
1
,1.5
,20px
) - 字符串,帶引號和不帶引號(如:
"foo"
,'foo'
,foo
) - 顏色(如:
red
,#28b0b4
,rgba(0, 0, 0, 0.5)
) - 布爾值(如:
true
,false
) - 空值(如:
null
) - 值列表(list),用空格或逗號分開(如:
2em 1em 0 1em
、Helvetica, Arial
) - maps:從一個值映射到另一個(如:
(key1: value1, key2: value2)
)
這邊來對比一下,使用 SASS 開發的編譯前( SASS 語法 ) & 編譯後( 轉為 CSS 語法輸出 )的程式碼,如下:
/** 編譯前( sass 語法 ) **/
$bnr-font: Helvetica, sans-serif;
$bnr-color: #494947;
.banner1 p{
font-family: $bnr-font;
color: $bnr-color;
padding: 10px 15px;
letter-spacing: 0.2em;
}
.banner2 p{
font-family: $bnr-font;
color: $bnr-color;
margin: 15px;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.banner1 p{
font-family: Helvetica, sans-serif;
color: #494947;
padding: 10px 15px;
letter-spacing: 0.2em;
}
.banner2 p{
font-family: Helvetica, sans-serif;
color: #494947;
margin: 15px;
}
如此一來,當哪天收到需要更改某通用按鈕顏色、通用字體字型 .. ,就可以直接更改變量即可,是不是很方便 😆 😆
6. 引入
SASS 擴展了 CSS 的 @import
功能,允許在文件內導入其他的 SASS 或 SCSS 子文件。
在文件進行編譯後,被導入的 SASS 或 SCSS 子文件,會全部合併到同一個 CSS 文件,然後呈現出來。
常見的 .sass
或 .scss
導入
這邊展示一下基本用法,我們把 _reset.scss
導入到 main.scss
中,直接上代碼:
/** 編譯前( sass 語法 ) **/
/** _reset.scss **/
html, body, ul, ol, a {
margin: 0;
padding: 0;
}
/** main.scss **/
@import 'reset';
body {
background: #a08106;
font-size: 16px;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
html, body, ul, ol, a {
margin: 0;
padding: 0;
}
body {
background: #a08106;
font-size: 16px;
}
小提醒:若有多個文件需匯入,可同時使用多個
@import
引用文件,如下圖 😛 😛
監聽父文件即可
編寫代碼過程中,可以把不同樣式區塊的 SASS 或 SCSS 代碼,拆開成不同獨立的文件,然後使用 @import
把各片段文件,統整匯入到同一支 .sass
或 .scss
文件中,並監聽這一支文件即可 😛 😛
在文件進行監聽時,所有 @import
進來的 .sass
或 .scss
子文件,也同時被監聽,所以當子文件有修改,父文件編譯出的 .css
也會自動更新。
使用下劃線,SASS 編譯自動忽略
若有片段文件不需 SASS 編譯出新的 CSS 文件,可在文件開頭添加一個下劃線,在編譯過程中,系統就會忽略它,而只對開頭無下劃線的文件,進行新的 CSS 文件生成。
上述的範例說明
看一下另一個範例,下面是 bootstrap 的目錄文件:
- 把多個 scss 文件,使用
@import
添加到 bootstrap.scss 中。之後只需監聽--watch
bootstrap.scss 這一支文件即可,假如內部@import
的文件有變更,都會在 bootstrap.css 自動更新。 - bootstrap.scss 文件內的
@import
檔案,不需要加下劃線。 - 開頭有下劃線的文件,在執行 sass 指令時,不會生成新的 css 文件,系統會自動忽略。
@import
scss 片段文件,不用加上副檔名也可以,系統會自動尋找同名的副檔名.scss
或.sass
文件,並依序導入。
一般 CSS @import
功能
@import
默認情況,會預設導入同名的 .sass
或 .scss
文件,但在以下情況下,僅當成一般的 CSS @import
語句,不會導入任何的 SASS 文件,如下:
- 如果文件的副檔名是
.css
:@import "foo.css";
- 文件名以
http://
開始 :@import "http://foo.com/bar";
- 文件名是
url()
:@import url(foo);
@import
中包含媒體查詢(media queries)
7. 混合
若是有重複的代碼,會不斷使用到,就可用混合指令(Mixin Directives),直接把樣式封裝成一個類名稱,就可以重複調用,如下:
/** 編譯前( sass 語法 ) **/
/** 定義 mixin 指令 **/
@mixin font-main {
font: {
family: Arial;
size: 16px;
weight: 100;
}
color: #000;
}
/** 引用 mixin **/
.box p {
@include font-main;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.box p {
font-family: Arial;
font-size: 16px;
font-weight: 100;
color: #000;
}
- 使用
@mixin
定義一個「 混合 」 - 使用
@include
引用一個「 混合 」 - 可同時引用多個「 混合 」
使用參數功能
使用「 混合 」功能,有設置參數功能( 可設定默認值 ),讓整體功能變更彈性,有點像函數的傳入參數,如下:
/** 編譯前( sass語法 ) **/
/** 定義 mixin 指令 **/
@mixin border-set($color, $width, $style: solid) {
border: {
color: $color;
width: $width;
style: $style;
}
}
@mixin background-set($color, $image, $repeat) {
background: {
color: $color;
image: url($image);
repeat: $repeat;
}
}
/** 引用 mixin **/
.box div {
@include border-set(red, 2px);
@include background-set(green, "../img_tree.png", 'no-repeat');
letter-spacing: 0.5em;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.box div {
border-color: red;
border-width: 2px;
border-style: solid;
background-color: green;
background-image: url("../img_tree.png");
background-repeat: "no-repeat";
letter-spacing: 0.5em;
}
8. 繼承
「 繼承 」@extend
是一個滿實用的功能,若想讓多個 class 使用相同樣式,就可使用 @extend
直接繼承過來,減少重複編寫的時間,如下:
/** 編譯前( sass語法 ) **/
%msg-style {
display: block;
flex-wrap: wrap;
background: #d9d9d8;
color: #000;
}
.msg {
@extend %msg-style;
}
.msg-success {
@extend %msg-style;
background: #34fc6d;
}
.msg-error {
@extend %msg-style;
background: #fc253e;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.msg, .msg-success, .msg-error {
display: block;
flex-wrap: wrap;
background: #d9d9d8;
color: #000;
}
.msg-success {
background: #34fc6d;
}
.msg-error {
background: #fc253e;
}
- 使用站位選擇器
%
,定義一個樣式,被定義的類,它將不會被編譯出來。 - 若沒有標註
%
的類,也可以使用@extend
引入,但定義的類會被編譯出來。 - 有使用
@extend
的類,會被系統編譯整合,使用共用樣式。
多重擴展,可引入多個選擇器
同一個選擇器,可以使用 @extend
擴展多個選擇器,這代表它繼承了擴展選擇器的樣式,如下:
/** 編譯前( sass語法 ) **/
.error {
background-color: #fa945c;
}
.notice {
font-size: 16px;
font-family: sans-serif;
font-color: #000;
}
.seriousError {
@extend .error;
@extend .notice;
background-color: #ff1b1b;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.error, .seriousError {
background-color: #fa945c;
}
.notice, .seriousError {
font-size: 16px;
font-family: sans-serif;
font-color: #000;
}
.seriousError {
background-color: #ff1b1b;
}
上面幾個狀況,應該是比較常見的 @extend
功能,應該滿足夠使用了,若想了解更多,可以直接參考 SASS 官方。
9. 操作符
SassScript 支持對數字的運算,如:(加法 +
、減法 +
、乘法 *
、除法 /
、取模 %
等 ..),來看一下代碼,如下:
/** 編譯前( sass 語法 ) **/
div a {
$width: 500px;
width: $width/2; // 使用變量,和 /
font: 16px/10px; // 原生CSS,不作為除法
height: (250px/2); // 使用了(), 和 /
margin-left: 10px + 8px/2px; // 使用了 +, 和 /
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
div a {
width: 250px;
font: 16px/10px;
height: 125px;
margin-left: 14px;
}
簡單來說,就是增加了運算功能,有需要也可進行使用。
這邊也有另一個範例,如下:
/** 編譯前( sass語法 ) **/
.container { width: 100%; }
article[role="main"] {
float: left;
width: 700px / 960px * 100%;
}
aside[role="complementary"] {
float: right;
width: 400px / 960px * 100%;
}
/** 編譯後( 轉為 CSS 語法輸出 ) **/
.container {
width: 100%;
}
article[role="main"] {
float: left;
width: 72.9166666667%;
}
aside[role="complementary"] {
float: right;
width: 41.6666666667%;
}
10. 結論
如果能看到這邊,首先給自己掌聲!相信對 SASS教學 ,也有程度的認識了!
接著,可以找個小案子,來自己練習,你會發現,CSS 結合了 JS 特性,開發起來會變得更加快速(省了很多代碼 😀 😀 )
SASS 在入門安裝+下指令時,會有些要適應,但這邊搞定後,會發現後面語法觀念,其實很容易上手,優化了傳統 CSS 開發上的許多不變。
希望這篇 SASS教學 文,有幫助到需要的捧有們,我們下篇文章見 🙂 🙂
謝謝文章!非常受用!
有一點要補充一下
現在若要查詢sass的版本
必須輸入
$sass –version (而非$sass -v)
才可以看到版本號唷
(我使用的版本是1.26.10 compiled with dart2js 2.8.4,不曉得是不是因為新版才用不了sass -v)