善用 data-attributes 為 Tailwind CSS 設定動態樣式

更新於 發佈於 閱讀時間約 8 分鐘

Tailwind CSS 為什麼受歡迎

Tailwind CSS 是熱門的CSS框架,最大的賣點在於「原子化」,也就是「一個class 對應到一個css 樣式」。使用 Tailwind CSS 後,開發者再也不用花時間思考class的名稱,只要在元件中的 markup 寫好構成樣式所需的 class 名稱,Tailwind 就會在 build 的時候生成對應的css樣式,像這樣:

<p className="text-3xl font-bold text-blue-500">Hello World</p>;

搭配 Webpack 或 Vite 等打包工具,執行 build 命令後, Tailwind 就會幫我們在 build 之後的靜態檔案裡新增樣式:

.text-blue-500 {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity));
}
Tailwind CSS 會根據 class 名稱,生成對應樣式。

Tailwind CSS 會根據 class 名稱,生成對應樣式。

此外,Tailwind CSS 在生成樣式時,有寫出的class才會生成對應的 CSS,因此不用擔心有像 BootStrap 等框架在網頁打包時,套件的css會讓檔案變得臃腫的情況。Tailwind 的好處還有避免同名的class之間樣式衝突等等,但這非本文重點,故不贅述。筆者希望把重點放在 Tailwind 難以解決的問題,和其解決方案上。


不易設定動態樣式

Tailwind 在 build 時生成樣式,因此要因應 client-side 的 state 或 prop 變化動態產生樣式會比較麻煩。面對這個問題,其中一種做法是使用如 clsx 的第三方套件,透過 JavaScript 在 runtime 時根據元件的狀態將 class 名稱組合成對應的樣式。


clsx 套件

clsx 是一個專門處理 CSS class 名稱的套件,他可以將物件、陣列甚至條件判斷轉換成字串,並計算出最終的 class 名稱。搭配 Tailwind 使用,可以讓動態樣式設定的開發者體驗更好:

const buttonClass = clsx("py-2 px-4 font-semibold rounded-lg text-white", {
"bg-blue-500": status === "Primary",
"bg-green-500": status === "Success",
"bg-red-500": status === "Danger",
});

return (
<div>
<button className={buttonClass}>{status}</button>
</div>
);

雖然 clsx 和 Tailwind 搭配已經十分好用,即使套件本身非常輕量化,畢竟仍會在打包時產生一些 JavaScript。那麼,有沒有不用第三方套件產生動態樣式的解決方案呢?


用data-* attribute 動態生成樣式

所幸 Tailwind CSS 在 3.2 版推出用 data-* attributes 動態生成樣式的方法。以下舉 React component 為例,說明如何透過 data 屬性的綁定,生成動態的 Tailwind classes:

import { useState, useEffect, useRef } from "react";

import Checkbox from "./Checkbox";

export default function App() {
const [status, setStatus] = useState("Primary");

const intervalRef = useRef(null);
useEffect(() => {
function switchBtnBackground(color) {
switch (color) {
case "Primary": {
return "Success";
}
case "Success": {
return "Danger";
}
case "Danger": {
return "Primary";
}
}
}

intervalRef.current = setInterval(() => {
setStatus((t) => switchBtnBackground(t));
}, 1500);

return () => clearInterval(intervalRef.current);
}, []);

return (
<div className="text-2xl border w-64">
<button
data-status={status}
className="w-full data-[status=Primary]:bg-[#007bff] text-white data-[status=Success]:bg-[#28a745] data-[status=Danger]:bg-[#dc3545] px-4 py-2 border-gray-500 rounded-sm text-center"
>
{btnText}
</button>
</div>
);
}


data attribute 是 HTML 內建的元素屬性,可以自定義元素的屬性,將網頁的狀態綁定在元素上。如上面的例子中,筆者將元件的狀態 status 綁定在按鈕上,當元件的狀態改變時,data-status 就會跟著改變。而 Tailwind 讓 data attribute 成為一種狀態,就像 media query 的 md/xl 等一樣,後面可以加上隨著data attribute值變化所套用的class 名稱,進而達到動態產生樣式的目的。

按鈕根據元件狀態變化,會有不同背景顏色。

按鈕根據元件狀態變化,會有不同背景顏色。



總結

data-attribute 讓使用Tailwind CSS 制定動態樣式變得更容易,且不需要依賴第三方套件,看起來十分美好。但 Tailwind 官方有提到:data attribute 只接受 arbitrary values,也就是開發者自定義的值,這也就代表會在 build 的時候額外生成classes。因此,如果元件內有大量的互動,造成樣式多變,使用 data attribute 也許不一定能減少打包檔案的大小。筆者認為,像clsx這樣處理多變樣式的套件,仍有其優勢,而data-* 屬性則適合在元件的動態較不複雜時使用。

arbitrary value 會在build 時生成額外的class,因此過度使用會讓css打包檔案變得很肥。

arbitrary value 會在build 時生成額外的class,因此過度使用會讓css打包檔案變得很肥。



參考資料

CLEANER Tailwind classes

Tailwind CSS v3.2: Dynamic breakpoints, multi-config, and container queries, oh my!

https://tailwindcss.com/blog/tailwindcss-v3-2#data-attribute-variants


留言
avatar-img
留言分享你的想法!
林博濂-avatar-img
2024/03/25
感謝分享!看完介紹會覺得能用clsx就盡量用,data-attribute 的原生寫法完全不吸引人XD
avatar-img
廖偉帆的沙龍
3會員
5內容數
我是Sail,這裡主要分享一些自己覺得有趣的前端議題。
廖偉帆的沙龍的其他內容
2024/05/30
在進行Electron 專案時,後端夥伴選擇將 sqlite 資料庫跟專案檔打包成一個執行檔。在開發過程中,前端的操作經常會更動到 db的資料,此時 Git 就會追蹤到 db 的變化,因此前端在推送檔案到遠端 repo 前,會需要將其移出 Git 追蹤範圍,該怎麼做?
Thumbnail
2024/05/30
在進行Electron 專案時,後端夥伴選擇將 sqlite 資料庫跟專案檔打包成一個執行檔。在開發過程中,前端的操作經常會更動到 db的資料,此時 Git 就會追蹤到 db 的變化,因此前端在推送檔案到遠端 repo 前,會需要將其移出 Git 追蹤範圍,該怎麼做?
Thumbnail
2024/05/13
在串接第三方 API時,需要定期刷新 token,那有沒有辦法針對 request 和 response 做配置,在 token 過期時先做刷新、再做請求呢?本文要介紹利用 axios 套件提供的攔截器刷新 token 的作法。
Thumbnail
2024/05/13
在串接第三方 API時,需要定期刷新 token,那有沒有辦法針對 request 和 response 做配置,在 token 過期時先做刷新、再做請求呢?本文要介紹利用 axios 套件提供的攔截器刷新 token 的作法。
Thumbnail
2024/05/01
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
2024/05/01
在 Vue 專案中使用 Apollo Graphql Client 從 API 獲取資料,由於資料結構較為複雜,筆者便跟著網路教學使用 codegen 工具自動化產生 TypeScript 型別定義。在某個元件中,需要使用 defineProps 來撰寫型別定義,結果⋯⋯
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
這篇文章介紹了網站的整體架構以及開發時所使用的工具和套件,包括 Next.js、Tailwind CSS 和 socket.io 等。文章回顧了程式碼的重構與優化,幫助開發者提高工作效率,適合希望深入瞭解前端開發和網站架構的讀者。
Thumbnail
這篇文章介紹了網站的整體架構以及開發時所使用的工具和套件,包括 Next.js、Tailwind CSS 和 socket.io 等。文章回顧了程式碼的重構與優化,幫助開發者提高工作效率,適合希望深入瞭解前端開發和網站架構的讀者。
Thumbnail
在本章中,我們探討了CSS Grid佈局的基本概念和應用。CSS Grid提供了一個強大而靈活的二維佈局系統,使得處理複雜的網頁佈局變得更加簡單和直觀。我們學習了如何設置Grid容器和Grid項目,以及如何使用各種Grid屬性來定義和管理佈局。
Thumbnail
在本章中,我們探討了CSS Grid佈局的基本概念和應用。CSS Grid提供了一個強大而靈活的二維佈局系統,使得處理複雜的網頁佈局變得更加簡單和直觀。我們學習了如何設置Grid容器和Grid項目,以及如何使用各種Grid屬性來定義和管理佈局。
Thumbnail
這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
Thumbnail
這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
使用靜態檔案下載 Bootstrap 的原因主要有以下幾點: 客製化:當你下載了 Bootstrap 的靜態檔案,你可以根據自己的需求來修改這些檔案。例如,你可以改變預設的顏色、字型大小、間距等,使其更符合你的網站風格。這是直接使用 CDN 所無法做到的。 效能優化:如果你的網站只使用 Boot
Thumbnail
使用靜態檔案下載 Bootstrap 的原因主要有以下幾點: 客製化:當你下載了 Bootstrap 的靜態檔案,你可以根據自己的需求來修改這些檔案。例如,你可以改變預設的顏色、字型大小、間距等,使其更符合你的網站風格。這是直接使用 CDN 所無法做到的。 效能優化:如果你的網站只使用 Boot
Thumbnail
本文介紹如何使用Vite建立前端開發初始檔案,並加入Tailwindcss的教學。透過指令和配置檔,讓你能快速建立個人專案的開發環境,並學習如何加入全域的Tailwindcss樣式。還有影片教學、資源連結和更多相關教學文章等,幫助你進一步學習。
Thumbnail
本文介紹如何使用Vite建立前端開發初始檔案,並加入Tailwindcss的教學。透過指令和配置檔,讓你能快速建立個人專案的開發環境,並學習如何加入全域的Tailwindcss樣式。還有影片教學、資源連結和更多相關教學文章等,幫助你進一步學習。
Thumbnail
CSS 的繼承性是開發網頁樣式時的一個重要概念,它使得樣式設計更加靈活和高效,有助於提高程式碼的可讀性、一致性和可重用性,並加快開發速度,從而提供更好的開發體驗。
Thumbnail
CSS 的繼承性是開發網頁樣式時的一個重要概念,它使得樣式設計更加靈活和高效,有助於提高程式碼的可讀性、一致性和可重用性,並加快開發速度,從而提供更好的開發體驗。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News