什麼是 CSS in JS?
CSS in JS 是一種將 CSS 樣式直接撰寫在 JavaScript 或 TypeScript 檔案中的開發模式,特別盛行於 React 生態系。其核心目標在於透過「元件化」來解決傳統 CSS 的全域命名衝突、樣式冗餘與死程式碼清理(Dead Code Elimination)等問題。主流工具如 styled-components 利用標籤模板字串實現樣式與邏輯的緊密綁定;而 CSS Modules 則透過工具自動混淆 Class 名稱達成隔離。這項技術不僅提升了開發速度與程式碼搬移的便利性,更讓樣式能根據元件的 Props 動態調整,是現代前端實現高度模組化的關鍵技術。
什麼是 CSS in JS:解決 CSS 命名問題的新思路
CSS in JS 解決了 CSS 命名 的問題。
由於 component-based 的概念興起,元件開發成為顯學,CSS in JS 提供了將樣式寫在元件中解決方案,也讓 CSS 需要從寫程式語言的角度去進行架構設計。
CSS in JS 不僅降低了維護難度也加速了開發速度,減少檔案切換和減少 class 命名錯誤等等問題,常見的 library 像是 CSS Modules、vanilla-extract、styled-components、styled-jsx (Next.js) 都非常好上手,更完整的將元件模組化並增加可重用性。
CSS in JS 缺點也要先說在前面,當需要 Server Render 時,相關的效能問題也需要一併考慮進去。
CSS in JS 像是把需要打扮的道具跟裝備直接跟使用的情境整合在一起,像是約會必勝穿搭、適合上班的妝容等等,在遇到相關情境時能夠輕鬆應對。
問題定義
- 當元件在其他專案使用時,搬動除了必須搬完相對應的樣式檔,還必須放在正確的位置。
- 在專案最佳化時,樣式檔的引用順序須讓機器不會混淆,若將樣式檔拆太細,很可能發生 Code Splitting 時順序錯誤。
CSS in JS 的優點與解決的問題
- 解決 Code Splitting 可能出現的順序問題。
- 解決命名互相覆蓋,在撰寫樣式檔時也可以用 BEM 的命名規則避開或導入原子化樣式設計。
- 維護時不需要再去找到底被哪個樣式檔影響。
CSS in JS 的缺點與挑戰
- RWD 不像 Bootstrap 有格線系統那樣使用方便,所以可以額外導入 CSS 框架 的格線系統混合使用。
- 較難做效果跟做覆蓋,不同狀態需要不同樣式時要再封裝一層。
- 語法的高亮、自動完成、防呆較不完整。
- 少了可以共用樣式的好處,像是
@extend或@mixin這樣的寫法,需把元件切的夠小,才會有一定程度的共用性。
styled-components:使用 JavaScript 撰寫 CSS 的框架
styled-components 提供了在 JavaScript 中直接撰寫 CSS 的介面,意謂著可以使用所有的 CSS 功能。切換主視覺要多用一個 <ThemeProvider>,傳入的 Props 差異太大時有點麻煩。
1 | import styled from "styled-components"; |
套用主視覺配置
styled-components 也提供了主視覺的配置,透過提供的 ThemeProvider 在外層注入就可以在元件中直接取值。
1 | import { ThemeProvider } from "styled-components"; |
在元件中直接取值,甚至可以寫 Function 進行判斷:
1 | const StyleWrapper = styled.div` |
RWD 實作
由於 styled-components 提供了 function 的撰寫模式,所以即使撰寫 RWD 的元件也很簡單:
1 | function getWidthString(span) { |
styled-jsx:Next.js 內建的 CSS in JS 解決方案
styled-jsx 則是 Next.js 內建支援的介面,寫法上稍微不同,使用 <style jsx> 標籤:
1 | function Sample() { |
CSS Modules:解決 CSS 命名衝突的方案
CSS Modules 是用來解決 CSS 命名衝突 的問題。在 Create React App 中,CSS 命名規則為 {檔名}.module.css。
main.module.css
1 | .information { |
page.module.css
1 | .information { |
1 | import styleMain from "./main.module.css"; |
StyleX:Facebook 推出的 Atomic CSS in JS 解決方案
Facebook 推出的 Atomic CSS in JS 解決方案 StyleX 上線啦!透過 Build Time 就處理好的樣式效能海放 Run Time 的 styled-components,同時也減少了要背一堆框架內建的 Util CSS 語法。
1 | const styles = stylex.create({ |
經過編譯後,會自動產生一個動態的 class 以及對應的樣式,完整的解決了命名問題並同時提供原子化樣式的優點。
FAQ:CSS in JS 常見問題
Q1:CSS in JS 會導致頁面效能下降嗎?
A:這取決於您使用的庫。Run-time 類型的庫(如 styled-components)會在執行期計算樣式並注入 DOM,在大型元件樹中可能會有些微開銷。而 Compile-time 類型的庫(如 StyleX 或 Vanilla Extract)則在打包時就生成靜態 CSS,效能幾乎與傳統 CSS 一致。
Q2:使用 CSS in JS 該如何處理 Server-Side Rendering (SSR)?
A:庫如 styled-components 需要額外配置(如使用 ServerStyleSheet)來收集首屏所需的樣式,並在伺服器端將其注入到 HTML 中,以避免出現無樣式內容閃爍 (FOUC) 的問題。Next.js 內建的 styled-jsx 則已處理好此部分。
Q3:CSS Modules 與 Styled Components 該如何選?
A:如果您偏好將 CSS 與 JS 完全分離,並使用傳統的 CSS 語法,CSS Modules 是穩健的選擇;如果您希望樣式與邏輯深度整合,並享受 Props 傳遞帶來的動態樣式便利性,styled-components 則能提供更優雅的開發體驗。
掌握了 CSS in JS,您就能為您的 React 元件穿上最合適的「裝備」。無論是選擇靈活的 styled-components,還是效能卓越的 StyleX,建立一致的開發規範才是專案成功的核心!
喜歡這篇文章,請幫忙拍拍手喔 🤣
