自从我们发布了 Tailwind CSS v3.0,已经过去了六个月,尽管我们自那时以来在代码库中收集了许多小改进,但我们还没有 that-one-feature 让你说 "好吧,是时候发布了"。
然后在几周前的一个随机星期六晚上,我在 Discord 中和 Robin 聊天,讨论如何使用 :has
选择器和文档中更深层的类来选择 html
元素,并解释了如果我们添加对任意变体的支持会是什么样子——这是我想处理的事情已经超过一年了:
![Adam Wathan: 我认为如果我们做任意变体,语法应该就是这样 '[html:has(&)]:bg-blue-500'。感觉这很灵活,就像你用真正的变体能做的任何事情,你也可以用任意变体做,因为它们是同一回事。 '[&>*:not(:first-child)]:pl-4'。
Robin: 这会弄乱我的脑子哈哈,因为 '[html:has(&)]:bg-blue-500' 会被用作 '&' 中的字面量。结合其他变体... 🤯。
Adam Wathan: 😅,这肯定会神经凌乱。CSS 会是这样的,哈哈 'html:has([html:has(&)]:bg-blue-500 {"{"} background: blue 500 }'。
Robin: 完全正确哈哈。好的,现在我想试试,稍等。](/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdiscord-message.225e322a.png&w=3840&q=75)
二十分钟后,Robin 有了一个工作的概念验证 (只有六行代码!),再加上一个小时左右,Jordan 在我们的类检测引擎中进行正则表达式奇迹之后, 任意变体 出现了,我们拥有了值得发布的功能。
所以这是——Tailwind CSS v3.1!完整的修复和改进列表请查看 发布说明,但这里是亮点:
- 官方 TypeScript 类型
- CLI 的 CSS 导入内置支持
- 使用主题函数时更改颜色的不透明度
- 更简单的 CSS 变量颜色配置
- 边框间距工具
- 启用和可选变体
- 优先对比变体
- 样式原生对话框背景
- 变体的任意值
通过从 npm 安装最新版本的 tailwindcss
来升级你的项目:
npm install tailwindcss@latest
或者启动一个 Tailwind Play 在浏览器中随便玩玩所有新的功能。
官方 TypeScript 类型
我们现在为您在使用 Tailwind 时所用的所有 JS API 提供类型,最显著的是 tailwind.config.js
文件。这意味着您可以获得各种有用的 IDE 支持,并且使更改配置时无需频繁参考文档变得容易得多。
要设置它,只需在配置定义上方添加类型注释:
/** @type {import('tailwindcss').Config} */module.exports = { content: [ // ... ], theme: { extend: {}, }, plugins: [],};
如果你是个 TypeScript 发烧友,你可能会喜欢探索实际的 类型定义——为了支持这样一个潜在复杂的对象,里面有很多有趣的内容。
CLI 的 CSS 导入内置支持
如果你正在使用我们的 CLI 工具来编译 CSS,postcss-import
现在已经内置这样你可以将自定义 CSS 组织成多个文件,而无需任何额外配置。
@import "tailwindcss/base";@import "./select2-theme.css";@import "tailwindcss/components";@import "tailwindcss/utilities";
如果你不使用我们的 CLI 工具而是将 Tailwind 作为 PostCSS 插件使用,你仍需要像使用 autoprefixer
一样安装并配置 postcss-import
,但如果你 使用 我们的 CLI 工具,它现在将会完全可用。
这对于使用我们 独立 CLI 并且不想安装任何节点依赖的用户来说尤其便利。
使用主题函数时更改颜色的不透明度
我认为很多人不知道这一点,但 Tailwind 将一个 theme()
函数 引入了您的 CSS 文件,这可以让您从配置文件中获取值——有点像将它们转换为您可以重用的变量。
.select2-dropdown { border-radius: theme(borderRadius.lg); background-color: theme(colors.gray.100); color: theme(colors.gray.900);}/* ... */
但有一个限制,你无法调整通过这种方式获取的任何颜色的 alpha 通道。因此,在 v3.1 中,我们添加了使用斜杠语法来调整不透明度的支持,就像你可以使用现代的 rgb
和 hsl
CSS 颜色函数那样:
.select2-dropdown { border-radius: theme(borderRadius.lg); background-color: theme(colors.gray.100 / 50%); color: theme(colors.gray.900);}/* ... */
我们还在 tailwind.config.js
文件中的 theme
函数中实现了这一点:
module.exports = { content: [ // ... ], theme: { extend: { colors: ({ theme }) => ({ primary: theme("colors.blue.500"), "primary-fade": theme("colors.blue.500 / 75%"), }), }, }, plugins: [],};
您甚至可以在任意值中使用这个功能,这真是太疯狂了——老实说,对于奇怪的自定义渐变等来说,意外的有用:
<div class="bg-[image:linear-gradient(to_right,theme(colors.red.500)_75%,theme(colors.red.500/25%))]"> <!-- ... --></div>
为了避免编辑 CSS 文件,我是对的?
更简单的 CSS 变量颜色配置
如果你喜欢将颜色定义为 CSS 变量,您可能在 tailwind.config.js
文件中有一些可怕的样板代码,如下所示:
function withOpacityValue(variable) { return ({ opacityValue }) => { if (opacityValue === undefined) { return `rgb(var(${variable}))`; } return `rgb(var(${variable}) / ${opacityValue})`; };}module.exports = { theme: { colors: { primary: withOpacityValue("--color-primary"), secondary: withOpacityValue("--color-secondary"), // ... }, },};
通过在 v3.1 中添加使用格式字符串定义颜色的支持,我们让这一切变得简单得多,我们不再需要使用函数:
module.exports = { theme: { colors: { primary: "rgb(var(--color-primary) / <alpha-value>)", secondary: "rgb(var(--color-secondary) / <alpha-value>)", // ... }, },};
不再需要编写接收 opacityValue
参数的函数,你只需要编写一个带有 <alpha-value>
占位符的字符串,Tailwind 将会根据工具类替换该占位符为正确的 alpha 值。
如果你以前没有见过这些,请查看我们更新的 使用 CSS 变量 文档以获取更多细节。
边框间距工具
我们添加了一组新的工具用于 border-spacing
属性,因此你可以控制在使用 分离边框 时表格边框之间的空间:
州 | 城市 |
---|---|
印第安纳州 | 印第安纳波利斯 |
俄亥俄州 | 哥伦布 |
密歇根州 | 底特律 |
<table class="border-separate border-spacing-2 ..."> <thead> <tr> <th class="border border-slate-300 ...">州</th> <th class="border border-slate-300 ...">城市</th> </tr> </thead> <tbody> <tr> <td class="border border-slate-300 ...">印第安纳州</td> <td class="border border-slate-300 ...">印第安纳波利斯</td> </tr> <!-- ... --> </tbody></table>
我知道你在想什么—— "我一辈子都没想过要建一个看起来像这样的表格..." — 但是请听我说说!
一个实际超级有用的情况是,当你在构建一个带有粘性表头的表格时,并且你想在标题下方保留一个持久的底边框:
滚动该表格以观察粘性表头的效果
姓名 | 角色 | |
---|---|---|
Courtney Henry | courtney.henry@example.com | 管理员 |
Tom Cook | tom.cook@example.com | 成员 |
Whitney Francis | whitney.francis@example.com | 管理员 |
Leonard Krasner | leonard.krasner@example.com | 所有者 |
Floyd Miles | floyd.miles@example.com | 成员 |
Emily Selman | emily.selman@example.com | 成员 |
Kristin Watson | kristin.watson@example.com | 管理员 |
Emma Dorsey | emma.dorsey@example.com | 成员 |
Alicia Bell | alicia.bell@example.com | 管理员 |
Jenny Wilson | jenny.wilson@example.com | 所有者 |
Anna Roberts | anna.roberts@example.com | 成员 |
Benjamin Russel | benjamin.russel@example.com | 成员 |
Jeffrey Webb | jeffrey.webb@example.com | 管理员 |
Kathryn Murphy | kathryn.murphy@example.com | 成员 |
<table class="border-separate border-spacing-0"> <thead class="bg-gray-50"> <tr> <th class="sticky top-0 z-10 border-b border-gray-300 ...">姓名</th> <th class="sticky top-0 z-10 border-b border-gray-300 ...">邮箱</th> <th class="sticky top-0 z-10 border-b border-gray-300 ...">角色</th> </tr> </thead> <tbody class="bg-white"> <tr> <td class="border-b border-gray-200 ...">Courtney Henry</td> <td class="border-b border-gray-200 ...">courtney.henry@example.com</td> <td class="border-b border-gray-200 ...">管理员</td> </tr> <!-- ... --> </tbody></table>
你可能会认为你可以在这里只使用 border-collapse
,因为实际上你不希望边框之间有任何空间,但你会错。没有 border-separate
和 border-spacing-0
,边框将在滚动时消失,而不是粘附在标题下。CSS 是多么有趣啊?
查看 边框间距文档 以获取更多详细信息。
启用和可选变体
我们为 :enabled
和 :optional
伪类添加了新的变体,针对表单元素在启用和可选时的状态。
"但是 Adam,为什么我需要这些,启用和可选甚至不是状态,它们是默认值。你真的会写网站吗?"
哎,这真是痛,因为这是真的——我现在基本上只是在写电子邮件和在 GitHub 上反复回答相同的问题。
但是看看这个禁用按钮的示例:
<button type="button" class="bg-indigo-500 hover:bg-indigo-400 disabled:opacity-75 ..." disabled>正在处理...</button>
注意在你将鼠标悬停在按钮上时,即使它被禁用,背景颜色仍然会改变?在这个版本之前,通常你会这样解决这个问题:
<button type="button" class="bg-indigo-500 hover:bg-indigo-400 disabled:opacity-75 disabled:hover:bg-indigo-500 ..." disabled> 正在处理...</button>
但使用新的 enabled
修饰符,你可以这样编写:
<button type="button" class="bg-indigo-500 hover:enabled:bg-indigo-400 disabled:opacity-75 ..." disabled> 正在处理...</button>
我们不再在按钮被禁用时将悬停颜色重置为默认色,而是组合 hover
和 enabled
变体,使按钮在禁用的情况下根本不应用悬停样式。我觉得这样更好!
这是一个结合新的 optional
修饰符和我们的 同胞状态特征 的示例,以隐藏对非必需字段的 "必填" 提示:
<form> <div> <label for="email" ...>邮箱</label> <div> <input required class="peer ..." id="email" /> <div class="peer-optional:hidden ...">必填</div> </div> </div> <div> <label for="name" ...>姓名</label> <div> <input class="peer ..." id="name" /> <div class="peer-optional:hidden ...">必填</div> </div> </div> <!-- ... --></form>
这让你可以对所有表单组使用相同的标记,并让 CSS 处理所有条件渲染,而不是自己处理。真是不错的主意!
优先对比变体
你知道有 prefers-contrast
媒体查询吗?其实是有的,Tailwind 现在开箱即用支持它。
使用新的 contrast-more
和 contrast-less
变体,当用户请求更多或更少的对比度时修改设计,通常通过操作系统的可访问性首选项,如 macOS 上的 “增加对比度”。
在开发者工具中尝试模拟 `prefers-contrast: more` 以查看更改
<form> <label class="block"> <span class="block text-sm font-medium text-slate-700">社会安全号码</span> <input class="border-slate-200 placeholder-slate-400 contrast-more:border-slate-400 contrast-more:placeholder-slate-500" /> <p class="mt-2 text-sm text-slate-600 opacity-10 contrast-more:opacity-100">我们需要这个以窃取你的身份。</p> </label></form>
我写过 一些文档,但老实说,我在这里写的更多。
样式原生对话框背景
有一个相当新的 HTML <dialog>
元素,支持相当不错的 浏览器,如果你喜欢在前沿探索,值得玩玩。
对话框有一个在对话框打开时呈现的新的 ::backdrop
伪元素,而 Tailwind CSS v3.1 添加了可以用来样式化这个背景的新 backdrop
修饰符:
<dialog class="backdrop:bg-slate-900/50 ..."> <form method="dialog"> <!-- ... --> <button value="cancel">取消</button> <button>提交</button> </form></dialog>
如果您想深入了解这个东西,我建议阅读 MDN 对话框文档——这都是令人兴奋的内容,但有很多内容需要掌握。
变体的任意值
好了,这个对我来说是真正的亮点——你知道我们给你提供了 addVariant
API 用于创建自定义变体吗?
const plugin = require("tailwindcss/plugin");module.exports = { // ... plugins: [ plugin(function ({ addVariant }) { addVariant("third", "&:nth-child(3)"); }), ],};
...你知道我们有 任意值 可以直接在你的 HTML 中使用任何想要的值吗?
<!--] --><div class="top-[117px]"> <!-- ... --></div>
那么 Tailwind CSS v3.1 引入了 任意变体,让你可以直接在 HTML 中创建自己的自定义变体:
<div class="[&:nth-child(3)]:py-0"> <!-- ... --></div>
这对那种感觉需要参数化的变体非常有用,比如使用 @supports
查询在浏览器支持特定 CSS 功能时添加样式:
<div class="bg-white [@supports(backdrop-filter:blur(0))]:bg-white/50 [@supports(backdrop-filter:blur(0))]:backdrop-blur"> <!-- ... --></div>
你甚至可以像使用任意变体那样针对子元素,如 [&>*]
:
Kristen Ramos
kristen.ramos@example.com
Floyd Miles
floyd.miles@example.com
Courtney Henry
courtney.henry@example.com
<ul role="list" class="space-y-4 [&>*]:rounded-lg [&>*]:bg-white [&>*]:p-4 [&>*]:shadow"> <li className="flex"> <img className="h-10 w-10 rounded-full" src="..." alt="" /> <div className="ml-3 overflow-hidden"> <p className="text-sm font-medium text-slate-900">Kristen Ramos</p> <p className="truncate text-sm text-slate-500">kristen.ramos@example.com</p> </div> </li> <!-- ... --></ul>
你甚至可以在第二个子 li
中的 div
内部样式设置第一个 p
,但是只在 hover
的时候:
尝试将鼠标悬停在文本 “Floyd Miles” 上
Kristen Ramos
kristen.ramos@example.com
Floyd Miles
floyd.miles@example.com
Courtney Henry
courtney.henry@example.com
<ul role="list" class="space-y-4 [&>*]:rounded-lg [&>*]:bg-white [&>*]:p-4 [&>*]:shadow hover:[&>li:nth-child(2)>div>p:first-child]:text-indigo-500"> <!-- ... --> <li className="flex"> <img className="h-10 w-10 rounded-full" src="..." alt="" /> <div className="ml-3 overflow-hidden"> <p className="text-sm font-medium text-slate-900">Floyd Miles</p> <p className="truncate text-sm text-slate-500">floyd.miles@example.com</p> </div> </li> <!-- ... --></ul>
那么 你应该做这个吗? 大概不是很频繁,但老实说,当你尝试样式设置 HTML 而无法直接修改时,这可能是一个非常有用的逃生口。这是一把锋利的刀,但最好的厨师不需要用安全剪刀来准备食物。
玩玩它们,我敢打赌你会发现当情况需要时,它们是一个很好的工具。我们在这些新网站模板的几个棘手的地方使用它们,体验优于创建自定义类。
这就是 Tailwind CSS v3.1!这只是一个小版本的更改,所以没有重大变化,你应该能够通过只安装最新版本来更新你的项目:
npm install tailwindcss@latest
有关更改的完整列表,包括错误修复和一些我在这里没有谈论的小改进,请查看 GitHub 上的 发布说明。
我已经有了一大堆关于 Tailwind CSS v3.2 的想法 (也许最终能加入文本阴影?!),但目前我们正在努力推进这些新 网站模板 完成。请在接下来的一两个星期内关注该主题的其他更新!