SASS 學習筆記
總共會寫兩個練手項目,成品在 https://goldenaarcher.com/scss-study 可以看到,代碼在 https://github.com/GoldenaArcher/scss-study。
什么是 SASS
SASS 是 CSS 預處理,它提供了變量(雖然現在 CSS 也提供了,不過 SASS 的更加靈活),嵌套、mixin、函數、導入和擴展等功能,可以高效地做到代碼復用。SASS 包括 SASS 和 SCSS,二者都支持嵌套、mixin 和變量,主要的區別在:
-
語法
SCSS 的語法更加貼近 CSS,而 SASS 不適用
{}
和;
,并且依賴縮進定義結構(有點類似 python 的寫法)因此 SASS 的排版必然是更加簡潔和美觀的,相對而言剛從 CSS 轉到 SASS 也有可能會不太適應
-
兼容性
SCSS 更加接近 CSS 的語法,因此兼容性相對更好一些,比較適合作為 CSS 到 SASS 的過渡。當然,對于不是非常復雜的項目,使用 SCSS 本身也夠了
SASS 的支持相對更強一些,不過因為兼容性和語法的問題,流行度相對低一些
-
學習曲線
SASS 比 SCSS 高
這篇筆記主要學習的是 SCSS 為主。
基礎
配置
SASS 作為 CSS 的預處理,無法直接在瀏覽器中運行,因此需要下載對應的包將寫好的 SASS 轉化為 CSS,使得瀏覽器可以解析。
編譯的方式有通過編輯器,或者是使用 node 依賴完成,這里使用后者,方式為下載 sass
,并且在 package.json
中添加一下代碼:
{"scripts": {"watch": "sass scss/:css/ -w"}
}
這樣 sass
會將 scss
文件夾下的內容編譯后保存到 css
文件夾下,-w
的 flag 代表監聽狀態,他會監聽 scss 文件夾下的變化,并且重新進行編譯。
項目整體結構大概如下:
除了 sass
之外,還有比較臭名昭著的 node-sass
,雖然 node-sass
還是在維護的,并且目前也支持到 node20,而且常規的 SCSS 功能都能實現完成編譯,不過 node-sass
的兼容性真的很有問題……反正我本人在 Windows 上嘗試運行 node-sass 的時候碰到很多問題。
另一個 SASS 的配置方法在 sass 簡易配置 里有 cv,那個用的包比較多,具體干什么的還沒怎么看,不過想要比較完整的項目配置,可以看看這個。
變量
scss 的變量以 $
開始,我是覺得目前 CSS 對變量的支持也挺好的,不過考慮到兼容性的問題,統一使用 SCSS 會方便些,具體使用方法如下:
// 定義
$color-dark: #262626;
$color-black: #000;
$color-primary: #d3ab55;
$color-secondary: #bbb;
$color-white: #fff;$font-dancingScript: 'Dancing Script', cursive;
$font-josefinSans: 'Josefin Sans', sans-serif;
$font-nunito: 'Nunito', sans-serif;// 使用
body {// local scope也可以重寫變量// 想要在本地重寫global變量可以使用下面的語法:// $color-white: #eee !global;background-color: $color-dark;
}
它的編譯結果如下:
body {background-color: #262626;
}
可以看到 $color-dark
已經被編譯了,而不是直接使用變量,所以如果要有老版瀏覽器兼容的考慮,使用 SCSS 變量會方便一些。
像是主題顏色(primary、 secondary、warning、success 這種顏色)和字體大小、breakpoint 一般都推薦使用全局定義的變量來實現。練手的項目 1 中對于顏色、字體都使用了變量進行定義,但是 media query 沒有,大概因為邊寫邊感覺的原因……?
嵌套
嵌套是一個我覺得使用 SCSS 非常方便的點,如下面這個 HTML 的結構:
<nav class="navbar"><input type="checkbox" name="check" id="check" class="checkbox" hidden /><div class="hamburger-menu"><label for="check" class="menu"><div class="menu-line menu-line-1"></div><div class="menu-line menu-line-2"></div><div class="menu-line menu-line-3"></div></label></div>
</nav>
要選擇 navbar > hamburger > menu
,并且分別應用樣式,CSS 的寫法為:
.navbar {
}.navbar .hamburger {
}.navbar .hamburger .menu {
}@media (max-width: 760px) {.navbar .hamburger {}.navbar .hamburger .menu {}
}
SCSS 的寫法為:
.navbar {.hamburger {@media (max-width: 760px) {}.menu {@media (max-width: 760px) {}}}
}
我個人還是比較偏好這種嵌套式的寫法,尤其是一些樣式都比較依賴選擇多個 class selector 去增加權重覆寫樣式的情況下,這樣的確能少寫一些代碼。media query 也嵌套在這里,找 responsive 的實現代碼也更方便一些。
extend
extend 是一個比較強大的方法,其實現和使用方法如下:
.full-space {width: 100%;height: 100%;
}.header {@extend .full-space;
}
編譯后的結果為:
.full-space,
.header {width: 100%;height: 100%;
}
如果有多個樣式都 extend 了同一個樣式,那么 SCSS 也會將其打包在一起,而不是額外重復一遍 CSS,如:
.full-space {width: 100%;height: 100%;
}.header {@extend .full-space;
}.footer {@extend .full-space;
}
對應的 CSS:
.full-space,
.header,
.footer {width: 100%;height: 100%;
}
mixin
mixin 是另一個 SCSS 強大的地方,它的使用方法為:
@mixin textStyles($transform: uppercase) {font-weight: 300;letter-spacing: 2px;text-transform: $transform;
}.main-name {font-family: $font-nunito;font-size: 50px;color: $color-secondary;@include textStyles;
}
編譯后的結果為:
.main-name {font-family: 'Nunito', sans-serif;font-size: 50px;color: #bbb;font-weight: 300;letter-spacing: 2px;text-transform: uppercase;
}
與 extend 最大的不同有兩點:
- mixin 可以接受參數
- mixin 會將定義好的樣式添加到當前 selector 中
總體來說,如果一個樣式的代碼是固定且不會變動的,并且想減少 CSS 的大小,那么就可以使用 extend。相反,如果想要一個代碼更加的動態,需要依靠傳入的變量進行修改時,就可以使用 mixin,另一個比較適合使用 mixin 的案例是 transition,一般 duration、應用的樣式及延遲都不太一樣,這時候可以使用 mixin 減少編程時的代碼量。
mixin 在提供 default value 是可以不傳值的,不傳值的情況下 SCSS 會使用默認值。不提供默認值好像是會報錯的來著……
function
function 可以實現一些計算,如:
@function fontSize($size: 12px) {@return $size * 2;
}
對于一些小型的項目來說,function 的使用并不一定會很方便,不過對于一些大型項目,特別是 margin、padding 都有定義好的 responsive 項目,使用 function 會方便很多。
SCSS 也有一些預設的 function,如顏色有 darken
, lightedn
等 數字有 percent
等,數學有 min
, max
等,以便開發。
placeholder selector
用 extend
會創建一個空置的 class,使用 placeholder selector 可以解決這個問題,用法如下:
%full-space {width: 100%;height: 100%;
}.header {@extend %full-space;
}.footer {@extend %full-space;
}
對應的 CSS:
.header,
.footer {width: 100%;height: 100%;
}
import & partials
partial 指的是 SCSS 文件名在命名時使用 _
作為前綴的命名規范,如 _base.scss
,這樣 SCSS 就不會多生成一個 _base.scss
的文件。隨后使用 import
關鍵詞在 main.scss
中導入對應的包,就可以將 _base.scss
的樣式添加到 main.scss
中,如:
-
_base.scss
$color-dark: #262626; $color-black: #000; $color-primary: #d3ab55; $color-secondary: #bbb; $color-white: #fff;$font-dancingScript: 'Dancing Script', cursive; $font-josefinSans: 'Josefin Sans', sans-serif; $font-nunito: 'Nunito', sans-serif;
-
main.scss
@import 'base'; @import 'layout'; @import 'components';
因為 base
是最先導入的,layout
和 component
也可以使用 base
中定義好的變量名。
一些有趣的 CSS 小技巧
使用 checkbox
checkbox 本身可以使用 HTML5 的 hidden
,同時使用選擇器,這樣可以在不懈 JS 的情況下完成 onclick
的事件實現
hamburger icon
這個在點擊的時候有兩個特效:
第一個 90 度翻轉比較好理解,第二個也是用 CSS 實現的,簡單的說就是將中間的那條線透明度設置為 0,同時左右兩根線分別按照 z 軸向左向右旋轉一定角度,獲取下面的箭頭形狀:
然后搭配 transform-origin: right;
使用即可。
這個用法真的好巧妙啊。