Tailwind CSS 新手上路:概念、安裝與工具推薦

Tailwind CSS 到底在紅什麼?它有哪些優缺點?這篇文章我們要一起來看看 Tailwind CSS 是什麼、要如何使用它、以及有哪些方便的工具可以使用。

Kelly CHI
23 min readNov 20, 2023
Tailwind CSS 好香
Tailwind CSS 好香

目錄

· Tailwind CSS 基本概念
· Tailwind CSS 的優點
· Tailwind CSS 的缺點
· 如何學習 Tailwind CSS
· 安裝與使用 Tailwind CSS

前言

在開發網頁使用者介面的過程中,CSS 是不可或缺的元素。然而,隨著專案規模的擴大,僅使用原生 CSS 在開發效率和維護性上會面臨種種挑戰。這時候,導入一個合適的 CSS 框架就是一個常見的解決方案。

最早推出於 2017 年,Tailwind CSS 是一個採用了「Utility First」理念的 CSS 框架。相對於傳統的 CSS 框架如 Bootstrap 或 CSS-in-JS 解決方案,Tailwind CSS 有著其獨特的優勢和特色。近年來,隨著生態系發展日益成熟,Tailwind CSS 儼然已成為現代前端 UI 開發的默認選擇。官方團隊在今年六月的時候還舉辦了首次的 conference Tailwind Connect,顯示了 Tailwind 的未來前景不可限量。

對於初學者而言,剛開始使用 Tailwind CSS 或許會感到有些不習慣。但根據我的個人經驗,一旦掌握了基本概念,開發過程將變得越來越得心應手,甚至感到「再也回不去原生 CSS 了!」所以,我希望透過這篇文章來介紹 Tailwind CSS 的基本概念、安裝方法,以及建議的學習路徑和相關工具,讓更多人能夠感受到 Tailwind CSS 的魅力。

Tailwind CSS 基本概念

Utility First Framework

前面有提到 Tailwind CSS 是主打「Utility First」的 CSS 框架,這意味著它提供了大量已預先定義好的、單一用途的 CSS class,讓我們可以直接應用在 HTML 標籤上,而不需要額外撰寫 CSS 樣式。

以往,如果要為一個通知元件撰寫樣式,我們可能會這樣做:

<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">ChitChat</h4>
<p class="chat-notification-message">You have a new message!</p>
</div>
</div>

<style>
.chat-notification {
display: flex;
max-width: 24rem;
margin: 0 auto;
padding: 1.5rem;
border-radius: 0.5rem;
background-color: #fff;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.chat-notification-logo-wrapper {
flex-shrink: 0;
}
.chat-notification-logo {
height: 3rem;
width: 3rem;
}
.chat-notification-content {
margin-left: 1.5rem;
padding-top: 0.25rem;
}
.chat-notification-title {
color: #1a202c;
font-size: 1.25rem;
line-height: 1.25;
}
.chat-notification-message {
color: #718096;
font-size: 1rem;
line-height: 1.5;
}
</style>

但如果使用 Tailwind CSS,我們的 markup 會變成這樣:

<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
<div class="shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>

你可能會想說,那這樣跟直接寫 inline styles 有什麼不一樣?主要的差異有兩個:

第一,在 inline styles 中我們還是可以任意的撰寫想要的樣式,但是 Tailwind CSS 所提供的 utility class 背後是有一套經過深思熟慮的 Design System,讓你在有限的選擇中創造具有一致性、且容易維護的 UI。

第二,在 inline styles 我們沒有辦法設定 media query 樣式或是 hover、focus 等狀態的樣式,但是透過 Tailwind CSS 提供的 prefix 和 state modifier,我們可以輕鬆的在 HTML markup 中直接撰寫這些樣式。

💡若對於 utility first 框架的歷史發展有興趣的人,非常建議閱讀 Huli 大大的這篇 淺談 Atomic CSS 的發展背景與 Tailwind CSS,可以對這樣的設計有更全面的理解。

與 Bootstrap、CSS-in-JS 的差異

Bootstrap 雖然可以快速地為應用程式打造可用的 prototype,但他在客製化上缺乏彈性長期為人詬病,也會發生「Bootstrap 網站看起來就像是 Bootstrap 網站」的狀況。Tailwind CSS 則更注重自由度和彈性,不像 Bootstrap 提供了預先設計好的元件,透過複製貼上就可以在應用程式中使用,Tailwind CSS 僅提供了預先定義好的 utility class,需由開發者自行搭建所需的元件。

CSS-in-JS 解決方案 (例如 Styled-Components、Emotion 等) 提供了元件 markup 和 CSS 的綁定,並且可以利用 JavaScript 來撰寫動態樣式,然而,這樣的靈活性和方便性有時會伴隨著效能上的犧牲。而 Tailwind CSS 則會在 build time 時自動移除所有未使用的 CSS 樣式,這意味著最終生成的 CSS bundle 大小極小,這在效能上提供了顯著的優勢。

💡有興趣進一步閱讀 CSS-in-JS 在效能方面的探討以及與 Tailwind CSS 的比較可以參考這幾篇文章:

  1. Why We’re Breaking Up with CSS-in-JS
  2. Why I moved from styled-components to Tailwind CSS and what’s the future of CSS-in-JS?
  3. Tailwind CSS vs Emotion

Tailwind CSS 的優點

✅ 提升開發效率

Tailwind CSS的「Utility First」設計風格使開發速度變得極快。開發者可以直接在 HTML markup 中使用預先定義好的 class,而不需要經常切換到樣式表中進行設定。Tailwind CSS 也提供了簡便的 media query、hover、focus 狀態、dark 模式等等的 prefix 和 state modifier 讓開發者更容易撰寫響應式介面和不同狀態的 UI。這種直觀的開發方式使得快速建立 prototype 和後續修改維護變得更加容易。

✅ Design System

使用 Tailwind CSS 有助於建構一致的設計系統,尤其在多人共同開發的專案中,每個開發者對於樣式的寫法都可能有自己的習慣,長期下來可能導致樣式的管理變得複雜。在 Tailwind CSS 中,由於所有樣式都是預先定義好的,整個專案中的樣式便能保持一致。這樣的一致性不僅提高了程式碼的維護性,也使得與設計師的協作變得更加容易。

Tailwind 作者所出版的官方電子書 Refactoring UI
Tailwind 作者所出版的官方電子書 Refactoring UI

💡 Tailwind 官方有推出一本電子書:Refactoring UI,裡面提到了 Tailwind 本身的設計系統背後的思考哲學,例如單位的設定、調色板 (color palette) 的設計等等,有興趣的人可以參考 Theo 的這支影片

✅ 容易客製化

對於需要製作高度客製化的網頁的人,或許會覺得這些預先定義好的 class 無法滿足這樣的需求,但 Tailwind CSS 提供了豐富的 config 選項,開發者可以根據專案的需求去定義顏色、字型、邊框等屬性,Tailwind 甚至還會根據我們的設定去自動產生相對應的各種客製化 class。此外,在 markup 中我們也直接透過特殊的 syntax 去宣告預設中沒有的屬性和值。

✅ 極小的 CSS Bundle

雖然 Tailwind CSS 提供了大量的 utility class,但是在 build time 時會自動將所有沒有用到的 class 移除,因此就算我們自行定義了許多客製化的 utility class,最終生成的 CSS 文件其實仍是相對較小的,這有助於提高網站的效能。

✅ 廣大的社群和生態系

自從 Tailwind CSS 推出以來,它的社群和生態系都在持續的擴展,形成了一個龐大而活躍的開發者社群。社群提供了廣泛的教學資源、方便的工具和插件,以及大量的技術討論,使得學習和使用 Tailwind CSS 變得更加容易。

Tailwind CSS 的缺點

⚠️ HTML Markup 難以閱讀

使用 Tailwind CSS 的一個明顯缺點是 HTML markup 中包含了大量且冗長的 class,這可能影響原始碼的可讀性,並增加除錯的困難度 (之前有一陣子推特上面出現了大量嘲諷 Tailwind 的迷因,詳情可參考此篇文章)。這個特色也違反了所謂「Seperation of Concern」的原則,這一原則強調 HTML、CSS 和 JavaScript 應該要盡可能處理獨立的職責,以提高原始碼的維護性和擴展性。

超~~~~級多又長的 class,這樣是好是壞?
超~~~~級多又長的 class,這樣是好是壞?

然而,在「元件化開發」已經成為主流的現在,何謂好的「Seperation of Concern」仍然是一個值得辯論的議題。在 Tailwind CSS 作者 2017 年的這篇文章中就探討了「語意化 HTML 結構」與「CSS 複用性」之間的權衡,相當值得一讀。

⚠️ 需要時間上手

雖然 Tailwind CSS 的使用相對直觀,但初學者可能需要一些時間來習慣其獨特的開發方式,並熟悉特定語法的使用。特別是對於那些已經習慣傳統 CSS 或其他框架的開發者,需要一定的時間轉變思維。

⚠️ 沒有預設元件

與其他 CSS 框架如 Bootstrap 相比,Tailwind CSS 並沒有提供預設的元件。這意味著開發者需要自行按照設計需求來撰寫元件的樣式。對於一些喜歡快速開發並使用預設元件的開發者而言,這可能被視為一個不足之處。不過,隨著生態系的發展,相關的 Tailwind CSS 元件庫也越來越豐富,例如我之前在文章中有介紹過的 Shadcn-ui

Shadcn ui,近期快速獲得關注的 Tailwind CSS 元件「合集」
Shadcn ui,近期快速獲得關注的 Tailwind CSS 元件「合集」

總而言之,Tailwind CSS 作為一個高度靈活的 CSS 框架,其優點在於開發速度、客製化彈性、設計系統的建立等方面,但同時也存在著一些需要開發者留意的缺點,如原始碼的可讀性和上手難度。是否選擇使用 Tailwind CSS 還是要根據具體的專案需求和團隊的開發習慣來進行權衡。

如何學習 Tailwind CSS

對於剛學習網頁開發的新手,可能會納悶,既然 Tailwind CSS 這麼好用又受歡迎,那我還要學原生的 CSS 嗎?答案是一個大大的 YES

1. 最重要的第一步:打好 CSS 基礎

要記住的一點是,所有 Tailwind CSS 所提供的 utility class 都是原生 CSS 的抽象化罷了,例如 flex-direction: column; 會寫成 .flex-col;或是 max-width: 100%; 會寫成 .max-w-full,如果一開始並不知道如何使用這些 CSS 屬性,那麼在 Tailwind CSS 中你還是不知道該使用哪些 utility class。因此,在開始學習與使用 Tailwind 之前,先打好 CSS 的基礎是很重要的。推薦的學習資源有 Kevin Powell 的 YT 頻道以及 Wes Bos 的 FlexboxGrid 課程。

2. 官方文件與教學

接著,我們可以透過閱讀官方文件與教學來了解 Tailwind CSS 的基本概念、核心特性和使用方式。在 Tailwind Lab 的 YT 頻道上面提供了一系列的影片教學,個人認為是入門的最佳指南。我們還可以在官方的 Tailwind Play 線上編輯器中直接體驗撰寫 Tailwind CSS 的感覺,以熟悉基本的語法。

雖然是 V2 的介紹 (現在已經是 V3) 但是主要的概念和做法都是延續的!
雖然是 V2 的介紹 (現在已經是 V3) 但是主要的概念和做法都是延續的!

3. 在專案中實際應用

最好的學習方式是實際將 Tailwind CSS 應用在專案中。我們可以從小型的專案開始,嘗試應用各種不同的 utility class 來還原設計稿。Frontend Mentor 網站中的大小挑戰都是值得拿來練習的素材。沒有聽過 Frontend Mentor 這個網站的朋友可以參考以前寫過的這篇文章:Frontend Mentor 前端切版練功坊:用實作來逃離 tutorial hell 吧!

4. 參與社群

最後,我們還可以關注與 Tailwind CSS 生態系有關的社群動態,了解相關工具、UI 元件庫等等,並參與討論,學習他人的使用經驗。

安裝與使用 Tailwind CSS

搭配 Vite & React 來安裝

在大部分的情況下,要在專案中使用 Tailwind CSS 會建議搭配打包工具 (build tools) 一起使用,以達到最佳的效能與開發體驗,這邊將介紹搭配 Vite 和 React 的安裝方式,若你是使用其他的框架或是工具可以參考官方的文件

  1. 開啟一個新的 Vite 專案,並指定使用 React template
npm create vite@latest my-project -- --template react
cd my-project

2. 透過 npm 下載 Tailwind CSS 以及相關的相依性 (dependencies),再透過 init 指令來生成 tailwind.config.jspostcss.config.js 這兩個 config 檔案

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

3. 在 tailwind.config.js 中指定在專案中會使用到 Tailwind CSS 的檔案路徑

/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}

4. 在主要的 CSS 檔案 ./src/index.css 中加入 Tailwind CSS 各個層級的 utility class

@tailwind base;
@tailwind components;
@tailwind utilities;

5. 在專案中使用 Tailwind CSS utility class 來撰寫樣式

export default function App() {
return (
<h1 className="text-3xl font-bold underline">
Hello world!
</h1>
)
}

6. 透過終端機執行 build process,我們會在最終產出的 dist 資料夾中找到經過自動清除和壓縮的 CSS 檔案

npm run dev

基本客製化設定

我們可以在 tailwind.config.js 檔案中進行專案的各項基本設定,例如自定義顏色、字型、間距等。例如以下這個設定覆蓋了原本預設的 media breakpoints、色彩和字型。如果沒有要覆蓋原本的預設,可以使用下方的 extend 來擴充原本沒有的 utility class。此外,我們還可以使用 plugins 來新增各式各樣的實用插件。(參閱官方文件說明)

/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
screens: {
sm: '480px',
md: '768px',
lg: '976px',
xl: '1440px',
},
colors: {
'blue': '#1fb6ff',
'purple': '#7e5bef',
'pink': '#ff49db',
'orange': '#ff7849',
'green': '#13ce66',
'yellow': '#ffc82c',
'gray-dark': '#273444',
'gray': '#8492a6',
'gray-light': '#d3dce6',
},
fontFamily: {
sans: ['Graphik', 'sans-serif'],
serif: ['Merriweather', 'serif'],
},
extend: {
spacing: {
'128': '32rem',
'144': '36rem',
},
borderRadius: {
'4xl': '2rem',
}
}
},
plugins: [require('@tailwindcss/forms')]
}

⚙️ 推薦搭配使用的工具或套件

Official VS Code IntelliSense

Tailwind CSS 和 VS Code 合作的官方插件,幫助我們在開發的時候可以更方便地撰寫 utility class。這個插件提供了像是自動完成、錯誤提示和預覽最後生成的原生 CSS 樣式等功能,可以說是用 Tailwind CSS 開發的必備工具。

Automatic Class Sorting Prettier Plugin

Prettier 是一個在開發的時侯常用的工具,幫助我們保持程式碼風格的一致性。在使用 Tailwind CSS 開發元件的時候,常常會遇到 class 太過冗長、雜亂而找不到想要修改的 class 的問題。這個插件可以自動整理 class 的順序,讓不同元件的樣式寫法保持一致,減少修改上的麻煩。

Tailwind CSS Cheat Sheet

由於 Tailwind CSS 有大量的 utility class,初學者可能難以迅速記住所有的語法。這時候,使用 cheatsheet 可以方便地查閱各種 class 的寫法,提升開發效率。

使用 Cheatsheet 可以快速查詢 CSS 屬性和 Tailwind CSS class 的對照
使用 Cheatsheet 可以快速查詢 CSS 屬性和 Tailwind CSS class 的對照

Tailwind Merge 套件

在使用 Tailwind CSS 開發的時候有一個常見的陷阱,當我們在同一個元素上面為同一個 CSS 屬性設定了不同的值 (例如同時設定了 bg-blue-500bg-green-500),根據直覺可能會覺得應該是寫在後面的那個值會反映到該元素上,但實際上在 Tailwind CSS 中並不是這樣!最後反映在元素上的樣式是根據 source CSS 中的順序來決定的。因此,使用 Tailwind Merge 這個套件可以確保有衝突的 class 可以確實的套用到該元素上。(可進一步參考這個影片的說明)

clsx 套件

clsx 套件則是協助我們撰寫條件式的樣式的好用工具,例如以下的範例,classes 在任何時候都會套用到該元素上,但是 classes1 只會在 condition1 為真的時候套用,而在 condition2condition3 皆為真的時候則是套用 classes2

clsx('classes', {
'classes1': condition1,
'classes2': condition2 && condition3
})

我們也可以將這兩個常用的 package 結合為同一個 utility function,讓使用更方便。

import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";

function cn(...args) {
return twMerge(clsx(args));
}

CVA (Class Variance Authority) 套件

在開發 UI 的過程中,我們時常要處理同一個 UI 的不同「狀態」,而依據這些狀態我們的 UI 會有不同的「變化 (variants)」。最常見的例子是,一個按鈕元件可能會有「主要」、「次要」、「警告」、「禁用」等等不同的變化。而 CVA 這個套件就是為了讓我們可以更方便的撰寫與管理這些變化的樣式,同時它也完全支援 TypeScript,幫助我們在使用這些按鈕時可以有充分的智慧提示。更詳盡的介紹與使用方式可以參考官方文件與 Coding in Public 的這支影片

Carbon (IBM 的開源設計系統) 的按鈕元件
Carbon (IBM 的開源設計系統) 的按鈕元件
// 以 Shadcn-ui 的 button 元件為例
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)

除了上述所提到的工具和套件之外,Tailwind CSS 還有許多實用的插件可供使用,像是用來處理 markdown 文件樣式的 Typography 插件、為表單提供基本樣式的 Form 插件和 Container Queries 插件等等,都可以為我們的開發過程提供不小的幫助。

結語

Tailwind CSS 推出至今已在前端開發領域贏得了相當的地位,甚至成為許多框架的默認 styling 選擇。儘管如同所有工具一樣,它未必適用於每個專案或每位開發者,但我相信學習 Tailwind CSS 無論是在製作 Side Project 或導入公司未來專案的技術中,都將是一個極具價值的選擇。因此,擇日不如撞日,看完文章的你,趕快著手使用 Tailwind 來開發新專案吧!

參考資源整理

  1. Tailwind CSS 官方文件
  2. Tailwind Play 官方線上編輯器
  3. Tailwind Connect:首次官方 conference 的文字記錄
  4. Refactoring UI:介紹設計系統背後的思考哲學的電子書
  5. Tailwind CSS v2.0: From Zero to Production:官方影片教學系列
  6. 淺談 Atomic CSS 的發展背景與 Tailwind CSS by Huli
  7. CSS Utility Classes and “Separation of Concerns” by Adam Wathan
  8. I didn’t realize THIS about Tailwind… by Theo — t3․gg
  9. The Tailwind CSS Drama Your Users Don’t Care About by Builder.io
  10. Shadcn-ui : 美觀、無障礙、又能 100 % 客製化的「元件合集」 by Kelly CHI
  11. Tailwind-Merge Is Incredibly Useful — And Here’s Why! by Simon Swiss
  12. Class Variance Authority (CVA) Quickstart by Coding in Public
  13. Why We’re Breaking Up with CSS-in-JS by Sam Magura
  14. Why I moved from styled-components to Tailwind CSS and what’s the future of CSS-in-JS? by Ido Shamun
  15. Tailwind CSS vs Emotion by Irelia Codeheart

--

--

Kelly CHI

法文系畢業的前端工程師,致力於打造具有美感和良好用戶體驗的介面,同時也是個愛看冷門電影的骨灰級影迷。