ok,經過學習Tailwindcss我決定將此專欄建設成為一個Tailwindcss實戰專欄,我將在專欄內完成
5050
挑戰:50天50個Tailwindcss練習項目
,歡迎大家訂閱!!!
Tailwind CSS v4 帶來了更強大的主題定制能力,給了前端開發者更加靈活的設計空間。
今天,我們將來學習 Tailwind CSS v4 的主題相關特性,并且給出一套實踐模板 🚀
主題相關核心 API 介紹
Tailwind v4 主題使用 @theme
定義,并支持直接使用 CSS 變量來簡化主題設計。下面是官方文檔鏈接:
- 主題變量
- 添加自定義樣式
- 函數和指令
下面介紹集中常見的主題相關的指令以及自定義變體。
1. @theme
元素
Tailwind v4 引入 @theme
用來定義 CSS 變量,與v3版本需要在 tailwind.config.js
里配置相比,更為簡潔統一。
@theme {--color-primary: var(--primary);--radius-md: calc(var(--radius) - 2px);
}
2. @custom-variant
Tailwind v4 支持自定義優先級,實現更靈活的 dark mode 、 sidebar mode 等 UI 體驗的切換。
@custom-variant dark (&:is(.dark *));
定義了一個名為 dark 的自定義變體,它會匹配所有帶有 .dark 類的元素內部的所有元素。
3. @layer
雖然 Tailwind 能滿足大部分樣式需求,但有時候還是需要編寫純 CSS。這時,@layer
指令就登場了!
- 使用
@layer
指令告訴 Tailwind 一組自定義樣式屬于哪個bucket
。有效圖層為base
、components
和utilities
。- 三個圖層的生效順序是不一致的,作用在同一元素上的相同的樣式屬性,生效優先級順序是:
utilities
>components
>base
- 三個圖層的生效順序是不一致的,作用在同一元素上的相同的樣式屬性,生效優先級順序是:
- 使用
@apply
將任何現有工具類內聯到你自己的自定義 CSS 中 - 你仍然可以在你的css文件中寫出任何原生的css樣式,但是通常不建議這么做,這會增加維護難度。
@layer base {body {@apply bg-background text-foreground;}
}@layer components {card {@apply bg-card text-card-foreground;}
}@layer utilities {.heading {@apply text-4xl font-bold;}
}
利用Theme
實現主題切換
我們可以通過 :root
和 .dark
樣式規則來分別定義不同主題模式下的 變量 值,然后配合 @theme
以及 自定義變體
展開 Tailwind 內部設計。
@custom-variant dark (&:is(.dark *));@theme {--color-background: var(--background);--color-foreground: var(--foreground);--color-card: var(--card);--color-card-foreground: var(--card-foreground);--color-popover: var(--popover);--color-popover-foreground: var(--popover-foreground);--color-primary: var(--primary);--color-primary-foreground: var(--primary-foreground);--color-secondary: var(--secondary);--color-secondary-foreground: var(--secondary-foreground);--color-muted: var(--muted);--color-muted-foreground: var(--muted-foreground);--color-accent: var(--accent);--color-accent-foreground: var(--accent-foreground);--color-destructive: var(--destructive);--color-destructive-foreground: var(--destructive-foreground);--color-border: var(--border);--color-input: var(--input);--color-ring: var(--ring);--color-chart-1: var(--chart-1);--color-chart-2: var(--chart-2);--color-chart-3: var(--chart-3);--color-chart-4: var(--chart-4);--color-chart-5: var(--chart-5);--radius-sm: calc(var(--radius) - 4px);--radius-md: calc(var(--radius) - 2px);--radius-lg: var(--radius);--radius-xl: calc(var(--radius) + 4px);--color-sidebar: var(--sidebar);--color-sidebar-foreground: var(--sidebar-foreground);--color-sidebar-primary: var(--sidebar-primary);--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);--color-sidebar-accent: var(--sidebar-accent);--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);--color-sidebar-border: var(--sidebar-border);--color-sidebar-ring: var(--sidebar-ring);
}:root {--background: oklch(1 0 0);--foreground: oklch(0.145 0 0);--card: oklch(1 0 0);--card-foreground: oklch(0.145 0 0);--popover: oklch(1 0 0);--popover-foreground: oklch(0.145 0 0);--primary: oklch(0.205 0 0);--primary-foreground: oklch(0.985 0 0);--secondary: oklch(0.97 0 0);--secondary-foreground: oklch(0.205 0 0);--muted: oklch(0.97 0 0);--muted-foreground: oklch(0.556 0 0);--accent: oklch(0.97 0 0);--accent-foreground: oklch(0.205 0 0);--destructive: oklch(0.577 0.245 27.325);--destructive-foreground: oklch(0.577 0.245 27.325);--border: oklch(0.922 0 0);--input: oklch(0.922 0 0);--ring: oklch(0.708 0 0);--chart-1: oklch(0.646 0.222 41.116);--chart-2: oklch(0.6 0.118 184.704);--chart-3: oklch(0.398 0.07 227.392);--chart-4: oklch(0.828 0.189 84.429);--chart-5: oklch(0.769 0.188 70.08);--radius: 0.625rem;--sidebar: oklch(0.985 0 0);--sidebar-foreground: oklch(0.145 0 0);--sidebar-primary: oklch(0.205 0 0);--sidebar-primary-foreground: oklch(0.985 0 0);--sidebar-accent: oklch(0.97 0 0);--sidebar-accent-foreground: oklch(0.205 0 0);--sidebar-border: oklch(0.922 0 0);--sidebar-ring: oklch(0.708 0 0);
}.dark {--background: oklch(0.145 0 0);--foreground: oklch(0.985 0 0);--card: oklch(0.145 0 0);--card-foreground: oklch(0.985 0 0);--popover: oklch(0.145 0 0);--popover-foreground: oklch(0.985 0 0);--primary: oklch(0.985 0 0);--primary-foreground: oklch(0.205 0 0);--secondary: oklch(0.269 0 0);--secondary-foreground: oklch(0.985 0 0);--muted: oklch(0.269 0 0);--muted-foreground: oklch(0.708 0 0);--accent: oklch(0.269 0 0);--accent-foreground: oklch(0.985 0 0);--destructive: oklch(0.396 0.141 25.723);--destructive-foreground: oklch(0.637 0.237 25.331);--border: oklch(0.269 0 0);--input: oklch(0.269 0 0);--ring: oklch(0.439 0 0);--chart-1: oklch(0.488 0.243 264.376);--chart-2: oklch(0.696 0.17 162.48);--chart-3: oklch(0.769 0.188 70.08);--chart-4: oklch(0.627 0.265 303.9);--chart-5: oklch(0.645 0.246 16.439);--sidebar: oklch(0.205 0 0);--sidebar-foreground: oklch(0.985 0 0);--sidebar-primary: oklch(0.488 0.243 264.376);--sidebar-primary-foreground: oklch(0.985 0 0);--sidebar-accent: oklch(0.269 0 0);--sidebar-accent-foreground: oklch(0.985 0 0);--sidebar-border: oklch(0.269 0 0);--sidebar-ring: oklch(0.439 0 0);
}
... 其他主題樣式
最佳實踐:切換主題按鈕組件
下面是我創建的用于切換主題的按鈕組件,大家可以參考一下:
<template><button@click="toggleTheme"class="flex items-center gap-2 rounded bg-gray-200 px-4 py-2 text-gray-800 transition-colors duration-300 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600"><span v-if="isDark">🌙 暗黑</span><span v-else>?? 亮色</span></button>
</template><script setup>import { ref, onMounted } from 'vue'const isDark = ref(false)const toggleTheme = () => {isDark.value = !isDark.valuedocument.documentElement.classList.toggle('dark')localStorage.setItem('theme', isDark.value ? 'dark' : 'light')}onMounted(() => {const theme = localStorage.getItem('theme')isDark.value = theme === 'dark'if (isDark.value) {document.documentElement.classList.add('dark')}})
</script>
其他
當然tailwindcss v4支持豐富的 自定義樣式
復雜樣式
以及 自定義變體
,今天們探討一些常用的主題配置和規則。
Tailwind CSS v4 主題相關引入,讓你從分散的屬性處理升級到全局統一。