Sass(Syntactically Awesome StyleSheets)是一種 CSS 的擴充,是為 CSS 的超集合(透過編譯會 compiled 成傳統 CSS,讓瀏覽器可以閱讀)。使用 Sass 的出現是為了解決在大型專案時傳統 CSS 會遇到的重複、可維護性差等問題(新增了 nested rules, variables, mixins, selector inheritance 等特性)。讓開發者可以撰寫簡潔、富語意(expressive)、重複性佳(reusable)、可維護性佳和可延展性佳的 CSS 程式碼。
Syntax 語法
Sass是一個將指令碼解析成CSS的手稿語言,即SassScript。
Sass包括兩套語法。
- SASS(學習曲線較高,檔案名稱為 *.sass)。
- 不使用大括弧格式。
- 使用縮排。
- 不使用分號。
- 不能直接使用 CSS 語法。
- SCSS (學習曲線相對較緩,初學者建議使用 SCSS 語法,檔案名稱為 *.scss) 。
- 使用和CSS一樣的語法。
- 大括號將不同的規則分開。
- 使用分號將具體的樣式分開。
SASS |
SCSS |
.button padding: 3px 10px font-size: 12px border-radius: 3px border: 1px solid #e1e4e8
|
|
.button { padding: 3px 10px; font-size: 12px; border-radius: 3px; border: 1px solid #e1e4e8; }
|
|
編譯方式
Sass為CSS預處理器,網頁瀏覽器無法識別此格式,所以須先將Sass編譯成CSS的格式。
常見讀編譯方式有:
- 編譯器:prepos
- Gulp / webpack 等任務處理 & 打包工具。
- 網頁編輯器的插件: Live Sass Compiler
SASS有分兩種註解,這兩種差別是在是否會被編譯出來。
|
// |
/**/ |
編譯顯示 |
不會編譯進CSS,不會顯示出來 |
會編譯進CSS,並顯示出來 |
類型 |
開發階段 dev |
正式階段 prod |
編譯後檔案容量 |
小,不含註解 |
大,包含註解 |
Nesting 巢狀
可以更加清晰地表示元素之間的關係。
優點:可以把輸出的CSS做整理,很快就看出語法含意。
缺點:過於多層,CSS會變得很難維護,看的時候語意不清楚。
SCSS |
CSS |
.nav ul { gackground: gray; display: flex; justify-content: spacer-between; > li { padding: 0 16px; } }
|
|
|
&連結詞
使用在:
- 偽元素「before」、「after」等
- 偽類「hover」「active」等。
- 同層但不同名稱的 class。
SCSS |
CSS |
a { display: block; padding: 6px 12px; text-decoration: none; &::after { content: ''; display: block; width: 100%; border-bottom: 2px solid #000; } &:hover { gackground: aqua; } }
|
|
|
Variables 變數
Sass支援定義變數,變數可以用來儲存值,方便重複利用。
變數以美元符號($
)作為開頭。變數用冒號(:
)賦值。
SassScript支援四種資料類型:
變數可以用作函式的參數或返回值。
SCSS |
CSS |
$blue: #3bbfce; $margin: 16px;
.content-navigation { border-color: $blue; color: darken($blue, 10%); }
.border { padding: $margin; margin: $margin; border-color: $blue; }
|
|
|
變數也支援運算
SCSS |
CSS |
$blue: #3bbfce; $margin: 16px;
.content-navigation { border-color: $blue; color: darken($blue, 10%); }
.border { padding: $margin / 2; margin: $margin / 2; font-size: $margin * 2; border-color: $blue; }
|
|
|
須注意幾點,如下:
- 建議加減乘除統一都用空格相鄰,避免編譯出現錯誤。
- 單位,css常見的單位類型可分為「絕對單位」和「相對單位」,如下:
- 絕對單位
- 印刷輸出的單位,如px, pt, pc, in, mm, cm…
- 相對單位
- 顯示設備的單位,如ex, em, rem…
- 絕對和相對單位,不能放一起運算。
- 相對單位不能互相運算。
- 絕對單位不能相乘。
單位最好不要混搭,只需用一個單位,這樣就減少出錯的機率。
字串管理
變數也能用於字串中,使用 ' '
or " "
,將字串包覆中便能調用字串。
常用於字型的管理。
顏色的運算
Sass 可透過一些內建的函式來簡單地調整顏色。
- 亮度調整,
darken
& lighten
darken
& lighten
是基於HSL並調整L(lightness) 。
這兩個函數在操作 hover 狀態時非常好用。
- 提高亮度(lighten)
- 色調與陰影
Tint
& Shade
@function tint($color, $percentage) { @return mix(white, $color, $percentage); }
|
- 混合黑色色調(Shade)
@function shade($color, $percentage) { @return mix(black, $color, $percentage); }
|
變數預設值 !default
可以在變數尚未賦值前,通過在值的最後處添加 !default
標記來為其指定。
也就是說,如果該變數已經被賦值,就不會再次賦值;但是,如果還沒有被賦值,就會被指定一個值。
Interpolation 插值
插值語法可以被用於幾乎所有的 Sass stylesheet 去崁入規則於CSS內。
只要將表達式包裹進 #{}
。
SCSS |
CSS |
$name: foo; $attr: border; p.#{$name} { #{$attr}-color: blue; }
|
|
p.foo { border-color: blue; }
|
|
At-rule 規則
Sass 支持所有 CSS3 的 @
規則, 以及一些 Sass 專屬的規則,也被稱為“指令(directives)”。 這些規則在 Sass 中具有不同的功能。
@import
Sass 擴充了 CSS 的 @import
規則,讓它能夠引入 SCSS 和 Sass 文件。 所有引入的 SCSS 和 Sass 文件都會被合併並輸出一個單一的 CSS 文件。
另外,被導入的文件中所定義的變數或 mixins 都可以在主文件中使用。
@import "_foo.scss";
@import "_foo";
|
常見錯誤(SCSS):
- 結尾為加入分號。
- 載入錯誤,可能為名稱錯誤,或者在載入的順序相反。
但在少數幾種情況下,它會被編譯成 CSS 的 @import 規則:
- 如果檔案的副檔名是 .css。
- 如果檔案名以 http:// 開頭。
- 如果檔案名是 url()。
- 如果 @import 包含了任何 media queries。
SCSS |
CSS |
@import "foo.css"; @import "foo" screen; @import "http://foo.com/bar"; @import url(foo);
|
|
@import "foo.css"; @import "foo" screen; @import "http://foo.com/bar"; @import url(foo);
|
|
CSS Reset - meyerweb 與 Normalize 的差異
開發網頁時,瀏覽器會自帶預設的樣式,如果要將樣式清除,必須重新寫CSS檔案來清空樣式,如今已經有現成的可供使用,分別為 meyerweb & Normalize,以下為兩者的差異。
- meyerweb - 將所有瀏覽器的樣式全數清空。
- Normalize
- 保留有用的瀏覽器默認設置,而不是將其刪除。
- 為廣泛的 HTML 元素提供一般化的樣式。
- 修正瀏覽器的 Bug 與不一致。
- 透過微妙的改善提高可用性。
- 有詳細的文檔來解釋代碼。(每個樣式都有註解是處理什麼問題。)
Partials
如果有一個 SCSS 或 Sass 檔案需要引入, 但又不希望它被編譯為一個 CSS 檔案,這時,你就可以在檔案名前面加一個下底線 _
,就能避免被編譯。
這將告訴 Sass 不要把它編譯成 CSS 檔案。 然後就可以像往常一樣引入這個檔案了,並且還可以省略掉檔案名前面的下劃線。
有一個檔案叫做 _colors.scss。 這樣就不會生成 _colors.css 檔案了, 而且還可以使用
來引入 _colors.scss 檔案。
注意,在同一個目錄下不能同時存在帶下底線和不帶下底線的同名檔案。
@mixin and @include
讓你不會回想原理,而中斷思緒
- 使用時機:需要大量重複使用到的屬性。
- 使用目的:建立專屬語法資料庫。
- @minix 需對應 @include
Syntax
@mixin 名稱 { 語法內容 };
.selector { @include 名稱; }
|
範例:
@mixin hide_text { text-indent: 101%; white-space: nowrap; overflow: hidden; }
.logo { background-image: url(....); @include hide_text }
|
帶入參數
Syntax
@mixin 名稱 ($var1, $var2,...) { css語法:$var1; css語法:$var2; };
selector { @include ($var1, $var2,...) 名稱 }
|
於 @include
名稱後面的小括號內設定參數數值,需依照 @mixin
所設定的變數順序來設定數值;
如無照順序的情況下,SASS編譯不會出現錯誤,但會讓網頁排版錯誤。
參數預設值
@mixin
帶入的參數是可以設定預設值的,但是有設定預設值的參數需排列在最後方,否則sass編譯時會出現error。
Required argument $max-width must come before any optional arguments.
Syntax
@mixin grid($max-width, $flex: true) { }
|
參數的變數
在Sass裡,變數可以為多個值的集合,稱為 list ,如果要將 list 帶入 padding 等可以有多值的屬性。
SCSS |
CSS |
@mixin padding($values) { @each $var in $values { padding: #{$var}; } } a { @include padding(2px 4px 6px); }
|
|
a { padding: 2px; padding: 4px; padding: 6px; }
|
|
可以改成,使用展開參數
...
加在變數的後方。
展開參數
SCSS |
CSS |
@mixin padding($values...) { @each $var in $values { padding: #{$var}; } } a { @include padding(2px 4px 6px); }
|
|
a { padding: 2px 4px 6px; }
|
|
另外一種方式,定義兩個變數,分別為 list and map,並定義一個 mixin 可帶入3個參數。
此兩個變數皆使用 展開參數 …
帶入。
SCSS |
CSS |
$style1: 100%, 70px, #fo6d06; $style2: (background: #bada55, width: 100%, height: 100px); @mixin box($width, $height, $background) { width: $width; height: $height; background-color: $background; } .fogdog { @include box($style1...); } .badass { @include box($style2...); }
|
|
.fogdog { width: 100%; height: 70px; background-color: #fo6d06; }
.badass { width: 100%; height: 100px; background-color: #bada55; }
|
|
- 在 list 的情況下
- 當 list 內有3個項目,且 mixin 須帶入的參數也為3個時,每一個參數皆會依順序分別的帶入,順序不能有錯,不然會造成網頁排版錯誤。
- 如 list 項目小於3個時,編譯時會出現錯誤。
- 當 list 項目大於3個時,編譯時只會取前3個。
- 在 map 的情況下
- 與 lsit 相同,但例外的點為,mpa 內的 key values 會對應變數名稱。
與響應式搭配
Syntax
@mixin + 名稱 { @media (裝置寬度) { @content } };
selector { @include + 名稱() { 內容 }; }
|
@media
裡面只要填 @content
。- 用
@include
+ 名稱() 引入, 裡面填上 @media
的css樣式。
範例:
SCSS |
CSS |
@mixin pad { @media (max-width: 768px) { @content } } .header { font-size: 24px; @include pad { font-size: 16px; }; }
|
|
.header { font-size: 24px; } @media (max-width: 768px) { .header { font-size: 16px; } }
|
|
@content
@content
的用途主要是拿來傳遞樣式到 @Mixin
裡面去。
@function
使用流程如下:
- 給予「變數」設定基礎數值。
- 給予function名稱,讓scss可套用。
- function內新增參數並設定預設值。
@function padding( $index: 1) {}
|
- function內設定運算公式。
@function padding( $index: 1) { @return $basePadding * $index; }
|
- 引入function。
selector { css樣式: function名稱 (參數); }
|
可把「變數」放在裡面。
@function padding( $index: 1, $basePadding: 10px) { @return $basePadding * $index; }
selector { css樣式: function名稱 ($index, $basePadding); }
|
@extend
sass中extend 是用來把css中重複的樣式作模組化,未來如要修改語法,只要改一次就能全部修改。
- 新增extend內容
- 增加extend名稱,格式使用「.」+名稱,裡面放重複的樣式。
- 在class或是id內的樣式放上
@extend + extend
名稱
SCSS |
CSS |
.error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; }
|
|
.error, .seriousError { border: 1px #f00; background-color: #fdd; } .seriousError { border-width: 3px; }
|
|
進階使用
mixin和function: 運算程式模組化
- 設定變數
$basePadding
,他的值為 10px。 - 建立名叫做 padding的
@function
,為運算程式,預設值為 1 。 @function
內容裡面分兩部分: @if
和 @return
。- 使用
@mixin
,裡面的內容是 @function
,如果有多個 @function
,可一次全部帶入到css中。
SCSS |
CSS |
$basePadding: 10px; @function padding( $index: 1) { @if $index < 1 { $index: 1; } @return $basePadding * $index; } @mixin a ( $index:1 ) { padding-left: padding($index); padding-right: padding($index); };
.px { @include a(3) }
|
|
.px { padding-left: 30px; padding-right: 30px; }
|
|
Flow control 流程控制
@if and @else
@if
用在判斷條件如果符合,就執行內容。
@else
是如果在 @if
中不符合條件,則執行 @else
的內容。
Syntax
@if (expression) { ... } @else { ... }
|
@each
Syntax
@each $var in ( list or map ) {}
|
list是一個SassScript表達式。
SCSS |
CSS |
@each $var in ( normal, bold ) { .font-#{$var} { font-weight: $var; } }
|
|
|
Maps是Sass Maps,於Sass 3.3所提供另一種變數的設定方式。
類似 json 內 key
與 value
的概念。
$name
就是map裡面,key
的值 (normal, …)。
$value
就是map裡面,value
的值 (flex-start, …)。
SCSS |
CSS |
$flex_posi: ( "normal":"flex-start", "end":"flex-end", "center":"center", "between":"spacer-between", "rounder":"spacer-rounder" ); @each $name, $value in $flex_posi { .justify-content-#{$name} { justify-content: $value; } }
|
|
|
@for
sass for迴圈有兩種語法 :
Syntax
@for $var from (start) through (end)
|
@for $var from <start> through <end>
|
從整個循環都跑一遍。
透過 #{ }
轉為css可用的數值。
SCSS |
CSS |
@for $var from 1 through 5 { .padding-#{$var} { padding: 10px * $var; } }
|
|
|
Syntax
@for $var from (start) to (end)
|
從 start
開始碰到 end
就結束,所以沒有套用到 end
。
因此大部分使用sass的for迴圈都是使用 @for $var from through
。
SCSS |
CSS |
@for $var from 1 to 5 { .padding-#{$var} { padding: 10px * $var; } }
|
|
|
@for $i from 1 through 5 { .box-#{$i} { background-color: darken(#c1dfc4, $i * 10%); } }
|
@while
while 只要條件符合 true ,就會一直跑下去,除非手動停止,否則很容易形成無限迴圈也因此稍有不慎會影響電腦效能。
Syntax
@while (expression) { ... }
|
@function scale-below($value, $base, $ratio: 1.618) { @while $value > $base { $value: $value / $ratio; } @return $value; }
$normal-font-size: 16px; sup { font-size: scale-below(20px, 16px); }
|