[Sass]學習筆記

Cheling Liao
Coding Cheling
Published in
18 min readDec 20, 2019

Sass (英文全稱:Syntactically Awesome Stylesheets) 是一個最初由Hampton Catlin 設計並由Natalie Weizenbaum 開發的層疊樣式表語言。

Sass 是一個CSS 預處理器。Sass 是CSS 擴展語言,可以幫助我們減少CSS 重複的代碼,節省開發時間。Sass 完全兼容所有版本的CSS。Sass 擴展了CSS3,增加了規則、變量、混入、選擇器、繼承、內置函數等等特性。Sass 生成良好格式化的CSS 代碼,易於組織和維護。

寫完 Sass 透過編譯成CSS給瀏覽器讀取的優點:可以寫較少的程式碼、可讀性高、提供巢狀結構和變數管理及運算功能、模組化好維護。

為什麼使用Sass?

Sass 是一款強化 CSS 的輔助工具,它在 CSS 語法的基礎上增加了變量 (variables)、嵌套 (nested rules)、混合 (mixins)、導入 (inline imports) 等高級功能,這些拓展令 CSS 更加強大與優雅。使用 Sass 以及 Sass 的樣式庫(如 Compass)有助于更好地組織管理樣式文件,以及更高效地開發項目。

CSS 本身語法不夠強大,導致重複編寫一些代碼,無法實現復用,而且在代碼也不方便維護。

Sass 引入合理的樣式複用機制,增加了規則、變量、混入、選擇器、繼承、內置函數等等特性。以下整理 Sass 特性。

註解

Sass 的註解有兩種,/* *///

兩者不僅僅是多行註解與單行註解的差異,// 是不會被編譯出來的。

Nesting:巢狀

降低父元素重複性。

轉譯後的 CSS 樣式:

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

轉譯前:

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

這樣如果需要修改 .parent 名稱,就只需要改一個地方。

要避免過度巢狀,如果包太多層,選擇器階層性過長,會導致瀏覽器渲染時間會比較久。

Sass 嵌套規則與屬性

Sass 嵌套 CSS 選擇器類似於 HTML 的嵌套規則。
如下我們嵌套一個導航欄的樣式:

Sass 代碼:

nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}

實例中,ul, li, 和 a 選擇器都嵌套在 nav 選擇器中,將以上代碼轉換未 CSS 代碼,如下所示:

Css 代碼:

nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}

Sass 嵌套属性

很多 CSS 屬性都有同樣的前綴,例如:font-family, font-size 和 font-weight , text-align, text-transform 和 text-overflow。在 Sass 中,我們可以使用嵌套屬性來編寫它們:

Sass 代碼:

font: {
family: Helvetica, sans-serif;
size: 18px;
weight: bold;
}
text: {
align: center;
transform: lowercase;
overflow: hidden;
}

將以上代碼轉換未 CSS 代碼,如下所示:

Css 代碼:

font-family: Helvetica, sans-serif;
font-size: 18px;
font-weight: bold;
text-align: center;
text-transform: lowercase;
text-overflow: hidden;

Variables:變量

Sass 支援定義變數。變數以美元符號($)作為開頭。變數用冒號(:)賦值。
變數的資料型態可以是 Numbers(可以有單位或無單位)、Strings、Booleans、null 值(視為空值),甚至可以使用 Lists、Maps 。

$text-color: #f00;

1. 變數使用時機

變數使用時機:

  • 全域樣式設定
  • 時常需要設定的樣式

如果需要修改樣式時,只需要修改變數的數值,就可以快速修改全部網頁的樣式,不需要逐一修改程式碼。

2. 變數格式

  • 數字,1, 2, 13, 10px
  • 字符串,有引號字符串與無引號字符串,"foo", 'bar', baz
  • 顔色,blue, #04a3f9, rgba(255,0,0,0.5)
  • 布林類型,true, false
  • 空值,null
  • 數組 (list),用空格或逗号作分隔符,1.5em 1em 0 2em, Helvetica, Arial, sans-serif
  • maps, 相當于 JavaScript 的 object,(key1: value1, key2: value2)

比較常用的為前三項。

數值

$flex: 2;
$fontsize-m: 16px;

字串

$ffm: "'Noto Sans TC', sans-serif";
$imge: '../../photo.png';

顏色

$white: white;
$color-1: #FFF000;
$color-2: rgb(0, 0, 0, .5);

運算

Sass 支持數字的標準運算(加 +、減 -、乘 *、除 / 和取餘 %),並且,如果需要的話,也可以在不同單位間做轉換:

// scss
p {
width: 1in + 8pt;
}
/* 編譯 css */
p {
width: 1.111in;
}

Sass 的陣列

雖然說陣列的英文應該是 Array,但是 Sass 裡面只有 List,但用法相同。

Sass 的陣列索引是從 1 開始,陣列通常是用來存放沒有鍵名的變數

$color: #000, #FFF, #222;// 透過 nth() 使用 List。
p {
color: nth($color, 2);
}

// 當然你也可以傳入索引變數
$index: 3;
a {
color: nth($color, $index);
}
/* 編譯 CSS */
p {
color: #FFF;
}
a {
color: #ABC;
}

Sass 的物件

雖然說物件的英文應該是 Object,但是 Map 裡面只有 maps,但用法相同。

Map 和 List 不同的地方在於你可以自訂每個資料的鍵名,也就是他們的名稱。

$linkColor: (
'dark': #000,
'light': #FFF,
'red': #791229,
);
p {
color: map-get($linkColor, dark);
}
/* 編譯 CSS */
p {
color: #000;
}

Maps function

  • map-get(map, key),取出指定的值
  • map-merge(map1, map2),合併多個 map
  • map-remove(map, key),移除指定的值
  • map-keys(map),列出指定 map 的全部 key
  • map-values(map),列出指定 map 的全部 value
  • map-has-key(map, key),確認 map 中是否有指定 key

@import

@import 可以將 CSS 程式碼切成好幾份來做檔案管理,最後編譯出來合併成一個CSS檔案,方便管理。

在檔案名稱前面加上 _,檔案將不會被編譯,例如 _reset.sass

利用 Sass import 功能,就可以將程式碼切成各糢組區塊,程式碼較少,同時也較能準確聚焦欲修改的區塊。

@mixin

使用 Sass @mixin 的好處:

  • 省去重複撰寫相同 CSS 樣式的時間
  • 建立 CSS 技巧資料庫,快速取用

以指令 @mixin 宣告,並以指令 @include 呼叫。

如果撰寫 SASS 格式:

  • @mixin= 符號
  • @include+ 符號

@mixin 範例:

@mixin table-base {
th {
text-align: center;
font-weight: bold;
}
td, th {
padding: 2px
}
}
#data {
@include table-base;
}
/* 編譯 css */
#data th {
text-align: center;
font-weight: bold;
}
#data td, #data th {
padding: 2px;
}

向混入傳遞變量

混入可以接收參數。我們可以向混入傳遞變量。
定義可以接收參數的混入:

實例

/*混入接收兩個參數*/
@mixin bordered ( $color , $width ) {
border : $width solid $color ;
}
.myArticle {
@include bordered ( blue , 1px ) ; //調用混入,並傳遞兩個參數
}
.myNotes {
@include bordered ( red , 2px ) ; //調用混入,並傳遞兩個參數
}

以上實例的混入參數為設置邊框的屬性(color 和width) 。
將以上代碼轉換未CSS 代碼,如下所示:

Css 代碼:

.myArticle {
border : 1px solid blue ;
}
.myNotes {
border : 2px solid red ;

參數預設值

@mixin 還可以附帶參數並給予預設值,如果沒有給值就會將預設值帶入。

@mixin bordered ( $color : blue , $width : 1px ) {
border : $width solid $color ;
}

在包含混入時,你只需要傳遞需要的變量名及其值:

實例

@mixin sexy- border ( $color , $width : 1in ) {
border : {
color : $color ;
width : $width ;
style : dashed ;
}
}
p { @include sexy- border ( blue ) ; }
h1 { @include sexy- border ( blue , 2in ) ; }

將以上代碼轉換未CSS 代碼,如下所示:

Css 代碼:

p {
border-color : blue ;
border-width : 1in ;
border-style : dashed ; }
h1 {
border-color : blue ;
border-width : 2in ;
border-style : dashed ;
}

@each

在@each中,定義了一個變量,其中包含列表中每個項目的值。

語句

@each $var in <list or map>

下面簡要解釋語法。

  • $ each:它表示變量的名稱。@each規則將$ var設置到列表中的每個項目,並使用值$ var輸出樣式。
  • <列表或地圖>:這些是SassScript表達式,將返回列表或映射。

$list 方法:

@each $color in red, green, yellow {
.p_#{$color} {
background-color: #{$color};
}
}

$map 方法:

$colors: (color1: red, color2: green, color3: yellow);

@each $key, $color in $colors {
.p_#{$color} {background-color: $color;}
}

使用each+Sass Maps來設計程式碼:

//scss程式碼
$types: (
primary : #428bca,
success : #5cb85c,
) !default;
//按鈕
@each $name, $color in $types {
.btn-#{$name} {
background:$color;
color:#fff;
border: 1px solid darken($color,5%);
}
}
]//編譯出來的CSS
.btn-primary {
background: #428bca;
color: #fff;
border: 1px solid #357ebd;
}
.btn-success {
background: #5cb85c;
color: #fff;
border: 1px solid #4cae4c;
}

我們一一來解析這樣的程式碼:

Sass Maps
Sass Maps是Sass 3.3所提供另一種變數的設定方式,
有點像是json富有key與value的概念,
所以一開始就把你這網站有哪些樣式整理好後,
key就寫此顏色的名稱,
valuse就寫他的色碼:

$types: (
primary : #428bca,
success : #5cb85c,
info : #5bc0de,
warning : #f0ad4e,
danger : #d9534f
)

@each
@each $name , $color in $types各別的意思是,
$types就是去讀取你的Sass Map裡面的變數,
看裡面有幾組,他的迴圈就會跑幾次。 $name、$color這兩個變數你可以自己命名,
只要知道第一個變數$name會去找冒號前面的內容,
第二個變數$color會找冒號後面的值即可。

${} 插補
變數沒辦法直接接字串,
如果你希望變數可以連結字串的話,
變數就必須使用插補包起來,
所以我each裡面迴圈的程式碼,
就可以透過插補動態產生class名稱,
所以.btn-#{$name}跑第一次迴圈時,
自然會先找到primary,組合起來就變成.btn-primary,
後面就依序組合各別的Class名稱。

@content

@content 的用途主要是拿來傳遞內容到 @mixin 裡面去的,像是一般的 @mixin 大家所認知的就是他能夠傳遞變數進去,

一般的 @mixin 如下程式碼:

@mixin bg($text-color, $bg-color) {
background: $bg-color;
color: $text-color;
}
.box {
@include bg(#fff,#000);
}
/* 編譯 css */
.box {
background: 000;
color: #fff;
}

使用 @content 就能在 @mixin 裡面繼續寫額外的東西

@mixin bg($text-color, $bg-color) {
background: $bg-color;
color: $text-color;
@content; // 增加一個 @content
}
.box {
@include bg(#fff, #000) {
border: 1px solid lighten(#000, 10);
// 將額外的程式碼寫在 @include 中括號裡面
}
}
/* 編譯 css */
.box {
background: #000;
color: #fff;
border: 1px solid #1a1a1a; /*對應 @content*/
}

舉個例子 @content 可以用在狀態樣式的表示:

// 連結樣式
@mixin link {
&:link,&:visited{
@content;
}
}
// 被點擊後的樣式
@mixin link-hover {
&:hover, &:focus, &:active, &.active{
@content;
}
}
.box {
height:50px;
@include link{color:#fff};
@include link-hover{color:#000};
}
/* 編譯 css */
.box {
height: 50px;
}
.box:link, .box:visited {
color: #fff;
}
.box:hover, .box:focus, .box:active {
color: #000;
}

利用此方法可以不用每次都要手寫 hoveractivefocus 的樣式。

另外 @content 的使用還可以在 media-queries、animation 的 keyframes 定義,還有為瀏覽器兼容的定義等等。

RWD 搭配 @mixin

也可以用在 RWD 斷點設計

$pc: 1024px;
$mobile: 768px;
@mixin rwd($width) {
@media (max-width: $width) {
@content;
}
}
.box{
float:left;
width: 30%;
@include rwd($mobile) {
float: none;
width: 100%;
}
}
/* 編譯 css */
.box {
float: left;
width: 30%;
}
@media (max-width: 768px) {
.box {
float: none;
width: 100%;
}
}

@extend

@extend 為合併樣式,將相同樣式的選擇器合併,並且可以繼續延續新增新的樣式。

@extend 語法:

.box1 {
background-color: #FFDDDD;
border: 1px solid yellow;
}

.box2 {
@extend .box1;
border-color: pink;
}
/* 編譯 css */
.box1, .box2 {
background-color: #FFDDDD;
border: 1px solid yellow;
}
.box2 {
border-color: pink;
}

注意合併樣式的先後順序。

.box2 {
@extend .box1;
border-color: pink;
}
.box1 {
background-color: #ffdddd;
border: 1px solid yellow;
}
/* 編譯 css */
.box2 {
border-color: pink;
}
.box1, .box2 {
background-color: #ffdddd;
border: 1px solid yellow;
}

如果是這樣,box2 的樣式將會被覆蓋。

佔位符選擇器%foo (Placeholder Selectors: %foo)

從 Sass3.3 開始,可以在同一行中使用最近選擇器引用 & 來實現高級選擇器,比如:

.foo {
&-bar {
color: red;
}
}
/* 編譯 CSS */
.foo-bar {
color: red;
}

種方式通常被用來配合 BEM 全名方式使用。

Sass額外提供了一種特殊類型的選擇器:佔位符選擇器 (placeholder selector)。與常用的 id 與 class 選擇器寫法相似,只是#.替換成了%。必須通過@extend指令調用。

當佔位符選擇器單獨使用時(未通過@extend調用),不會編譯到CSS文件中。

假如我們要建立一個樣式,但又不會去呼叫它,只是用來繼承,這時可以使用 % 符號。

Sass 對這種選取項型態稱作 Placeholders,只有當使用 @extend 才會有作用。

使用 % 符號,並不會被 Sass 編譯成 CSS:

a%drink {
font-size: 2em;
background-color: $lemon-yellow;
}
.lemonade {
@extend %drink;
/* more */
}
/* 編譯 css */
a.lemonade {
font-size: 2em;
background-color: yellow;
}
.lemonade {
/* more */
}

@extend@mixin 的差異性

1. @extend

@extend 主要用於合併相同程式碼

若程式碼中有部分的 CSS 段落都長一樣,就可以呼叫 @extend 將樣式合併,有點類似 JavaScript 的繼承。

2.@mixin

@mixin 主要用於壓縮程式碼段落

對於許多 CSS 段落需要重複使用,建議可以使用 @mixin 整理,此外,可以透過 代入參數 的特性重複使用,有點類似 JavaScript 的多型。

@extend與繼承

@extend指令告訴 Sass 一個選擇器的樣式從另一選擇器繼承。

如果一個樣式與另外一個樣式幾乎相同,只有少量的區別,則使用@extend就可能很有用。

以下 Sass 實例中,我們創建了一個基本的按鈕樣式 .button-basic,然後我們定義了兩個按鈕樣式 .button-report 與 .button-submit ,它們都繼承了 .button-basic,它們主要區別在於背景顏色與字體顏色,其他的樣式都是一樣的。

Sass代碼:

.button-basic {
border: none;
padding: 15px 30px;
text-align: center;
font-size: 16px;
cursor: pointer;
}
.button-report {
@extend .button-basic;
background-color: red;
}
.button-submit {
@extend .button-basic;
background-color: green;
color: white;
}

將以上代碼轉換未 CSS 代碼,如下所示:

.button-basic, .button-report, .button-submit {
border: none;
padding: 15px 30px;
text-align: center;
font-size: 16px;
cursor: pointer;
}
.button-report {
background-color: red;
}
.button-submit {
background-color: green;
color: white;
}

使用 @extend 後,我們在 HTML 按鈕標籤中就不需要指定多個類 class=”button-basic button-report” ,只需要設置 class=”button-report” 類就好了。

@extend 很好的體現了代碼的複用。

--

--