使用 shadcn/ui 前該補的 TailwindCSS 基礎知識(三) - TailwindCSS v4 基礎語法速查

本文是「使用 shadcn/ui 前該補的 TailwindCSS 基礎知識」系列文章的第三篇
系列文章:
- 從 MUI 到 TailwindCSS 設計哲學的轉變
- 理解 TailwindCSS 的運作原理
- TailwindCSS v4 基礎語法速查(本篇)
- 深入 TailwindCSS v4 的進階配置
- shadcn/ui 生態系工具鏈
顏色系統
TailwindCSS 的顏色系統非常直覺,格式為:{屬性}-{顏色}-{深淺度}
基礎顏色語法
語法規則說明:
- 屬性: 要套用顏色的 CSS 屬性,例如:
bg-= background-color (背景色)text-= color (文字顏色)border-= border-color (邊框顏色)
- 顏色: TailwindCSS 預設提供的顏色名稱,包含:
- 灰階:
slate,gray,zinc,neutral,stone - 色彩:
red,orange,amber,yellow, ...
- 灰階:
- 深淺度: 從
50(最淺) 到950(最深),詳見下方說明
完整屬性、顏色參考: TailwindCSS Colors 官方文件
// 背景色
<div className="bg-blue-500">藍色背景</div>
<div className="bg-red-600">紅色背景(較深)</div>
<div className="bg-green-400">綠色背景(較淺)</div>
// 文字顏色
<p className="text-gray-700">深灰色文字</p>
<p className="text-blue-500">藍色文字</p>
// 邊框顏色
<div className="border border-red-500">紅色邊框</div>
顏色深淺度規則:
50 - 最淺(幾乎是白色)
100 - 很淺
200 - 淺
300 - 稍淺
400 - 中淺
500 - 標準(預設)
600 - 中深
700 - 深
800 - 很深
900 - 最深(幾乎是黑色)
950 - 極深(v3.2+ 新增)
語意化顏色(Shadcn/ui 使用的方式)
在 shadcn/ui 官方範例專案的 index.css 或 globals.css 中,你會看到像這樣的定義:
@theme inline {
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
}
:root {
--primary: oklch(0.6171 0.1375 39.0427);
--primary-foreground: oklch(1 0 0);
--secondary: oklch(0.9245 0.0138 92.9892);
--secondary-foreground: oklch(0.2 0 0);
/* ... */
}
CSS 變數如何變成 utility classes?
TailwindCSS v4 的 @theme inline 會自動將 CSS 變數轉換為 utility classes,規則如下:
- CSS 變數格式:
--color-{顏色名稱} - 生成的 utility:
{屬性}-{顏色名稱}
範例對應:
--color-primary→bg-primary,text-primary,border-primary--color-primary-foreground→bg-primary-foreground,text-primary-foreground--color-destructive→bg-destructive,text-destructive
然後在元件中使用:
// primary 是藍色背景,primary-foreground 是白色文字
<button className="bg-primary text-primary-foreground">
主要按鈕
</button>
// destructive 是紅色背景,destructive-foreground 是白色文字
<button className="bg-destructive text-destructive-foreground">
刪除按鈕
</button>
foreground 是「前景色」,通常指該背景色上的文字顏色。shadcn/ui 會為每個語意化顏色提供一對顏色:主色(如 primary)作為背景色,前景色(如 primary-foreground)作為該背景上的文字顏色,確保有足夠的對比度。
為什麼要用語意化顏色?
// ❌ 使用固定顏色:如果要改主題色,要改很多地方
<button className="bg-blue-500 text-white">按鈕</button>
<div className="border-blue-500">邊框</div>
<p className="text-blue-600">文字</p>
// ✅ 使用語意化顏色:只需要改 CSS 變數,所有地方自動更新
<button className="bg-primary text-primary-foreground">按鈕</button>
<div className="border-primary">邊框</div>
<p className="text-primary">文字</p>
透明度控制
TailwindCSS 支援兩種透明度語法:
// 方法 1:使用 / 語法(推薦)
<div className="bg-blue-500/50">50% 透明度的藍色</div>
<div className="bg-red-500/75">75% 透明度的紅色</div>
<div className="text-gray-900/80">80% 透明度的文字</div>
// 方法 2:使用 opacity 屬性(影響整個元素)
<div className="bg-blue-500 opacity-50">整個元素 50% 透明</div>
重點提醒:
bg-blue-500/50只影響背景色,而opacity-50會影響整個元素(包括子元素)。
文字與字型
字體大小
<p className="text-xs">極小文字 (0.75rem)</p>
<p className="text-sm">小文字 (0.875rem)</p>
<p className="text-base">基礎文字 (1rem)</p>
<p className="text-lg">大文字 (1.125rem)</p>
<p className="text-xl">特大文字 (1.25rem)</p>
<p className="text-2xl">2倍大 (1.5rem)</p>
<p className="text-3xl">3倍大 (1.875rem)</p>
<p className="text-4xl">4倍大 (2.25rem)</p>
規則: text-{size},size 從 xs 到 9xl
字體粗細
<p className="font-thin">極細 (100)</p>
<p className="font-light">細 (300)</p>
<p className="font-normal">正常 (400)</p>
<p className="font-medium">中等 (500)</p>
<p className="font-semibold">半粗 (600)</p>
<p className="font-bold">粗體 (700)</p>
<p className="font-extrabold">特粗 (800)</p>
行高與字距
<p className="leading-none">無行高</p>
<p className="leading-tight">緊湊行高</p>
<p className="leading-normal">正常行高</p>
<p className="leading-relaxed">寬鬆行高</p>
<p className="leading-loose">很寬鬆行高</p>
// 字距
<p className="tracking-tighter">極緊字距</p>
<p className="tracking-tight">緊字距</p>
<p className="tracking-normal">正常字距</p>
<p className="tracking-wide">寬字距</p>
<p className="tracking-widest">極寬字距</p>
文字對齊與裝飾
<p className="text-left">靠左對齊</p>
<p className="text-center">置中對齊</p>
<p className="text-right">靠右對齊</p>
<p className="text-justify">兩端對齊</p>
// 裝飾
<p className="underline">底線</p>
<p className="line-through">刪除線</p>
<p className="no-underline">移除底線</p>
// 大小寫
<p className="uppercase">全部大寫</p>
<p className="lowercase">全部小寫</p>
<p className="capitalize">首字母大寫</p>
間距系統(Spacing)
TailwindCSS 的間距系統是最重要的概念之一。預設的間距單位是 0.25rem(4px)。
間距規則
數字 × 0.25rem = 實際大小
0 → 0
1 → 0.25rem (4px)
2 → 0.5rem (8px)
3 → 0.75rem (12px)
4 → 1rem (16px)
6 → 1.5rem (24px)
8 → 2rem (32px)
12 → 3rem (48px)
16 → 4rem (64px)
Margin(外距)
// 四個方向
<div className="m-4">四周 margin 1rem</div>
// 單一方向
<div className="mt-4">上方 margin</div>
<div className="mr-4">右方 margin</div>
<div className="mb-4">下方 margin</div>
<div className="ml-4">左方 margin</div>
// 水平/垂直
<div className="mx-4">左右 margin</div>
<div className="my-4">上下 margin</div>
// 自動置中
<div className="mx-auto">水平置中</div>
// 負值
<div className="-mt-4">負 margin(向上移動)</div>
Padding(內距)
// 四個方向
<div className="p-4">四周 padding 1rem</div>
// 單一方向
<div className="pt-4">上方 padding</div>
<div className="pr-4">右方 padding</div>
<div className="pb-4">下方 padding</div>
<div className="pl-4">左方 padding</div>
// 水平/垂直
<div className="px-4">左右 padding</div>
<div className="py-4">上下 padding</div>
Gap(Flexbox/Grid 間距)
// Flexbox 範例
<div className="flex gap-4">
<div>項目 1</div>
<div>項目 2</div>
<div>項目 3</div>
</div>
// Grid 範例
<div className="grid grid-cols-3 gap-6">
<div>格子 1</div>
<div>格子 2</div>
<div>格子 3</div>
</div>
// 分別控制水平/垂直間距
<div className="flex flex-col gap-y-4 gap-x-8">
{/* 垂直間距 4, 水平間距 8 */}
</div>
版面配置(Layout)
Display 屬性
<div className="block">區塊元素</div>
<div className="inline">行內元素</div>
<div className="inline-block">行內區塊</div>
<div className="flex">Flexbox 容器</div>
<div className="grid">Grid 容器</div>
<div className="hidden">隱藏元素</div>
Flexbox 布局
// 基礎 Flex 容器
<div className="flex">
<div>項目 1</div>
<div>項目 2</div>
</div>
// 方向
<div className="flex flex-row">水平排列(預設)</div>
<div className="flex flex-col">垂直排列</div>
<div className="flex flex-row-reverse">水平反向</div>
<div className="flex flex-col-reverse">垂直反向</div>
// 主軸對齊 (justify-content)
<div className="flex justify-start">靠左</div>
<div className="flex justify-center">置中</div>
<div className="flex justify-end">靠右</div>
<div className="flex justify-between">兩端對齊</div>
<div className="flex justify-around">環繞對齊</div>
// 交叉軸對齊 (align-items)
<div className="flex items-start">頂部對齊</div>
<div className="flex items-center">垂直置中</div>
<div className="flex items-end">底部對齊</div>
<div className="flex items-stretch">拉伸(預設)</div>
// 換行
<div className="flex flex-wrap">允許換行</div>
<div className="flex flex-nowrap">不換行(預設)</div>
Grid 布局
// 基礎 Grid
<div className="grid grid-cols-3 gap-4">
{/* ^^^^^^^^^^^^^ 3欄 ^^^^^ 間距 */}
<div>1</div>
<div>2</div>
<div>3</div>
</div>
// 響應式 Grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{/* ^^^^^^^^ 手機1欄 ^^^^^^ 平板2欄 ^^^^^^ 桌面3欄 */}
</div>
// 自動填充
<div className="grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))]">
{/* 自動根據容器寬度決定欄數 */}
</div>
尺寸控制
寬度
// 固定寬度
<div className="w-64">寬度 16rem (256px)</div>
<div className="w-96">寬度 24rem (384px)</div>
// 百分比
<div className="w-1/2">50% 寬度</div>
<div className="w-1/3">33.333% 寬度</div>
<div className="w-2/3">66.666% 寬度</div>
<div className="w-full">100% 寬度</div>
// 特殊值
<div className="w-screen">100vw(視窗寬度)</div>
<div className="w-auto">自動寬度</div>
<div className="w-fit">適應內容</div>
// 最小/最大寬度
<div className="min-w-0">最小寬度 0</div>
<div className="max-w-md">最大寬度 28rem</div>
<div className="max-w-screen-lg">最大寬度 1024px</div>
高度
// 固定高度
<div className="h-64">高度 16rem</div>
<div className="h-screen">100vh(視窗高度)</div>
// 百分比
<div className="h-full">100% 高度</div>
<div className="h-1/2">50% 高度</div>
// 最小/最大高度
<div className="min-h-screen">最小高度 100vh</div>
<div className="max-h-96">最大高度 24rem</div>
Size(同時設定寬高)
// v4 新增:size 屬性
<div className="size-16">寬高都是 4rem</div>
<div className="size-full">寬高都是 100%</div>
// 實務範例:圖標按鈕
<button className="size-9 rounded-md">
<Icon />
</button>
邊框與圓角
邊框
// 基礎邊框
<div className="border">1px 邊框(四周)</div>
<div className="border-2">2px 邊框</div>
<div className="border-4">4px 邊框</div>
// 單邊邊框
<div className="border-t">上邊框</div>
<div className="border-r">右邊框</div>
<div className="border-b">下邊框</div>
<div className="border-l">左邊框</div>
// 邊框顏色
<div className="border border-gray-300">灰色邊框</div>
<div className="border border-blue-500">藍色邊框</div>
// 邊框樣式
<div className="border border-solid">實線(預設)</div>
<div className="border border-dashed">虛線</div>
<div className="border border-dotted">點線</div>
圓角
// 預設圓角
<div className="rounded">0.25rem 圓角</div>
<div className="rounded-md">0.375rem 圓角</div>
<div className="rounded-lg">0.5rem 圓角</div>
<div className="rounded-xl">0.75rem 圓角</div>
<div className="rounded-2xl">1rem 圓角</div>
<div className="rounded-full">完全圓形</div>
// 單角圓角
<div className="rounded-t-lg">上方圓角</div>
<div className="rounded-r-lg">右方圓角</div>
<div className="rounded-b-lg">下方圓角</div>
<div className="rounded-l-lg">左方圓角</div>
// 單一角落
<div className="rounded-tl-lg">左上圓角</div>
<div className="rounded-tr-lg">右上圓角</div>
<div className="rounded-br-lg">右下圓角</div>
<div className="rounded-bl-lg">左下圓角</div>
實務範例: 使用語意化圓角
自定義語意化的圓角變數:
/* index.css */
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
:root {
--radius: 0.5rem;
}
語意化圓角的使用規則:
圓角的轉換規則與顏色類似,都會移除類型前綴:
- CSS 變數格式:
--radius-{大小} - 生成的 utility:
rounded-{大小}(移除radius-前綴)
範例對應:
--radius-sm→rounded-sm--radius-md→rounded-md--radius-lg→rounded-lg--radius-xl→rounded-xl
// 使用語意化圓角
<div className="rounded-sm">較小圓角</div>
<div className="rounded-lg">標準圓角</div>
<div className="rounded-xl">較大圓角</div>
對比說明:
- 顏色:
--color-primary→bg-primary(移除color-前綴)- 圓角:
--radius-lg→rounded-lg(移除radius-前綴)
狀態變化(Pseudo-classes)
Hover 狀態
<button className="bg-blue-500 hover:bg-blue-600">
滑鼠移上去會變深藍色
</button>
<a className="text-blue-500 hover:underline">
滑鼠移上去會有底線
</a>
// 多個 hover 效果
<button className="bg-white hover:bg-gray-100 hover:shadow-lg transition">
滑鼠移上去:背景變灰 + 陰影變大
</button>
Focus 狀態
<input
className="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200"
placeholder="點擊輸入框看效果"
/>
// 移除預設 outline
<button className="focus:outline-none focus:ring-2 focus:ring-blue-500">
自訂 focus 樣式
</button>
Active 狀態
<button className="bg-blue-500 active:bg-blue-700">點擊時會變更深</button>
Disabled 狀態
<button
className="bg-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
disabled
>
停用按鈕
</button>
響應式設計
TailwindCSS 使用 mobile-first 的響應式設計。
斷點規則
(無前綴) 所有尺寸(從 0px 開始)
sm: 640px 以上
md: 768px 以上
lg: 1024px 以上
xl: 1280px 以上
2xl: 1536px 以上
重要觀念:沒有前綴的 class 會套用到所有尺寸
// 這行的意思是:
<div className="flex flex-col md:flex-row">
{/* 0-767px: flex-col(垂直排列)*/}
{/* 768px以上: flex-row(水平排列)*/}
</div>
// 完整解釋:
// - flex:所有尺寸都是 Flexbox
// - flex-col:預設(0px起)使用垂直排列
// - md:flex-row:768px 以上改用水平排列
響應式範例
// 不同螢幕尺寸顯示不同文字大小
<h1 className="text-2xl md:text-4xl lg:text-6xl">
{/* 0-767px: text-2xl */}
{/* 768-1023px: text-4xl */}
{/* 1024px以上: text-6xl */}
響應式標題
</h1>
// 不同螢幕尺寸不同布局
<div className="flex flex-col md:flex-row">
{/* 0-767px: 垂直排列 */}
{/* 768px以上: 水平排列 */}
<div>左側</div>
<div>右側</div>
</div>
// 不同螢幕尺寸顯示/隱藏
<div className="hidden md:block">
{/* 0-767px: 隱藏 */}
{/* 768px以上: 顯示 */}
桌面版選單
</div>
<div className="block md:hidden">
{/* 0-767px: 顯示 */}
{/* 768px以上: 隱藏 */}
手機版選單
</div>
實務範例: 響應式 Grid
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{/*
手機: 1欄
小平板: 2欄
大平板: 3欄
桌面: 4欄
*/}
{items.map((item) => (
<Card key={item.id} {...item} />
))}
</div>
暗色模式
基本概念:dark: 前綴
在 TailwindCSS 中,可以用 dark: 前綴來指定「暗色模式時要用什麼樣式」。
首先需要在 CSS 中定義 dark: 前綴的行為:
/* index.css */
/* 當元素在 .dark class 的範圍內時,dark: 前綴的樣式才會生效 */
@custom-variant dark (&:is(.dark *));
接著就可以在元件中使用:
/*
- 平常:使用白色背景(`bg-white`)
- 切換到暗色模式時:使用深灰色背景(`dark:bg-gray-900`)
*/
<div className="bg-white dark:bg-gray-900">內容</div>
TailwindCSS 會檢查 HTML 有沒有 dark 這個 class 來決定是否套用 dark: 前綴的樣式:
<!-- 平常(亮色模式) -->
<html>
<body>
<div class="bg-white dark:bg-gray-900">內容</div>
<!-- 顯示:白色背景 -->
</body>
</html>
<!-- 切換到暗色模式 -->
<html class="dark">
<body>
<div class="bg-white dark:bg-gray-900">內容</div>
<!-- 顯示:深灰色背景 -->
</body>
</html>
當 <html> 標籤有 dark class 時,所有 dark: 開頭的樣式就會生效。通常你會用 JavaScript 來動態加上或移除這個 dark class,實現主題切換功能。
使用語意化顏色的方式
不過上面的寫法有個問題:每次要設定顏色都要寫兩次,一次 bg-white,一次 dark:bg-gray-800,很麻煩。
更好的做法是使用「語意化顏色」搭配 CSS 變數,不需要 @custom-variant 那行。完整的設定如下:
/* index.css */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
}
:root {
--background: white; /* 亮色模式的背景色 */
--foreground: black; /* 亮色模式的文字色 */
}
.dark {
--background: #1a1a1a; /* 暗色模式的背景色 */
--foreground: white; /* 暗色模式的文字色 */
}
各部分的作用:
@theme inline- 告訴 TailwindCSS 產生對應的 utility classes
--color-background→ 產生bg-background、text-background等 class--color-foreground→ 產生bg-foreground、text-foreground等 class
:root和.dark- 定義實際的顏色值
:root是預設值(亮色模式).dark是暗色模式的覆蓋值- 這是原生 CSS 的寫法,不需要 TailwindCSS 的特殊配置
使用方式:
<div className="bg-background text-foreground">內容</div>
不需要寫 dark: 前綴,但會自動切換顏色。原理是:
bg-background實際上使用--background這個 CSS 變數- 當 HTML 有
darkclass 時,CSS 會自動把--background的值從白色換成深灰色 - 同一個
bg-backgroundclass 在不同模式下會顯示不同顏色
對比兩種寫法:
// 傳統寫法:要寫很多 dark: 前綴
<div className="bg-white dark:bg-gray-900 text-black dark:text-white">
內容
</div>
// 語意化顏色:不用寫 dark: 前綴
<div className="bg-background text-foreground">
內容
</div>
兩種寫法效果相同,但語意化顏色更簡潔、易維護。這也是 shadcn/ui 推薦的做法。
Reference
- Customizing Colors - TailwindCSS
- Background Color - TailwindCSS
- Text Color - TailwindCSS
- Border Color - TailwindCSS
- Font Size - TailwindCSS
- Font Weight - TailwindCSS
- Line Height - TailwindCSS
- Letter Spacing - TailwindCSS
- Text Align - TailwindCSS
- Padding - TailwindCSS
- Margin - TailwindCSS
- Gap - TailwindCSS
- Display - TailwindCSS
- Flexbox - TailwindCSS
- Grid Template Columns - TailwindCSS
- Justify Content - TailwindCSS
- Align Items - TailwindCSS
- Width - TailwindCSS
- Height - TailwindCSS
- Border Width - TailwindCSS
- Border Radius - TailwindCSS
- Hover, Focus, and Other States - TailwindCSS
- Responsive Design - TailwindCSS
- Dark Mode - TailwindCSS