SASS、SCSS 與純 CSS 的差別一次釐清
SCSS 是 CSS 預處理器 Sass 的主流語法,把變數、巢狀、Mixin、繼承與拆檔能力加進原本的 CSS 裡,寫完再編譯回瀏覽器看得懂的純 CSS。它的真正價值在一致性:當…
SCSS 是 CSS 預處理器 Sass 的主流語法,把變數、巢狀、Mixin、繼承與拆檔能力加進原本的 CSS 裡,寫完再編譯回瀏覽器看得懂的純 CSS。它的真正價值在一致性:當品牌色或元件規格一變,整個專案的樣式能在改一行變數後同步更新。根據 Sass 官方文件 [來源:〈Sass Documentation〉〈https://sass-lang.com/documentation/〉〈2026〉],SCSS 保留與 CSS 完全相容的大括號寫法,任何一份合法 CSS 改副檔名為.scss 就能直接編譯,這是它成為主流的根本原因,也是新手該從 SCSS 著手的理由。
多數 SCSS 教學把焦點擺在「語法怎麼寫」,但真正決定專案能不能用得久的,是拆檔與命名策略。過度巢狀與濫用 @extend 會編譯出又肥又難覆寫的 CSS;判斷 SCSS 寫得好不好,關鍵看巢狀深度是否可控、變數與 Mixin 是否有明確規範,而非程式碼多寡。這篇會把相當篇幅放在工程化觀念,像 7-1 架構、部分檔命名、@use 取代 @import,以及何時該用 Mixin 而非 @extend。若還不熟基本樣式語法,可先看 CSS 基礎語法與入門觀念 與 CSS Box Model 盒模型設定 打底。
SASS、SCSS 與純 CSS 的差別一次釐清
SASS 與 SCSS 是同一個 CSS 預處理器的兩種語法。舊版 SASS 用縮排、沒有大括號與分號,新版 SCSS 保留與 CSS 完全相容的大括號寫法;因為任何一份合法 CSS 貼進.scss 都能直接編譯,學習成本最低,所以現在主流與官方文件都以 SCSS 為主,新手直接學 SCSS 即可 [來源:〈Syntax - Sass Documentation〉〈https://sass-lang.com/documentation/syntax/〉〈2026〉]。
預處理器的本質要記住:你寫的是 SCSS,經過編譯器轉成瀏覽器看得懂的純 CSS,瀏覽器本身根本不認識 SCSS。這代表 SCSS 是給開發者用的工具,不是給瀏覽器用的。理解這點之後,很多觀念會豁然開朗,例如變數在編譯期就固定了,不是執行期才改。
把兩種語法擺在一起對照最清楚。`.sass` 是縮排式,去掉括號與分號;`.scss` 是區塊式,保留括號分號,與 CSS 相容。相容性是關鍵:一份既有的 CSS 改副檔名為.scss 就能編譯,這是 SCSS 成為主流的根本原因。日常與官方文件常把兩者統稱 SASS,學 SCSS 就等於掌握了 SASS 生態。想了解整體自學路線,可參考 網頁設計自學路線圖。
| 比較項目 | SASS(舊版縮排式) | SCSS(新版區塊式) |
|---|---|---|
| 副檔名 | .sass | .scss |
| 括號與分號 | 無,靠縮排區分 | 保留,與 CSS 一致 |
| 與 CSS 相容 | 不相容,需重寫 | 完全相容,改副檔名即可 |
| 學習成本 | 較高 | 最低 |
| 主流與官方文件 | 屬維護既有專案 | 主流推薦 |
| 選擇建議 | 僅維護既有縮排專案時 | 新手與新專案一律從此著手 |
選擇建議很直白:除非要維護既有的縮排式專案,否則一律從 SCSS 著手,資源與社群支援都最多。多數公司與框架早就全面換成 SCSS,懂它之後回頭看縮排式語法也不會太陌生,因為觀念是相通的。延伸學習可看 網頁設計完整入門指南 與 網頁設計關鍵元素。
SCSS 安裝與編譯:三種方式與 --watch 即時監聽
安裝 SCSS 最常見的三條路是 Node.js 的 npm、Mac 的 Homebrew,或透過 GUI 工具。裝好後用 `sass --version` 確認版本,接著用 `sass --watch` 指令讓存檔時自動重新編譯,不用每次手動跑指令。這部分是新手最容易卡關的地方,撐過去後面語法就輕鬆了。
第一種安裝路線是 npm,跨平台最普遍,只要有 Node.js 環境就能跑。第二種是 Homebrew,Mac 專用、更新方便。第三種是 GUI 編譯軟體,給不想碰指令列的人用。安裝指令屬工具標準用法,可參考 Sass 官方 install 指南 [來源:〈Install Sass〉〈https://sass-lang.com/install/〉〈2026〉],版本號不寫死以免過期。三種方式的差異如下表。
| 安裝方式 | 指令 | 適合對象 | 優點 |
|---|---|---|---|
| npm | npm install -g sass | 跨平台開發者 | 最普遍,與前端工具鏈整合 |
| Homebrew | brew install sass | Mac 使用者 | 更新與解除安裝方便 |
| GUI 工具 | 圖形介面操作 | 不碰指令列者 | 設定一次即可,門檻低 |
這裡有一個不能裝錯的重點:官方目前維護的是 Dart Sass,npm 上的 `sass` 套件即為 Dart Sass。舊的 node-sass(背後的 LibSass)已正式宣告 end-of-life、不再維護 [來源:〈LibSass is deprecated〉〈https://sass-lang.com/blog/libsass-is-deprecated/〉〈2026〉],新專案千萬不要再 `npm install node-sass`,否則會用到一個不再更新、也不支援新語法的編譯器,碰到新版語法時編譯會直接失敗。安裝前確認裝的是 Dart Sass,是新手少走冤枉路的關鍵一步。
驗證安裝是否成功,輸入 `sass -v` 或 `sass --version`,能印出版號就代表沒問題。接著做單次編譯測試:`sass sass/style.scss:css/style.css` 會在 css 資料夾產出 style.css 與 source map。source map 是除錯用的對照檔,能讓瀏覽器把編譯後的 CSS 對應回原本的 SCSS 行數,排查問題時很好用。若想在本機架站練習,可看 MAMP 本機架站教學。
單次編譯的麻煩在於,每次改完都要重跑指令才能在瀏覽器看到變化,寫到後面一定會想撞牆。所以日常開發的標準作法是加上 `--watch` 參數做自動監聽。`sass --watch sass/style.scss:css/style.css` 會持續監聽,只要.scss 有變動就即時編譯。若要一次監聽整個資料夾,用 `sass --watch sass/:css/`,適合多檔案專案。
- 單檔監聽用 `sass --watch sass/style.scss:css/style.css`,入門最常這樣跑。
- 要一次處理整個資料夾,改成 `sass --watch sass/:css/`。
- 不想開終端機,裝 VSCode 的 Live Sass Compiler 擴充功能,存檔即編譯。
- 監聽會順便吐出 style.css 與 style.css.map 兩個檔,前者是瀏覽器吃的,後者是除錯用的 source map。
有人會問,那到底該用指令列還是 VSCode 擴充功能?我的看法是:只寫一個專案、又不熟指令,擴充功能真的省事;但同時維護多個專案、或要進 CI/CD 流程,指令列才是能寫進腳本的重複作法。說到底,工具選擇要看你的工作流,沒有絕對優劣。學完安裝後,若想了解頁面編輯器的選擇,可參考 WordPress 頁面編輯操作、Gutenberg 區塊編輯器外掛、WordPress 頁面編輯器比較。
巢狀與父選擇器 &
巢狀讓你把子選擇器寫在父選擇器裡面,編譯後展開成原本的 CSS,省去一再重複打.nav、.nav li 這類前綴。而 `&` 符號代表外層的父選擇器,最常搭配 :hover、:focus、::before 這類偽類與偽元素,把狀態樣式收在同一個區塊裡。這是 SCSS 最直觀、也是最容易上手的功能。
巢狀的核心價值在消除父層選擇器的重複書寫,讓樣式結構對應 HTML 階層,可讀性提升。除了選擇器能巢狀,屬性也能巢狀。例如 font-family、font-size、font-weight 都以 font 開頭,可以寫成 `font: { family:...; size:...; }`,background 系列同理。這種寫法在屬性多的時候能讓程式碼更緊湊。
`&` 的意義是直接抓父選擇器字串,編譯時原樣代入。最常見的用法是把 hover、focus、active 等狀態收進父區塊。寫成 `.btn { &:hover {... } }` 編譯後就是 `.btn:hover {... }`,視覺上狀態樣式與基礎樣式擺在一起,維護時不用在檔案裡跳來跳去找。這點在寫 CTA 按鈕設計指南 之類的元件時特別有感。
不過巢狀有個深度警告必須講:巢狀超過 3 層會編譯出又長又難覆寫的選擇器,像 `.nav ul li a span` 這種,應該有意識控制深度。過深巢狀不只檔案肥,也讓 CSS 權重(specificity)失控,之後要覆寫反而得用更長的選擇器硬撞,形成惡性循環。這也是為什麼很多資深開發者寧可用 BEM 命名把選擇器打平,也不願無腦巢狀。
| 比較項目 | SCSS 巢狀 | 原生 CSS Nesting |
|---|---|---|
| 歷史成熟度 | 十多年,工具鏈完整 | 較新,瀏覽器陸續支援 |
| 瀏覽器支援 | 編譯成傳統 CSS,全支援 | 較新的瀏覽器已陸續支援 [來源:〈Using CSS nesting - MDN〉〈https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting〉〈2026〉] |
| 工具鏈整合 | 與 PostCSS、建置流程成熟整合 | 仍在演進 |
| 功能完整度 | 搭配 Mixin、變數等完整生態 | 僅巢狀本身 |
現代瀏覽器已支援原生 CSS Nesting [來源:〈Using CSS nesting - MDN〉〈https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting〉〈2026〉],但 SCSS 的巢狀成熟度與工具鏈仍較完整。換句話說,原生巢狀能取代「巢狀」這一項功能,但取代不了 SCSS 整套生態。若你對版面結構有興趣,可延伸看 網頁版面設計與排版觀念、網頁排版設計範例參考、Bento Grid 網格版面配置。
巢狀除了選擇器與屬性,還有一個實用的搭配指令 `@at-root`。它的作用是把選擇器編譯到最外層,跳出當下的巢狀脈絡。最常見的場景是把媒體查詢包在元件內部維持可讀性,但又不希望編譯出來的選擇器被層層嵌套拉長:在元件內用 `@at-root (with: media) { @media ... }` 或單純 `@at-root { .modifier {...} }`,就能讓選擇器保持扁平。這對 RWD 斷點較多、又想讓元件樣式自成一個區塊的專案特別有用,是 `&` 之外另一個控制巢狀輸出的工具。相關的響應式版面觀念可看 RWD 響應式網頁設計觀念。
變數、資料型別與設計 token
SCSS 用 `$` 符號宣告變數,支援數字、字串、顏色、布林、null、清單與 maps 共七種資料型別。把品牌主色、字體大小、間距等重複值抽成變數後,只要改最源頭那一行,所有引用處的值會同步更新,這是 SCSS 對設計一致性最大的貢獻。
宣告語法很直觀:`$primary: #28b0b4;` 之後用 `$primary` 引用。命名建議語意化而非具象,也就是 `$color-brand` 優於 `$blue`,因為具象命名在品牌色從藍改成綠之後就變得誤導。這聽起來是小事,但在團隊協作時,命名語意化能省下大量溝通成本。配色觀念可搭配 色彩學與配色技巧解析、品牌色彩挑選指南。
七種型別中,最需要單獨認識的是 maps。它把一個值映射到另一個,例如 `$breakpoints: (sm: 576px, md: 768px, lg: 992px);`,之後用 `map-get` 取值,比散落一堆變數好管理;其餘的數字、字串、顏色、布林、null 與 list 用法直觀,遇到再查即可。作用域方面,變數有全域與區塊作用域,可用 `!global` 跨作用域,但要避免濫用造成追蹤困難。相關主題可看 網站配色計畫實戰、網頁配色工具推薦。
maps 在實戰上最經典的應用是「斷點查詢 Mixin」。把所有斷點存成一份 map,再寫一支接收 key 的 `@mixin respond-to($key)`,內部用 `map-get` 取出寬度並包成媒體查詢。如此一來,整個專案的 RWD 規則都走同一個入口,要新增或調整斷點只要動 map 那一行,不會再有 `@media (max-width: 767px)` 這種魔術數字散落各處。另一個常見用法是把主題色票存成巢狀 map,例如 `$themes: (light: (bg: #fff, text: #222), dark: (bg: #222, text: #eee))`,再搭配 `@each` 迴圈一次產出多組主題的 CSS,這正是 SCSS 編譯期能力勝過手寫 CSS 的地方。
設計 token 思維是把變數集中在一個 `_variables.scss`,等同為專案建立設計系統的單一真實來源。當所有顏色、字級、間距都從這個檔案引用,改色只需要動一個地方,這正是中大型專案能長期維護的關鍵。同一套變數也能帶動 排版設計與字體行距技巧、中文字體挑選與搭配、英文字體推薦與下載 的一致性。
那 SCSS 變數跟原生 CSS 自訂屬性比起來呢?兩者可互補搭配。CSS 自訂屬性能在執行期改值,適合需要動態切換的場景,例如深色模式即時切換;SCSS 變數是編譯期固定,適合品牌色這種一旦定下就不太動的值。兩者各有所長,懂得何時用哪個才是重點。判斷準則很單純:這個值會在使用者操作時即時變動(如主題切換、滑桿拖曳、依捲動位置變化),就用 CSS 自訂屬性交給瀏覽器在執行期算;這個值在建置階段就確定、整站一致(如品牌主色、斷點、字級 scale),就用 SCSS 變數在編譯期定死,輸出的 CSS 還能少掉一層 `var()` 解析成本。最常見的混用模式是把斷點與設計 token 留在 SCSS 編譯期,把深色模式的色票值改用 CSS 自訂屬性,在根元素上用一組 `[data-theme="dark"]` 覆寫即可整站切換。這點跟 RGB 與 CMYK 色彩模式、色相環配色完全手冊 談的色彩模式分工是類似的道理。
拆檔與模組化:@use、部分檔與 7-1 架構
把樣式依功能拆成多個以底線開頭的部分檔,例如 `_variables.scss`、`_buttons.scss`,再用一個主檔統一引入,這就是模組化的基礎。而官方已建議用 @use 與 @forward 取代舊的 @import,因為 @use 有命名空間、不會重複載入、也避免全域變數污染 [來源:〈@import - Sass Documentation〉〈https://sass-lang.com/documentation/at-rules/import/〉〈2026〉]。
部分檔的慣例是檔名以底線開頭,如 `_reset.scss`,代表它不會單獨編譯成 CSS,只供引入用。這個底線是給編譯器看的訊號,讓系統在執行 sass 指令時忽略它,只對開頭沒有底線的檔案生成新的 CSS。Bootstrap 的目錄結構就是這種拆法的經典範例,不少主流框架的原始碼以 SCSS 撰寫。
要特別說明 @import 的歷史包袱:它每次引入都把程式碼貼進來、沒有命名空間、變數全域共用,是編譯變慢與變數衝突的主因,Sass 官方已明確建議改用 @use [來源:〈@import - Sass Documentation〉〈https://sass-lang.com/documentation/at-rules/import/〉〈2026〉]。新專案一律從 @use 起手,能省下日後重構的成本,這條幾乎沒有例外。
| 比較項目 | @import | @use(官方推薦) |
|---|---|---|
| 載入行為 | 每次引入都貼入程式碼 | 每個檔案只載入一次 |
| 命名空間 | 無,全域共用 | 有,透過命名空間存取 |
| 變數衝突風險 | 高 | 低 |
| 編譯結果 | 可能重複產生樣式 | 較乾淨 |
| 官方狀態 | 已棄用 | 推薦 |
@use 的優勢在於透過命名空間存取成員、每個檔案只載入一次、編譯更乾淨,是 Sass 官方推薦做法。搭配 @forward 可以在聚合檔中轉發多個部分檔的成員,方便建立一個對外的統一模組。實務上常把基礎變數、Mixin 統一放在 abstracts 資料夾,再用一個 index 轉發出去,其他檔案只要 `@use 'abstracts' as *` 就能取用。
7-1 架構是中大型專案的常見組織方式,以 7 個分類資料夾加一個 main.scss 構成。這套結構由前端社群在 Hugo Giraudel 等開發者的推廣下廣泛流傳,本身沒有硬性數字規範,但能給團隊一個共同的拆檔語彙。七個資料夾各司其職,main.scss 負責把它們依序引入。
- base:reset、排版基礎、typography 等全站底層樣式。
- components:按鈕、卡片、表單等可重用元件,每個元件一個檔。
- layout:header、footer、grid 等版面結構。
- pages:單一頁面專屬樣式,命名對應頁面。
- themes:多主題或深色模式的覆寫。
- abstracts:變數、Mixin、函式等不直接輸出 CSS 的工具。
- vendors:第三方框架的樣式覆寫與整合。
拆檔策略要配合命名規範才能發揮效果。要記住,7-1 不是鐵律,小專案硬套反而徒增檔案。判斷準則是:專案會長大、有多個主題或斷點、需要設計系統時,這套架構的長期維護優勢才會明顯浮現。這也是為什麼大型電商或品牌網站幾乎都用類似結構,相關設計可參考 RWD 響應式購物網頁設計、RWD 響應式網頁設計觀念、用主題實作 RWD 響應式版面。
@mixin vs @extend:重用樣式的兩條路,用錯會反噬
@mixin 把一段樣式封裝成可帶參數的樣板,用 @include 引入,適合需要彈性傳值或產生瀏覽器前綴的場景。@extend 則是讓選擇器繼承另一個選擇器的樣式,能合併成群組選擇器省字數,但會產生難以預測的選擇器鏈。官方與實務上都建議優先使用 Mixin,@extend 留給真正單純的共用情境。
SCSS 最容易被濫用的功能就是 @extend。它會把選擇器串接成難以預測的群組,在媒體查詢內還有限制。典型的崩壞模式是:用 @extend 繼承一個後來被多人擴充的 class,編譯出的選擇器鏈長到沒人敢動,最後只能整段重寫。這也是為什麼實務上預設就該用 @mixin 帶參數,把 @extend 留給極單純的共用樣式。占位選擇器 `%` 則是折衷方案:用 `%name` 定義的樣式不會自行編譯出來,只供 @extend 使用,適合只想被繼承、不想單獨輸出的共用樣式。
| 比較項目 | @mixin | @extend |
|---|---|---|
| 能否帶參數 | 可,支援預設值 | 不可 |
| 編譯輸出 | 樣式複製到每個引入處 | 選擇器合併成群組 |
| 輸出體積 | 引入越多越大 | 理論上較省,但選擇器鏈可能失控 |
| 媒體查詢內 | 可用 | 有限制 |
| 追蹤難度 | 低 | 高,鏈難預測 |
| 適用情境 | 需傳參或條件邏輯 | 極單純的固定樣式共用 |
決策原則一句話:需要傳參或條件邏輯就用 Mixin;只是純粹共用一段固定樣式、且繼承對象單純,才考慮 @extend。這些細節在寫 UI 原型設計與 Wireframe、Figma UIUX 設計教學 轉成程式碼時特別實用。
對 @extend 較穩當的態度是「懂原理、少使用」。知道它怎麼運作,遇到遺留程式碼才看得懂;但自己寫新專案,預設就用 Mixin。這個立場看起來保守,卻能避掉絕大多數的維護地獄。相關工具與資源可看 Figma 網格系統與排版、Figma 響應式設計排版、免費 UIUX 自學資源。
運算、函式與實戰心法
SCSS 內建的 SassScript 支援加減乘除與取模等數學運算,還能用 @function 自訂函式處理顏色調整、單位換算等需求。但要讓 SCSS 真正長期幫上忙,關鍵是守住幾條紀律:控制巢狀深度、用命名規範(如 BEM)、變數集中管理、並區分 Mixin 與 @extend 的使用時機。
運算能力是 SCSS 的隱藏優勢。`+ - * / %` 都可用於數字與帶單位值,例如算欄寬、間距、字級比例都很方便。但要特別注意除法:因 `/` 與 CSS 字串語法衝突,官方已棄用直接相除,需用 `math.div` 或括號 [來源:〈Operators - Sass Documentation〉〈https://sass-lang.com/documentation/operators/〉〈2026〉]。內建函式如 darken、lighten、rgba、mix 能在編譯期算出衍生色,做主題色變化時不用手動算色碼。`@function` 則可封裝重複計算邏輯,例如依斷點算欄寬。
BEM 命名是搭配 SCSS 的黃金組合。Block__Element--Modifier 讓選擇器扁平、權重可控,與 SCSS 的巢狀互補:用 BEM 把命名打平,再用 SCSS 在檔案內做適度巢狀收納,兩者結合既好讀又好維護。靠命名讓結構清楚,勝過無腦巢狀把選擇器撐長。這個觀念在 最新網頁設計趨勢、網頁設計常見錯誤地雷 裡也能看到一致的脈絡。
實戰心法還有一條:定期檢查編譯後的 CSS 輸出。發現重複或過長的選擇器,就回頭拆 Mixin 或簡化繼承。編譯結果是 SCSS 健康度的體檢報告,不要只看.scss 原始碼自爽。很多看起來整齊的 SCSS,編譯出來的 CSS 卻肥得嚇人,這通常是 @extend 或過深巢狀造成的。網站效能與 Core Web Vitals 效能指標、網站速度優化技巧、網站速度瓶頸診斷解法 息息相關,CSS 肥大會直接拖累分數。
「CSS 肥一點沒關係」這個想法早已過時。Google 已將 Core Web Vitals 列為搜尋排名訊號,網頁體驗指標(LCP、INP、CLS)會直接反映在行動搜尋結果上 [來源:Google Search Central Blog〈Evaluating page experience as a ranking signal〉https://developers.google.com/search/blog/2020/05/evaluating-page-experience〈2020-05-28〉]。大型電商的實測更具體:Rakuten 24 投入 Core Web Vitals 優化後,每位訪客營收提升 53.37%,轉換率提升 33.13% [來源:web.dev〈Why does speed matter?〉https://web.dev/articles/why-speed-matters〈2026〉]。CSS 雖然通常不是 LCP 或 INP 的最大瓶頸,但過大的樣式表會拉長剖析與套用樣式的時間,在關鍵路徑上放大主執行緒的負擔。把編譯輸出控制得精實,等於在效能預算裡幫 CSS 留出安全邊際,這也是定期檢查編譯結果的務實理由。
以一個頁面數約 40-80 頁、走 7-1 架構的中型內容站或品牌網站為例,編譯輸出膨脹是最常見的隱性成本。這類站點若沒有刻意控制,主樣式表gzip 壓縮後大約會落在 60-120 KB(未壓縮約 350-700 KB),其中往往有約 15-30% 是用不到的死碼,主要來源是過深巢狀、@extend 鏈失控,以及@for 迴圈預先產出但頁面從未引用的類別。實務上常見的狀況是:開發者打開.scss 覺得結構乾淨,但用開發者工具的 Coverage 面板一量,才發現首頁實際用到的樣式只佔編譯輸出的一小部分,其餘全是被元件庫或多主題設定拖進來的重量。一個可參考的判斷門檻是:當壓縮後的主 CSS 超過約 100 KB、或 Coverage 顯示未使用比例高於約 30% 時,就值得回頭做一次拆檔與繼承體檢,把沒引用的類別、過長選擇器與重複的 Mixin 收掉。要誠實提醒一點,這類數字只是這類站點的典型幅度,實際值會因主題數量、第三方框架占比與頁面結構差很多,單看一個數字難有絕對好壞;比較務實的做法,是在「可維護的拆檔結構」與「夠精實的輸出體積」之間抓平衡,把 Coverage 與編譯後的 CSS 當成定期體檢指標,而非僅憑原始碼整齊度來判斷好壞。
如果要進一步壓縮輸出,可搭配壓縮工具與 快取 Cache 設定觀念、WordPress 快取加速外掛、CDN 網站加速原理。圖片資源也別忘了用 Lazy Loading 延遲載入、圖片壓縮工具實測、WordPress 圖片優化步驟 處理,前端效能是整體戰。
控制流程:@if、@for、@each、@while 讓樣式會思考
SCSS 真正勝過手寫 CSS 的地方,在於它能跑條件與迴圈。`@if`、`@for`、`@each`、`@while` 這四個指令讓你在編譯期用程式邏輯產出大量規則,而不是用複製貼上把 CSS 撐大。凡是「同一套結構、只有數值或名稱不同」的場景,都值得用迴圈收進來,例如 12 欄網格的欄寬類別、间距 scale、多種尺寸的按鈕、多種斷點的版型變體,這些若手寫會產生幾十行幾乎重複的規則。
用一個具體例子說明 `@each` 與 `@for` 的分工。假設品牌有五種語意色存在 map 裡,要為每種色產出對應的按鈕變體(背景、邊框、hover 加深),手寫要重複五次結構,用 `@each $name, $color in $theme-colors` 一圈就能展開,未來新增色系只要在 map 裡加一行;而 `@if / @else if / @else` 最常落在 Mixin 內依參數分支,例如同一支按鈕 Mixin 依 `$size` 輸出大中小三組 padding 與字級。`@for` 的經典應用是欄寬:`@for $i from 1 through 12 { .col-#{$i} { width: math.div($i, 12) * 100%; } }` 一口氣產出 12 個欄寬類別,比例由編譯器算,人不會算錯。`@while` 較少見,偶爾用於依黃金比例遞增產生字級 scale 這類編譯期數列推算。這類用法在設計系統規模一旦超過十幾個元件時,省下的工時與降低的出錯率非常明顯。
迴圈雖然強大,卻也是新手最容易過度使用的功能。一個常見的雷是拿 `@for` 產出幾十個其實用不到的類別,結果編譯後的 CSS 憑空多出幾 KB 死碼。判斷準則是:這些類別真的會在 HTML 被用到嗎?如果只是「以後可能會用」,就別先產。另一個雷是在迴圈裡巢狀 `@if` 加深選擇器,導致編譯輸出難以預測。穩當的做法是把迴圈寫在檔案最外層、選擇器保持扁平,並定期檢查編譯結果是否出現沒被任何頁面引用的類別。迴圈與條件是 SCSS 相對於原生 CSS 最難被取代的能力,也是評估一個專案值不值得導入 SCSS 的關鍵理由。
SCSS 與原生 CSS、Tailwind 的取捨
值得學,但理由要更新。原生 CSS 的變數與巢狀已能取代 SCSS 部分功能,Tailwind 則用公用類名解決了重複樣式問題。不過 SCSS 在 Mixin、迴圈、條件判斷、顏色運算與大型專案的模組化拆檔上仍有不可替代的優勢。比較務實的定位是把它當成在既有 CSS 工作流上疊加編譯期能力的工具,按專案規模選用,而非一體適用的萬靈丹。
先講被取代的部分。變數可用 CSS 自訂屬性取代,巢狀可用原生 Nesting 取代 [來源:〈Using CSS nesting - MDN〉〈https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting〉〈2026〉],小專案不一定需要 SCSS。如果你的專案只有幾頁、樣式變動頻率低,硬導入 SCSS 反而是負擔,光設定編譯流程就比寫樣式還久。
但 SCSS 仍有獨佔能力:@mixin 帶參、@for 與 @each 迴圈、@if 條件、編譯期顏色運算、模組化拆檔。這些是原生 CSS 目前做不到或做起來很彆扭的。尤其是迴圈與條件,在產生多欄網格、多主題樣式時能省下大量重複手寫,差別非常明顯。判斷準則是:專案會長大、有多個主題或斷點、需要設計系統時,SCSS 的長期維護優勢才會明顯浮現。
| 能力 | 原生 CSS | SCSS | Tailwind |
|---|---|---|---|
| 變數 | 自訂屬性,執行期可改 | 編譯期固定 | 設定檔 token |
| 巢狀 | 原生 Nesting(較新瀏覽器) | 完整成熟 | 不適用 |
| 帶參樣板 | 不支援 | @mixin | 元件類別 |
| 迴圈與條件 | 不支援 | @for/@each/@if | 不支援 |
| 顏色運算 | 有限 | 編譯期完整 | 設定檔產生 |
| 適合場景 | 小專案、動態切換 | 中大型、設計系統 | 版型快速搭建 |
與 Tailwind 的關係並非互斥。常見搭配是 Tailwind 處理版型與間距,SCSS 處理設計 token 與複雜元件。兩者各擅其場,硬要二選一反而綁死自己。學習投資報酬率方面,會 SCSS 能無痛接手大量既有專案與框架,不少主流框架的原始碼以 SCSS 撰寫,會看 SCSS 等於拿到讀懂這些框架原始碼的鑰匙。架站工具選擇可參考 寫程式與架站平台比較、WordPress 佈景主題推薦、Astra 主題入門教學。
真要給一個收斂的判斷框架:專案小、樣式少、變動低,用原生 CSS 就夠;要快速搭建版型、團隊接受 utility-first,Tailwind 很合;但只要專案會長到多頁、多主題、需要設計系統,SCSS 的模組化與編譯期能力就值得投資。回頭檢查編譯出來的 CSS 就知道寫得好不好:權重平不平、選擇器短不短、變數與 Mixin 有沒有重複定義。這幾個判準在 Elementor 頁面編輯器教學、Bricks Builder 視覺化編輯器、Divi 主題完整指南 這類工具的自訂樣式上同樣成立。
回顧一下整篇的重點:判斷一個專案該不該導入 SCSS,看的不是檔案多寡,而是樣式會不會反覆修改。只要同一個顏色或間距出現在超過三個地方,把它抽成變數的投資就開始回本。從 @use 起手、控制巢狀深度、優先用 Mixin 而非 @extend,這三條紀律守住,半年後回頭改樣式才不會想重寫。手機版排序調整可看 用 CSS 調整手機版排序。
SCSS 疑難排解:編譯失敗與除錯對照表
SCSS 的問題九成出現在編譯階段,學會看懂錯誤訊息能省下大量瞎猜的時間。底下整理開發者最常碰到的幾類編譯錯誤、成因與排查方向。通用原則是:錯誤訊息會附上行號與檔名,先依行號打開對應的.scss,再對照訊息類型判斷。搭配前述的 source map,瀏覽器開發者工具能把套用樣式的行數指回原始.scss,排查選擇器或覆寫問題時尤其好用。
| 錯誤訊息或症狀 | 常見成因 | 排查方向 |
|---|---|---|
| Error: Undefined variable | 使用了未宣告的變數,或變數在另一個檔案卻沒有用 @use 引入 | 確認變數已宣告,並透過 @use 加命名空間引入 |
| Error: wrong number of arguments | 呼叫 Mixin 或函式時參數數量不符 | 核對 Mixin 定義的參數清單與預設值 |
| Error: top-level expression parsing failed | 除法用了裸 `/`,已被官方棄用 | 改用 math.div,或把算式用括號包起來 |
| 編譯成功但樣式沒生效 | 選擇器權重被覆蓋,或快取未清 | 用開發者工具檢視套用來源,確認權重與來源檔 |
| 編譯出的選擇器異常肥長 | 巢狀過深或 @extend 鏈失控 | 把巢狀壓到 3 層內,改用 Mixin 或占位選擇器 |
| Color 函式報錯或回傳異常 | 傳入的顏色不是合法顏色型別(如字串色名拼錯) | 確認變數型別為顏色,必要時加型別註記檢查 |
除錯還有一個進階技巧:`@debug` 與 `@warn`。在 Mixin 或函式內用 `@debug $value;` 編譯時會把變數內容印到終端機,等於在編譯期下中斷點;`@warn` 則印警告但不中斷編譯,適合提醒自己某個參數走到了非預期分支。這兩個指令對排查迴圈產出的內容、確認 map 是否正確展開非常實用,是 SCSS 開發者該熟悉的除錯工具。把錯誤訊息當成線索而非障礙,是脫離新手期的關鍵心態。
導入 SCSS 前的最後檢查清單
決定導入 SCSS 之前,跑一次這份清單能避免日後重構。每一項都對應到前述章節談過的工程化觀念,把答案寫下來,等於為專案的樣式架構做一次體檢。
- 編譯器確認裝的是 Dart Sass,而非已停止維護的 node-sass。
- 引入檔案一律用 @use 與 @forward,杜絕 @import。
- 部分檔以底線開頭命名,只留一個 main.scss 對外編譯。
- 變數集中在 `_variables.scss`,命名採語意而非具象($color-brand 優於 $blue)。
- 巢狀深度控制在 3 層以內,搭配 BEM 把選擇器打平。
- 重用樣式優先用 @mixin 帶參數,@extend 只留給極單純的固定共用。
- 除法一律用 math.div,不再使用裸 `/`。
- 迴圈只產出實際會用到的類別,避免編譯出死碼。
- 設定 `--watch` 或建置腳本自動編譯,並輸出 source map 供除錯。
- 定期檢查編譯後的 CSS,移除重複樣式與過長選擇器。
這份清單不是教條,而是一組可勾選的工程檢查點。能在專案初期就守住這十條,後續不論是接手他人程式碼或擴充設計系統,阻力都會小很多。SCSS 的價值最終會反映在「改一個顏色不用全專案搜尋替換、新增一個斷點不會漏掉任何元件」這類日常體感上,這才是它值得學的核心理由。
常見問題 FAQ
SASS 跟 SCSS 有什麼不同?要學哪一個?
兩者是同一個預處理器的兩種語法。SASS 是縮排式、無括號分號;SCSS 保留大括號、與 CSS 完全相容。因為 SCSS 學習成本最低、官方文件與社群都以它為主,新手直接從 SCSS 學起即可,除非要接手既有的縮排式專案才需要碰 SASS。
SCSS 要怎麼安裝與編譯出 CSS?
跨平台最普遍的方式是用 npm install -g sass,Mac 可用 brew install sass,不想碰指令列則裝 GUI 工具。裝好後用 sass -v 確認版本,接著用 sass --watch 輸入.scss:輸出.css 讓存檔自動重新編譯,瀏覽器就能即時看到改動。
@mixin 和 @extend 到底該用哪一個?
需要帶參數或條件邏輯就選 @mixin,用 @include 引入;@extend 雖然能把選擇器合併省字數,卻會串接成難以預測的選擇器鏈,在媒體查詢內還有限制。實務上優先用 Mixin,只有極單純的固定樣式共用才考慮 @extend。
SCSS 會被原生 CSS 巢狀或 Tailwind 取代嗎?
部分功能會被取代,例如變數與巢狀已有原生方案,小專案不一定要 SCSS。但 SCSS 在帶參 Mixin、迴圈、條件判斷、編譯期顏色運算與大型專案模組化拆檔上仍不可替代,與 Tailwind 也能互補搭配,不會被完全取代。
SCSS 可以做數學運算嗎?
可以。SCSS 支援加減乘除與取模,可用於數字與帶單位值。但要留意除法因與 CSS 語法衝突,需改用 math.div 或括號;也能用 @function 自訂函式封裝重複計算,例如依斷點算欄寬。
新手學 SCSS 最常踩哪些雷?
最常見的三個雷是:安裝與監聯指令搞不定、巢狀寫太深導致選擇器又長又難覆寫、濫用 @extend 編譯出失控的選擇器鏈。對應解法是熟練 sass --watch、把巢狀控制在 3 層內、預設改用 @mixin 帶參數。