[筆記] 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)
- nulls:
null
- 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 0
或 font-family: Helvetica, Arial, sans-serif
。Lists 就是一系列的值,並且可以透過空格或逗號加以分隔,裡面的每個值稱作 item
,實際上任何單一的值也是 lists,他就是只有一個 item 的 lists。
lists 本身被沒有太多作用,在透過 SASSScript list functions 則讓 lists 變得非常好用。
nth
function :可以讀取 lists 內的 item。join
function :可以將多個 lists 連結再一起。append
function :可以將 items 添加到 lists 內。@each
directive 可以為 list 中的每一個 item 添加樣式。
除了包含單一值之外,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") => 1
map-get(("foo": 1, "bar": 2), "bar") => 2
參考資料
- SASS/SCSS 簡明入門教學 @ TechBridge
- SASS Guide @ SASS