什麼是 styled-components?
styled-components 允許你使用 JavaScript 來定義帶有樣式的 React 元件。它透過 標籤模板字面量(Tagged Template Literals) 將 CSS 樣式直接嵌入到 JavaScript 程式碼中,並將樣式綁定到特定的元件。這樣可以讓樣式與元件緊密結合,避免傳統 CSS 檔案中樣式可能造成的全局污染問題。
它的核心理念是:
-
元件化樣式:每個元件的樣式都獨立封裝,不會影響其他元件。
-
動態樣式:可以根據元件的 props 或 state 動態調整樣式。
-
直觀語法:使用熟悉的 CSS 語法,但寫在 JavaScript 中,易於上手。
-
自動優化:自動為樣式生成唯一的 class 名稱,減少命名衝突。
styled-components 的主要特點
-
元件化的樣式管理 你可以為每個 React 元件創建專屬的樣式,這些樣式只會套用到該元件,不會影響其他元件。這解決了傳統 CSS 中樣式可能意外互相干擾的問題。
-
支援 CSS 語法 styled-components 使用標準的 CSS 語法,像是 background-color、padding 等,對於熟悉 CSS 的前端工程師來說非常直觀。你甚至可以直接複製現有的 CSS 程式碼貼到 styled-components 中使用。
-
動態樣式(Props 支援) 你可以根據元件的 props 或 state 動態改變樣式。例如,根據按鈕的狀態(像是 disabled 或 active)來改變背景顏色。
-
主題(Theme)支援 styled-components 提供 ThemeProvider,讓你定義全局主題(例如顏色、字型等),並在所有元件中輕鬆引用,方便統一管理樣式。
-
自動處理瀏覽器前綴 它會自動為 CSS 屬性添加必要的瀏覽器前綴(例如 -webkit- 或 -moz-),省去手動處理的麻煩。
-
巢狀樣式與偽類 你可以像寫 SCSS 一樣,使用巢狀選擇器(&)來撰寫子元素樣式或偽類(如 :hover、:focus),讓程式碼更簡潔。
-
伺服器端渲染(SSR)支援 styled-components 支援伺服器端渲染,能確保樣式在伺服器端正確渲染,適合用於 Next.js 等框架。
基本使用方式
以下是一個簡單的範例,展示如何使用 styled-components 來定義一個帶樣式的按鈕元件:
import styled from 'styled-components';
// 定義一個樣式化的按鈕元件
const Button = styled.button`
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
/* 支援偽類 */
&:hover {
background-color: #0056b3;
}
/* 根據 props 動態改變樣式 */
background-color: ${props => (props.primary ? '#28a745' : '#007bff')};
`;
// 在 React 元件中使用
function App() {
return (
<div>
<Button>普通按鈕</Button>
<Button primary>主要按鈕</Button>
</div>
);
}
export default App;
程式碼說明:
-
styled.button 創建了一個樣式化的
<button>元素,樣式寫在反引號(`)中。 -
樣式中可以使用標準 CSS 屬性,並支援偽類(如 :hover)。
-
透過 props 可以動態改變樣式,例如當 primary 屬性為 true 時,背景顏色會變成綠色。
進階功能範例
1. 使用 ThemeProvider 管理主題
ThemeProvider 讓你定義全局主題,方便在多個元件中重複使用樣式。
import styled, { ThemeProvider } from 'styled-components';
// 定義主題
const theme = {
colors: {
primary: '#007bff',
success: '#28a745',
},
};
// 定義樣式化的元件
const Button = styled.button`
background-color: ${props => props.theme.colors.primary};
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: ${props => props.theme.colors.success};
}
`;
// 在 React 元件中使用 ThemeProvider
function App() {
return (
<ThemeProvider theme={theme}>
<Button>主題按鈕</Button>
</ThemeProvider>
);
}
export default App;
程式碼說明:
-
ThemeProvider 將 theme 物件傳遞給所有子元件。
-
在樣式中透過 props.theme 存取主題中的值(如 colors.primary)。
2. 巢狀樣式
你可以使用 & 來表示當前元件,並撰寫巢狀樣式。
import styled from 'styled-components';
const Card = styled.div`
background-color: #f8f9fa;
padding: 20px;
border-radius: 8px;
& h2 {
color: #343a40;
font-size: 24px;
}
& p {
color: #6c757d;
font-size: 16px;
}
`;
function App() {
return (
<Card>
<h2>卡片標題</h2>
<p>這是一段卡片內容。</p>
</Card>
);
}
export default App;
程式碼說明:
- & h2 表示 Card 內部的
<h2>元素,樣式只會套用到 Card 內的子元素。
3. 繼承樣式
你可以讓一個樣式化的元件繼承另一個元件的樣式,並加以修改。
import styled from 'styled-components';
const Button = styled.button`
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
`;
const LargeButton = styled(Button)`
padding: 15px 30px;
font-size: 18px;
`;
function App() {
return (
<div>
<Button>普通按鈕</Button>
<LargeButton>大型按鈕</LargeButton>
</div>
);
}
export default App;
程式碼說明:
- LargeButton 繼承了 Button 的樣式,並覆蓋了 padding 和 font-size。
優點與適用場景
優點:
-
樣式封裝:樣式只作用於特定元件,避免全局樣式衝突。
-
動態性:透過 props 和 state 輕鬆實現動態樣式。
-
易於維護:樣式與元件寫在一起,方便追蹤和修改。
-
與 React 高度整合:非常適合 React 專案,尤其是需要元件化開發的場景。
適用場景:
-
適合用於中大型 React 專案,尤其是需要高度模組化的 UI 元件。
-
當你需要動態樣式(例如根據使用者輸入或狀態改變樣式)。
-
當你希望樣式與元件緊密結合,避免管理多個 CSS 檔案。
注意事項
-
學習曲線:如果你不熟悉 JavaScript 模板字面量或 React props,可能需要一點時間適應。
-
效能考量:在大型專案中,過多的動態樣式可能影響渲染效能,建議適度使用。
-
與其他 CSS 方案的比較:
-
相較於傳統 CSS/SCSS,styled-components 更適合元件化開發,但可能不適合需要大量靜態樣式的專案。
-
相較於 Tailwind CSS,它更靈活於動態樣式,但語法不如 Tailwind 簡潔。
-
總結
styled-components 是一個強大且靈活的工具,特別適合用於 React 專案中管理元件樣式。它的語法直觀、支援動態樣式,且與 React 的元件化理念高度契合。透過簡單的學習,你可以快速上手,並打造出乾淨、可維護的 UI 元件。