Skip to main content

[筆記] SASS / SCSS

lighten($color, $amount) // Makes a color lighter.darken($color, $amount)  // Makes a color darker.

目錄#

[TOC]

資料型態(Data Types)#

SASSScript 支援 8 種資料型態:

  • 數值(number):1.2 , 13, 10px
  • 字串(strings):"foo", 'bar', baz(可以有引號或沒有)
  • 顏色(color):blue, #04a3f9, rgba(255, 0, 0, 0.4)
  • nullsnull
  • lists of value:1.5em 1em 0 2em, Helvetica, Arial, sans-serif
  • maps from one value to another:(key1: value1, key2: value2)
  • function references

Data Types @ SASS Reference

String Interpolation#

在 SASS 中可以使用 #{} ,裡面的內容會被 SASS 編譯:

@mixin tooltip($background) {  background-image: url(#{$background});}

Lists#

Lists 是在 SASS 中用來表徵 CSS 樣式的方式,像是 margin: 10px 15px 0 0font-family: Helvetica, Arial, sans-serifLists 就是一系列的值,並且可以透過空格或逗號加以分隔,裡面的每個值稱作 item,實際上任何單一的值也是 lists,他就是只有一個 item 的 lists。

lists 本身被沒有太多作用,在透過 SASSScript list functions 則讓 lists 變得非常好用。

除了包含單一值之外,lists 也可以包含其他 lists,舉例來說,1px 2px, 5px 6px 是一個包了兩個 lists 的 lists,其中第一個 item 是 list 1px 2px,另一個 item 則是 list 5px 6px。如果裡面的 lists 和外面的 lists 有相同的分隔符號(即,空格或逗號),那麼則需要使用括號來定義清楚,舉例來說,(1px 2px) (5px 6px) 和前面一樣,都是包有兩個 lists 的 lists。

當 lists 被轉換成 CSS 時,SASS 不會添加任何括號,因為 CSS 並不了解他們,也就是說 (1px 2px) (5px 6px)1px 2px 5px 6px 在它們轉換成 CSS 之後,都是一樣的,但在轉換之前他們是不同的。

Lists 也可以不包含任何 items,這樣的 lists 可以用 () 表示(這也同樣是空的 map),他們沒辦法被直接轉換成 CSS。

Maps#

Maps 在 SASS 中用來表徵 key 和 values 的關係,和 lists 不同,maps 總是必須要透過括號包著,並且用逗號分隔

$map: (  key1: value1,  key2: value2,  key3: value3,);

和 Lists 類似,maps 經常透過 SASSScript functions 來使用:

  • map-get 可以找出在 map 裡面的 value。
  • map-merge :可以添加值到 map 當中。
  • @each directive :可以用來為 map 中的每一個 key/value pair 添加樣式。

Maps 也可以用來任和 lists 可以用的地方,當對 maps 使用 lists 的函式時,map 會被視為 a list of pairs,舉例來說,(key1: value, key2: value2),將會被視為 key1 value1, key2 value2 的 list。

但 Lists 並不能被當作 maps 使用,除了空的 lists () 之外,() 可以用來同時表示沒有 item 的 lists 或是沒有 key/value pairs 的 Maps。

Maps 並沒有辦法轉換成 CSS,透過 inspect($value) 可以用來檢視某個 maps 的內容,方便 debug 使用

建立變數(variable)#

keywords: !global, !default#

在 SASS 中可以使用關鍵字 $ 來建立變數。在 SASS 所定義的變數中,底線(_)和連結線(-)的使用可以互換,舉例來說,雖然下面定義的變數名稱是 $bg_black,但是一樣可以透過 $bg-black 提取:

$bg_black: #333;
.block1 {  background-color: $bg_black;}
.block2 {  background-color: $bg-black;}

全域變數(!global)#

這些變數只有在它所定義的階層中有效,因此如果想定義的是全域變數,可以使用 $ 將變數定義在最外層,或者是用 !global 標籤來定義全域變數:

$black: '#CCC';
body {  background-color: $black;  $width: 100% !global; // 這個 $width 會變成全域變數  width: $width;}

預設變數(!default)#

對某一個變數後方加上 !default 後,如果這個變數有被賦值過,則使用該值,如果沒有被賦值過,則使用預設值:

// SCSS$gray: #eaeaea;
$black: #333 !default; // $black 沒被賦值過,所以會套用預設值$gray: #cacaca !default; // $gray 被賦值過,所以不會套用預設值
.block {  background-color: $black;  color: $gray;}

編譯後:

/* CSS */.block {  background-color: #333;  color: #eaeaea;}

建立函式(function directive)#

$grid-width: 40px;$gutter-width: 10px;
@function grid-width($n) {  @return $n * $grid-width + ($n - 1) * $gutter-width;}
#sidebar {  width: grid-width(5);}

Function Directive @ SASS Documentation

Partials#

keywords: @import#

在 SASS 中會以底線開頭的方式來為 partials 檔案命名,例如 _partial.scss,SASS 會知道底線開頭的檔案是 partial,因此不會產生一支獨立的 CSS 檔。在主要的 SASS 檔中則可以透過 @import 來載入 partial 檔。

若想載入名為 _partial.scss 的 partial 檔,只需在主要的檔案使用 @import ,同時 partial 檔的底線(_)和副檔名(.scss)可以不用寫出來:

// main.scss@import 'partial';

mixins#

keywords: @mixin, @include, @content#

使用關鍵字 @mixin 來建立函式;使用關鍵字 @include 來載入函式。

不帶參數的 mixin#

/** * 建立基本的 mixin **/@mixin large-text {  font: {    family: Arial;    size: 20px;    weight: bold;  }  color: #ff0000;}
.page-title {  @include large-text;  padding: 4px;  margin-top: 10px;}

帶有參數的 mixin#

/** * 建立帶參數和預設值的 mixin **/
@mixin sexy-border($color, $width: 1px) {  border: {    color: $color;    width: $width;    style: dashed;  }}p {  @include sexy-border(blue);}h1 {  @include sexy-border(blue, 2px);}

@content#

在使用 @mixin 時搭配 @content 可以把 @include 中的內容載入,這很適合用在 RWD 的 media-query 使用:

// SCSS@mixin apply-to-ipad {  @media screen and (max-width: 768px) {    @content;  }}@mixin apply-to-iphone {  @media screen and (max-width: 375px) {    @content;  }}
@include apply-to-iphone {  #logo {    background-image: url(/logo.gif);  }}
@include apply-to-ipad {  #logo {    background-image: url(/logo2x.gif);  }}

編譯後:

@media screen and (max-width: 375px) {  #logo {    background-image: url(/logo.gif);  }}@media screen and (max-width: 768px) {  #logo {    background-image: url(/logo2x.gif);  }}

Extend/Inheritance#

keywords: @extend, placeholder class#

extend placeholder class(%)#

// scss%center-center {  display: flex;  align-items: center;  justify-content: center;}
.icon {  @extend %center-center;  color: white;}
.banner {  @extend %center-center;  width: 100%;}

編譯出來的結果會是這樣:

  • %center-center 的內容並不會被編譯出來,因此在程式碼中並不能直接使用 .center-center 這個樣式
.banner,.icon {  display: flex;  align-items: center;  justify-content: center;}
.icon {  color: white;}
.banner {  width: 100%;}

extend 另一個 class#

除了使用 placeholder class 之外,也透過 @extend 直接繼承另一個 class 內的樣式:

// scss.message {  border: 1px solid #ccc;  padding: 10px;  color: #333;}
.success {  @extend .message;  border-color: green;}
.error {  @extend .message;  border-color: red;}

編譯後的 CSS 會是這樣:

  • 在程式碼中可以直接使用 .message 這個 class:
/* CSS */.message,.success,.error {  border: 1px solid #ccc;  padding: 10px;  color: #333;}
.success {  border-color: green;}
.error {  border-color: red;}

嵌套(nested)#

keywords: &#

使用關鍵字 & 來表示父層元素:

// SCSS// 意思是 .nav:hover{...}.nav {  &:hover {    color: #ccc;  }}

Nested Properties#

在 CSS 中許多的屬性都帶有相同的 "namespaces" ,例如 font-family, font-size, font-weight;在 SASS 中則提供了可簡便的寫法,你只需要寫一次 namespace 即可:

// SCSS.foo {  font: {    family: fantasy;    size: 30em;    weight: bold;  }}

SASS 會自動編譯成:

/* CSS */.foo {  font-family: fantasy;  font-size: 30em;  font-weight: bold;}

註解(Comments)#

keywords: /*...*/ , //...#

在 SASS 中提供了兩種註解的方式,一種是多行註解 /* ... */,另一種是單行註解 //... ,在編譯成 CSS 檔後,多行註解會被保留但單行註解會被移除

Directives 和 Functions#

常用#

darken(#ccc,12);lighten(#ccc ,12);
adjust-hue(#F05941, 20%);

SASS::Script::Functions @ SASS Documentation

@root#

透過 @root 可以把原本被牽套在內的樣式拉到最外層:

@root @ Sass Lang

@mixin apply-to-webp($child) {  @at-root html.webp #{$child} {    @content;  }}
@mixin apply-to-no-webp($child) {  @at-root html.no-webp #{$child} {    @content;  }}
.block-reviews {  // 透過 & 可以選到當前的 CSS 選擇器  @include apply-to-webp(&) {    background-image: url('~images/background/coffee_shop.webp');  }
  // 透過 & 可以選到當前的 CSS 選擇器  @include apply-to-no-webp(&) {    background-image: url('~images/background/coffee_shop.png');  }}
// 編譯出來後html.webp .block-reviews {  background-image: url('~images/background/coffee_shop.webp');}html.no-webp .block-reviews {  background-image: url('~images/background/coffee_shop.png');}

@each#

keywords: @each $var in <list or map>, @each $var1, $var2, ... in <list>#
// SCSS
// with one variable in list@each $animal in puma, sea-slug, egret, salamander {  .#{$animal}-icon {    background-image: url('/images/#{$animal}.png');  }}
// with multiple variables in list@each $animal, $color, $cursor in (puma, black, default), (sea-slug, blue, pointer),  (egret, white, move){  .#{$animal}-icon {    background-image: url('/images/#{$animal}.png');    border: 2px solid $color;    cursor: $cursor;  }}
// SCSS
// with multiple variables in map@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {  #{$header} {    font-size: $size;  }}

map_merge#

透過 map_merge($map1, $map2) 可以用來合併兩個 map:

#map_merge($map1, $map2)

範例:

map-merge(("foo": 1), ("bar": 2)) => ("foo": 1, "bar": 2)map-merge(("foo": 1, "bar": 2), ("bar": 3)) => ("foo": 1, "bar": 3)

map_get#

透過 map_get 可以取得 map 中某個 key 相對應的 value:

map-get($map, $key) // Returns the value in a map associated with a given key.map-get(("foo": 1, "bar": 2), "foo") => 1map-get(("foo": 1, "bar": 2), "bar") => 2

參考資料#