当前位置: 首页 > ds >正文

Tailwind CSS v4 主题化实践入门(自定义 Theme + 主题模式切换)✨

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。有效图层为 basecomponentsutilities
    • 三个图层的生效顺序是不一致的,作用在同一元素上的相同的样式属性,生效优先级顺序是: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 主题相关引入,让你从分散的属性处理升级到全局统一。

http://www.xdnf.cn/news/5361.html

相关文章:

  • shell 编程之正则表达式与文本处理器
  • JS逆向-7881游戏平台Lb-Sign参数和Lb-Timestamp参数
  • SaaS场快订平台项目说明【持续更新】
  • ensp的华为小实验
  • 管道-验证和转换
  • 关于“铜宝”电线的质量,以下是综合分析:
  • 第3.2.3节 Android动态调用链路的获取
  • 【程序员AI入门:开发】11.从零构建智能问答引擎:LangChain + RAG 实战手册
  • 计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 08.阴影
  • Python函数式编程入门:闭包与装饰器详解
  • 【数据结构】子串、前缀
  • 数据库索引详解:原理 · 类型 · 使用 · 优化
  • 傅利叶十周年,升级核心战略:“有温度”的具身智能蓝图
  • 【STM32 学习笔记】USART串口
  • ScaleTransition 是 Flutter 中的一个动画组件,用于实现缩放动画效果。
  • vscode_python远程调试_pathMappings配置说明
  • 一、数据仓库基石:核心理论、分层艺术与 ETL/ELT 之辨
  • Day21 奇异值分解(SVD)全面解析
  • 【Redis】缓存和分布式锁
  • spark-哈希join介绍
  • spring中的@Inject注解详情
  • 嵌入式学习笔记 - 运算放大器的共模抑制比
  • 探索C++内存管理
  • MySQL中like模糊查询如何优化?
  • JSON 在 Java 中的应用:手动生成与使用库的对比
  • 部署dify
  • 操作系统学习笔记第2章 (竟成)
  • 材料创新与工艺升级——猎板PCB引领高频阻抗板制造革命
  • 不同环境下运行脚本如何解决pythonpath问题
  • Cesium高度参考系统