用tailwindcss适配暗黑模式竟如此简单

接着上面一篇《从Nuxt文档里发现色彩的配搭诀窍》的内容,本文是我继续对 Nuxt/Content 的探索。当我研究它的色彩系统的时候,我还发现它还提供了暗黑模式,这也算是色彩系统的一种吧,毕竟也是和色彩搭配有关。经过一番学习折腾之后发现它的暗黑模式实现非常简单,甚至不需要你对这个模式有多么深刻的理解,只需要设置几个选项就能完成,并且搭配了 tailwindcss 的 color 系统灵活性也非常的好。

本文就以 引发作者探索暗黑模式的背景 -> 暗黑模式起源以及重要性 -> tailwindcss + vue3 实践暗黑模式的思路来进行讲解。

2021-11-21-20.49.12

首先我们先来通过 html 源码看看整个页面的样式变化。

image-20211123224911527

image-20211121205139746

从 切换到黑暗模式下的class 的内容就可以看出来,与普通模式相比会有两个变化:

1.根元素会挂载一个 dark-mode 的样式。

2.任何设置了 dark:{class} 的样式会生效。

没错,这就是 tailwindcss 内置的 dark mode,根据模式切换,能自动往根元素插入一个class,并且让 我们一开始设置的dark:{class}生效 ,大概的原理我们懂了,就差实践了,那么在进入实践之前,先来聊聊,为什么会有暗黑模式?当前以下不仅会回答这个问题,我还会解释为什么要用暗黑模式。

起因

让我们开始吧!

在计算机诞生早期的时候,计算机的显示屏其实一直被「暗黑模式」所占据,这是因为在20世纪6080年代的计算机显示器使用的是仅能支持单色显示的阴极射线管(CRT),黑底绿字的展示方式就成为了当时的常态。(原来这是一直延续的传统

「深色模式」的前世今生,都在这一篇里了

即使是80年代之后,彩色CRT显示器逐渐流行普及,但当时主流的DOS并没有什么「图形界面」的概念,依然延续了先前黑底的习惯。直到1984年,苹果发布了个人计算机Macintosh,普及了图形用户界面(Graphic User Interface)的概念,从而开启了以白色为底色的图形交互时代。

「深色模式」的前世今生,都在这一篇里了

直到2019年10月, IOS 13 这一支持暗黑模式系统的发布,「Dark Mode」的热度达到了空前的顶峰。

image-20211122233250391

然后各大互联网APP进行适配「暗黑模式」,可以从下图看出来~(图来自优设),其实我们也有感受,自从那以后周围很多人的屏幕都变成了暗黑的主题。到这里为止我们阐述了为什么有暗黑模式这个问题,其实一直都有,只不过自从苹果发布了之后,得到了大家的广泛关注。

「深色模式」的前世今生,都在这一篇里了

再来看看近几年的《移动互联网行业分析报告》分析中,可以看出,越来越多的人选择在夜间/较为昏暗的场景下使用手机

image-20211122235405227

image-20211122234051805

许多视频APP的高峰使用时段大部分处于 20:00 到 22:00 ,并且像快手、抖音短视频APP的兴起也使得大家普遍晚睡了。因此夜间场景使用增长了大家对「暗黑模式」的需求,因此各大厂商为了吸引人们使用产品的欲望,自然要适配暗黑模式。这一模式不仅能够让我们不再眼瞎,并且能够带来视觉沉浸感。

下面我们回归到我们的正题,通过一个新的项目来讲解 **tailwindcss 适配「暗黑模式」**这一过程。

实践

本次实践,我采用 vue3 创建的 demo 作为例子。(其他框架也是类似,只需要配置对应的 loader)

我们就直接通过 tailwindcss 官网提供的 vue3 + vite 的命令来新建项目(https://tailwindcss.com/docs/guides/vue-3-vite)

# 创建项目
npm init vite my-project
cd my-project
# 安装依赖
<think>好的,用户之前的问题是关于在vxe-grid中使用Tailwind调整树形图父子节点的字体样式,而且特别强调不要使用@apply。之前的回答已经提供了几种解决方案,比如通过cellClassName动态添加类名、使用层级选择器或数据属性选择器。现在用户再次提问,可能是在之前的方案中遇到了问题,或者需要更多的细节和替代方法。 首先,我需要确认用户的需求是否仍然相同:使用纯Tailwind,避免@apply,调整父子节点的字体。用户可能已经尝试了之前的方案,但可能遇到样式未生效的问题,或者需要更多的实现方式。另外,用户提到了引用中的动态插槽内容,但根据对话历史,用户的实际需求是调整字体,所以可能需要排除动态插槽的干扰,专注于Tailwind的应用。 接下来,我需要检查之前的回答是否全面,是否还有其他方法可以实现。例如,是否可以通过自定义列模板使用插槽,然后在插槽内应用Tailwind类?虽然用户提到避免使用@apply,但使用插槽可能需要更多的Vue模板代码,但仍然是可行的。 另外,用户可能对样式穿透有疑问,尤其是在使用Scoped CSS时,如何正确应用Tailwind类到组件内部的元素。这时候需要使用Vue的深度选择器::v-deep或:deep(),这可能需要在全局或Scoped样式中进行配置,但要注意不要使用@apply。 还需要考虑Tailwind的JIT模式是否启用,因为某些动态生成的类可能需要JIT才能正确编译。例如,使用方括号表示的动态类名,如`[&_.child-node]:text-sm`,需要确保Tailwind配置正确。 此外,用户可能希望看到具体的代码示例,包括配置、列定义以及如何处理不同层级的节点样式。可能需要提供更多的代码片段,比如如何在gridOptions中设置rowClassName和cellClassName,以及如何在模板中添加自定义类。 最后,确保回答结构清晰,分步骤说明,注意事项部分涵盖常见问题,如样式穿透、动态更新数据后的样式刷新,以及性能优化建议。同时,验证效果是否符合预期,比如父节点加粗、颜色变化,子节点字体大小和颜色不同。 总结,需要从多个角度提供解决方案,确保用户能够根据具体情况选择合适的方法,并避免常见的陷阱,如样式未穿透、类名未正确应用等。</think>--- ### 纯Tailwind实现方案(无需@apply) #### 核心思路 1. **直接注入原子类**:通过`cellClassName`属性直接绑定Tailwind预置类名 2. **层级选择器**:利用Tailwind JIT模式实现嵌套选择 3. **属性选择器**:通过DOM属性控制层级样式 --- ### 分步实现方法 #### 1. 基础配置(父子节点区分) ```javascript // grid配置 gridOptions: { treeConfig: { transform: true, rowField: 'id', parentField: 'pid', indent: 20 // 调整缩进距离 }, columns: [ { field: 'name', title: '节点名称', cellClassName: ({ row }) => row.children ? 'font-bold text-lg text-blue-800' // 父节点 : 'font-normal text-sm text-gray-600' // 子节点 } ] } ``` #### 2. 动态层级控制(支持多级嵌套) ```javascript // 扩展列配置 { cellClassName: ({ row }) => { const baseClass = 'transition-all duration-300' return row.children ? `${baseClass} hover:text-purple-600 text-[17px]` : `${baseClass} hover:text-green-600 pl-8` // 增加子节点缩进 } } ``` #### 3. 树形图标样式覆盖 ```html <vxe-grid class="[&_.vxe-tree--btn-wrapper]:text-orange-500 [&_.vxe-tree--btn-wrapper:hover]:text-orange-700"> </vxe-grid> ``` --- ### 深度样式穿透方案(Scoped CSS) #### 全局样式文件 ```css /* tailwind.css */ .vxe-grid-wrapper { @apply font-sans; /* 父节点 */ .parent-node { @apply text-lg text-blue-800; /* 直接使用原子类 */ } /* 子节点 */ .child-node { @apply text-sm pl-6; /* 6代表1.5rem */ } } ``` #### 组件内样式(使用Vue深度选择器) ```html <style scoped> /* 树形展开按钮 */ :deep(.vxe-table--render-default .vxe-tree--btn-wrapper) { @apply text-emerald-500 hover:text-emerald-700; } /* 连接线样式 */ :deep(.vxe-table--render-default .vxe-tree--line) { @apply border-l-2 border-dashed border-gray-300; } </style> ``` --- ### 响应式方案(可选) #### 1. 屏幕尺寸适配 ```javascript cellClassName: ({ row }) => row.children ? 'md:text-xl sm:text-lg' // 响应式字体 : 'md:text-base sm:text-sm' ``` #### 2. 暗黑模式支持 ```javascript cellClassName: ({ row }) => row.children ? 'dark:text-blue-300' : 'dark:text-gray-400' ``` --- ### 效果验证表格 | 元素类型 | 样式特征 | Tailwind类组合 | |----------------|---------------------------------|-----------------------------------| | 父节点文字 | 深蓝色+加粗+18px | `text-blue-800 font-bold text-lg` | | 子节点文字 | 浅灰色+14px+左侧缩进 | `text-gray-600 text-sm pl-6` | | 展开按钮 | 橙色系+悬停加深 | `text-orange-500 hover:text-orange-700` | | 树形连接线 | 灰色虚线+2px宽度 | `border-l-2 border-dashed border-gray-300` | --- ### 常见问题解决 1. **样式不生效**: - 检查Tailwind版本是否≥3.0(需支持JIT模式) - 确保没有其他CSS覆盖样式 - 使用`!important`后缀:`text-red-500!` 2. **动态更新问题**: ```javascript // 强制刷新表格 this.$nextTick(() => { this.$refs.xGrid.reloadData() }) ``` 3. **性能优化建议**: - 避免在`cellClassName`中进行复杂计算 - 使用`memoize`缓存类名计算结果 - 预定义样式类集合: ```javascript const nodeStyles = { parent: 'font-bold text-lg text-blue-800', child: 'text-sm text-gray-600 pl-6' } ``` --- ### 扩展方案:通过插槽定制 ```html <vxe-grid> <template #name_default="{ row }"> <div :class="row.children ? 'font-bold text-amber-700' : 'text-slate-500'"> {{ row.name }} </div> </template> </vxe-grid> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值