<!-- .slide: data-transition="fade" -->
## 前言
---
### 對你而言,
- 編寫樣式是件苦差事 ?
- 經常覺得 CSS 很難使用 ?
- 認為樣式很難被 Debug ?
- 專案中充斥著難被理解的CSS類 ?
---
擁有這樣想法的你並不孤單,
也許你也該試試 TailwindCSS,
接下來,我將透過幾個情境,
向你解釋它怎麼面對這些問題。
---
<!-- .slide: data-transition="fade-in" -->
## 迷人的 TailwindCSS
分享者: Nilson Weng
---
<!-- .slide: data-transition="zoom-in" -->
### 情境一
因為不同瀏覽器所默認的樣式行為有
所不同,例如,行高、邊距和標題字
體大小等。因此,需要設置樣式重置
表覆蓋的既有樣式效果,避免差異。
---
因為不確定所用的重置樣式表方案,
是 [Reset CSS](https://meyerweb.com/eric/tools/css/reset/),還是 [Normalize.css](https://github.com/necolas/normalize.css) 呢?
在開始工作前你得先查閱舊專案。

---
重置樣式表總是佔據樣式表最上方。

---
<!-- .slide: data-transition="fade" -->
### Tailwind
@tailwind base 會自動注入這些樣式
```css
@tailwind base; /* Preflight will be injected here */
@tailwind components;
@tailwind utilities;
```
---
<!-- .slide: data-transition="zoom-in" -->
### 情境二
- ## 完成 ChitChat 對話視窗

---
<!-- .slide: data-transition="fade" -->
### 使用 CSS
- 分析元件,產生 html 結構 (3 min)
- 建立 .css 檔案,並引入專案。(2 min)
- 思考樣式類的命名方式,(2 min)
- 創建樣式類的區塊、組織結構,(5 min)
- 在對應的區塊中填入 CSS,(5 min)
檢查效果是否符合預期。(3 min)
費時: 20 分鐘
---
<!-- .slide: data-transition="fade" -->
### 使用 Tailwind
- 分析元件,產生 html 結構 (3 min)
- ~~建立 .css 檔案,並引入專案。 (2 min)~~
- ~~思考樣式類的命名方式,(2 min)~~
- ~~創建樣式類的區塊、組織結構,(5 min)~~
- **在 html 中填入 tailwind 類,(4 min)**
檢查效果是否符合預期。(3 min)
費時: 10 分鐘
---
- 使用 CSS 完成的效果

---
- 使用 Tailwind 完成的效果

---
### [css vs tailwind](https://planflow.dev/blog/the-main-advantage-of-tailwindcss)

---
<!-- .slide: data-transition="zoom-in" -->
### 情境三
- #### 請問以下Hex值,分別代表什麼顏色?
- (紅、綠、藍、黃?要猜猜看嗎?)
```css
{ background-color: "#93c5fd" }
{ background-color: "#bfdbfe" }
{ background-color: "#dbeafe" }
{ background-color: "#eff6ff" }
```
---
你需要一個 [Color Picker](https://www.w3schools.com/colors/colors_picker.asp)
來確認顏色的 hex 值、rgb 值。

---
### Tailwind
- 預設讓顏色採色階方式定義
- 能有效辨識出顏色色系、深淺
- 如 bg-cyan-100、text-sky-300。

---
### 誰更容易理解與維護 ?
CSS
```css
{ background-color: "#93c5fd" }
{ background-color: "#bfdbfe" }
{ background-color: "#dbeafe" }
{ background-color: "#eff6ff" }
```
Tailwind
```htmlembedded
<div class="bg-blue-50"></div>
<div class="bg-blue-100"></div>
<div class="bg-blue-200"></div>
<div class="bg-blue-300"></div>
```
---
### 情境四
<!-- .slide: data-transition="zoom-in" -->
- 邊距、行高、尺寸、大小。
- 在這裡將透過以下來例子說明:

---
### 使用 CSS

---
### 使用 Tailwind
- 能搭配 IDE 查看實際所對應的 CSS 屬性

---
- ### Tailwind - 邊距、尺寸、大小
- 基本單位是 rem
- 邊界的距離使用一般數字,表示級距。
如 p-10、w-2、max-w-1、border-1
- 尺寸使用 sm、md(base)、lg、xl、2xl。
如 text-sm、rounded-md
- 亦可使用 **[ ]** 自訂義大小,
如 p-[100px]、text-[16px]
---
### 為何用 rem,px 哪裡不好 ?
- px 不夠彈性。
- rem 是相對單位,因應響應式設計需求。
若不同尺寸的螢幕上改變父元素(:root)的
px數值,便可改變所有子元素的單位數值
``` css
/* 默認大小 1rem = 16px*/
:root { font-size: 16px; }
```
---
### 情境五
<!-- .slide: data-transition="zoom-in" -->
- RWD 開發需求
- 繼續使用情境四的例子,
根據畫面寬度改變顏色。
---
### CSS
- 使用 media query 語法

---
### Tailwind
- 使用 "`:`" (使樣式於特定條件下觸發效果)
(https://play.tailwindcss.com/mSBqQyV4D9)
- 預設的尺寸表如下

---
### Tailwind 自定義其他尺寸

---
### 情境六 - 討厭的前綴
<!-- .slide: data-transition="zoom-in" -->
- 某些CSS屬性需要添加特定的前綴,
適應不同瀏覽器之間的差異。
```css
-webkit- /* Chrome、Safari */
-moz- /* Firefox */
-o- /* Opera */
-ms- /* Internet Explorer */
```
---
### [Can I Use](https://caniuse.com/)
- 你需要查看各瀏覽器的支援情況。

---
CSS
- 自行添加這些前綴,既繁瑣,且容易錯誤。

👉 [Autoprefixer Online](https://autoprefixer.github.io/)
---
### Autoprefixer
- Autoprefixer 是一個 PostCSS 插件
- 它能解析當前 CSS 並自動添加這些前綴。

---
### Tailwind
- 高度利用 postcss。
- 採插件型式擴展 Autoprefixer。
```js
// @file: postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
```
---
### 情境七 - 膨脹的 CSS 體積
<!-- .slide: data-transition="zoom-in" -->
- 膨脹的CSS 也是網頁載入緩慢的原因
---
- CSS
- 單純CSS開發下,
隨著專案規模擴大,
幾乎不可能避免此問題。
- Bootstrap、Material UI
- 即使透過搖樹(tree-shaking)方式,
拆分元件也效果有限。
---
### PurgeCSS
- PurgeCSS 可以刪除未使用的 CSS 代碼,
從而生成更小的 CSS 文件。

#### [purifycss-online](https://purifycss.online) 👈
---
- ### Tailwind
- 對比先前的 autoprefixer
需要 postcss.config.js 中配置
- PurgeCSS 是直接內置的,
不需要額外配置。
---
### Tailwind 工作流程
- 能掃描專案的所有文件,並輸出一份實際有用到的樣式文件。

<!-- 
-->
---
<!-- .slide: data-transition="zoom-in" -->
### Tailwind 豐富的生態系
- Editor Support
(VSCode、WebStorm、Neovim)
- Prettier
---
<!-- .slide: data-transition="fade" -->
### VSCode ❤ Tailwind

---
### 完成的效果
- 出現選項視窗
<!--  -->

- 滑鼠選停在樣式上會出現對應的CSS語法
<!--  -->

---
### Tailwind 解決 CSS 難題
- 樣式衝突、命名衝突、殭屍樣式(zombies)

---
- Tailwind 帶來安全、可靠的開發體驗


- Tailwind 發現衝突的樣式
---
<!-- .slide: data-transition="fade" -->
### Prettier ❤ Tailwind

---
### 完成的效果
- 使團隊中在CSS編寫順序維持一致。
- 減少認知差異,避免誤會與風格混亂。

---
<!-- .slide: data-transition="zoom-in" -->
### 小結
- 優秀的抽象層設計與豐富的文件。
- 提升人員開發樣式的工作效率。
- 優化樣式文件的可靠度與性能表現。
- 極佳的開發體驗與可維護性。
---
<!-- .slide: data-transition="zoom-in" -->

---
<!-- .slide: data-transition="slide-in" -->
### 感謝各位聆聽
---
## 補充
- 上手安裝
---
### 如何上手安裝
---
### Node.js

---
### [下載安裝 TailwindCSS](https://tailwindcss.com/docs/installation)
- 命令行工具與編譯器(TailwindCSS 核心)
```shell
# 創建一個專案
$ mkdir tailwind_project
$ cd tailwind_project
# 安裝 TailwindCSS
$ npm install -D tailwindcss
```
---
### Tailwind 配置文件
- TailwindCSS 專案初始化建置開發環境
```shell
$ npx tailwindcss init
```
```js
// @file: ./tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {},
},
plugins: [],
}
```
---
### Tailwind Preflight
- 配置 @tailwind 指令添加到主要得CSS文件中。
- 配置 Tailwind 默認的重置樣式表效果。
```css
/* @file: ./input.css */
/* 假設 input.css 為主要CSS文件 */
@tailwind base;
@tailwind components;
@tailwind utilities;
```
---
### Tailwind CLI
- 透過命令行工具啟用 Tailwind 工作流程。
- 掃描專案中所有文件中的類來構建 CSS。
```shell
$ npx tailwindcss -i ./input.css -o ./output.css --watch
```
---
### Tailwind 的 PurgeCSS 機制
- 設置 content 屬性,將影響 Tailwind 掃描的文件範圍。在該範圍之外所輸入的Tailwind類將不會被自動產生出來。
```js
// @file: ./tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js}"], // 👈
(略...)
}
```
---
### Tailwind 工作原理

---
### Tailwind Build 命令
能產出壓縮過的CSS文件使體積縮小提升性能。
```shell
$ npx tailwindcss build -o ./dist/build.css --minify
```
---
### 壓縮後的 Tailwind.css
- 檔案大小 10.3 kB → 3.83kB (減少 62.8%)
- 載入大小 3.5kB → 1.8kB (減少 48.5%)
- 載入速度 11ms → 6ms (加快 83%)

---
### CSS to Tailwind
給美術人員或想學習Tailwind的建議
---
### 建議瞭解 CSS 開始學
- Tailwind 是基於 CSS 而生,因此,
你應先學習 CSS,再去使用它。
- 記憶學習 Tailwind 很簡單,但是,
理解 CSS 特性必不容易。
👉 [CSS to Tailwind Online Tool](https://transform.tools/css-to-tailwind)
---
### Tailwind 基本語法
- 使用 Tailwind CSS 時,首要理解 Variant 和 Utility 之間的關係,並熟悉如何使用它們來構成所需的**組合樣式**。 關係式如下:
```jsx
[Variant]:[Utility]
- 變量 ( Variant ):
- 某個對象、特定條件、狀態等。
- 功能類 ( Utility Class ) :
- 則是定義小的、基本的、可重複使用的風格的類。
- 這些類可以組合在一起,以創建複雜的設計。
```
#### 👉 [tailwindcss-online](https://play.tailwindcss.com/)
---
### Utility Class 範例1
- 一般常見的功能類 👉 [Demo](https://play.tailwindcss.com/e7Sb4lKdYH)
```tsx
// bg-pink-400 : 預設情形下,讓設置背景為粉紅色
<div class="p-[100px] bg-pink-400" />
```

---
### Utility Class 範例2
- 會根據條件決定的功能類 👉 [Demo](https://play.tailwindcss.com/Jclt3RyCJ6)
- media query 語法
```tsx
// bg-pink-400 : 預設情形下,讓設置背景為粉紅色
// 其他根據不同寬度: 產生顏色便換。
// 預設尺寸如: sm、lg、xl、2xl...
<div class="p-[100px]
bg-pink-400
sm:bg-orange-400
lg:bg-yellow-400" />
```
---
### Tailwind 進階課題
給有Tailwind使用經驗的學習者
---
### Tailwind 進階 - 樣式抽離

---
### 如何將樣式抽離 -1
可以使用 @apply 來抽離,但是不要濫用

---
### 如何將樣式抽離 -2
搭配前端框架,Tailwind 可以發揮得更好。

---
### 如何將樣式抽離 -3
- 注入 bgColor 動態樣式

---
### 不推薦的使用方式 ⛔
- 使用情境

- 需設置白名單才能作用

---
### 較好的使用方式 ✅
```jsx
// Box 是一個簡單的元件,用來顯示一個有背景色的方塊。
const Box = ({ bgColor }) => {
return <div className={bgColor}></div>;
};
// 使用 tw 來注入背景色
<Box bgColor="bg-red-300" />
```
---
### 與 CSS 一起使用 🤝
無法事前就決定的 Tailwind 樣式,
所以,何不直接使用 css 來解決。
```jsx
// 將 CSS 和 Tailwind 一起使用
const Box = ({ bgColor }) => {
return <div style={{ backgroundColor: bgColor }}></div>;
};
<Box className="p-4" bgColor={'#ff0000'} />;
```
---
### 如何合併 tailwind 樣式 ?
在開發 tailwind 樣式中,會遇到
需要合併 tailwind 樣式的時候。
<br>
直覺上,你可能會這樣做...
```js
<div class={"px-2 py-1 bg-red " + "bg-blue"} />
// ^ 記得留空格
```
---
但是,由於樣式的發生順序是根據
樣式表的先後順序來決定,因此,
這裡反而 bg-red 會蓋掉 bg-blue 效果。

```js
<div class={"px-2 py-1 bg-red bg-blue"} />
```
---
### twMerge
為避免這種狀況,與樣式的衝突發生,
可借助 tailwind-merge 庫來進行合併。
```js
import { twMerge } from 'tailwind-merge'
twMerge('px-2 py-1 bg-red ', 'p-3 bg-blue')
// → 'p-3 bg-blue' ✨
```
---
### clsx
clsx 函數可以讓你用多種類型,如物件、
陣列、布林值或字串,來組成字串,
借此提升了編寫 tailwind 樣式的彈性。
```js
import { clsx } from 'clsx';
// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'
```
---
### cn = twMerge + clsx ⚔️
- twMerge : 將樣式字串序列進行排序。
- clsx : 幫助合併 tailwind class 成字串序列
```ts
// @file: ./utils/cn.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
---
### 借助 cn 函式改進元件

🎞️ [請帥哥教你cn](https://www.youtube.com/watch?v=re2JFITR7TI&list=PLvn_u52ubqUFM8o2RKvI6YyRyppXn36a1&ab_channel=ByteGrad)
---
## cva
主要目的在於創造元件樣式的變體(variants)

##### 👉 [bootstrap 按鈕變體範例](https://getbootstrap.com/docs/5.3/components/buttons/#variants)
---
### 變體 (Variants)
理解上,變體為元件的差異化種類。用神奇寶貝
來說,就像是"色微"的感覺。仍屬於原來物種,
能力一致,但在外型上卻有所差異。

---
### cva 的結構
- variants
- compoundVariants
- defaultVariants
---
### cva 學習指南
由於篇幅設計這裡只能簡單介紹,
cva 本質是針對複雜元件的方案。
詳細資訊不如聽聽創作者怎麼說
🎞️[CVA 創造者](https://www.youtube.com/watch?v=B6FrDu2Qbt0&t=158s&ab_channel=FrontendFYI)
👉[CVA Docs](https://cva.style/docs)
---
### cva 效果程式範例
將按鈕元件,再以 cva 提出 intent, size 兩個變因。

{"description":"分享者: Nilson Weng","title":"Charming TailwindCSS","contributors":"[{\"id\":\"ceacb5e9-1b52-45c6-a5db-8c8e3d7a3790\",\"add\":22373,\"del\":9507}]"}