Tailwind CSS v3.1:你想疯狂一把吗?来吧,让我们疯狂起来!

日期

自从我们发布 Tailwind CSS v3.0 已经过去了大约六个月,尽管我们一直在代码库中收集许多小的改进,但我们还没有找到那个功能,它会让你说“好吧,现在是发布的时候了”

然后,几周前的一个随机的星期六晚上,我在我们的 Discord 上和 Robin 讨论如何使用:has 和文档中更深层的类来定位html 元素,并解释了如果我们添加对任意变体的支持,我认为它会是什么样子——这是我一年多来一直想解决的问题。

Adam Wathan: I think if we do arbitrary variants, the syntax should just be that exact thing, '[html:has(&)]:bg-blue-500'. Feel like that is pretty flexible, like anything you can do with a real variant you can also do with an arbitrary variant since they are the same thing. '[&>*:not(:first-child)]:pl-4'. Robin: This is going to break my brain haha because '[html:has(&)]:bg-blue-500' would be used as a literal inside the '&'. That in combination with other variants... 🤯. Adam Wathan: 😅 it'll be a brain melter for sure. The CSS would be this lol 'html:has(\[html\:has\(\&\)\]\:bg-blue-500 { background: blue 500 }'. Robin: exactly haha. ok, now I want to try that brb.

20 分钟后,Robin 就有了可行的概念证明(只有六行代码!),在 Jordan 在我们的类检测引擎中进行了一个多小时的正则表达式奇迹之后,任意变体 就诞生了,我们有了值得发布的功能。

所以,它来了——Tailwind CSS v3.1!有关所有修复和改进的完整列表,请查看 发布说明,但以下是重点。

从 npm 安装最新版本的tailwindcss 来升级您的项目。

npm install tailwindcss@latest

或者启动一个 Tailwind Play,在浏览器中玩弄所有新功能。


第一方 TypeScript 类型

我们现在为所有在使用 Tailwind 时使用的 JS API 提供类型,最值得注意的是 `tailwind.config.js` 文件。这意味着您将获得各种有用的 IDE 支持,并且更容易对配置进行更改,而无需过多地参考文档。

要设置它,只需在您的配置定义上方添加类型注释

tailwind.config.js
/** @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 向您的 CSS 文件公开了一个 theme() 函数,它允许您从您的配置文件中获取值 - 将它们变成可以重复使用的变量。

select2-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-theme.css
.select2-dropdown {
  border-radius: theme(borderRadius.lg);
  background-color: theme(colors.gray.100 / 50%);
  color: theme(colors.gray.900);
}
/* ... */

我们也让它在您的 `tailwind.config.js` 文件中的 `theme` 函数中起作用。

tailwind.config.js
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 文件中有一些可怕的样板代码

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 中通过添加对使用格式字符串定义颜色的支持,使这变得不那么糟糕,而不是必须使用函数

tailwind.config.js
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 ...">State</th>
      <th class="border border-slate-300 ...">City</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="border border-slate-300 ...">Indiana</td>
      <td class="border border-slate-300 ...">Indianapolis</td>
    </tr>
    <!-- ... -->
  </tbody>
</table>

我知道你在想什么——“我一生中从未想过要构建一个看起来像这样的表格……”——但请听我说一下!

这实际上非常有用的一种情况是,当构建一个带有粘性标题行的表格时,你想要在标题下方有一个持久的下边框

滚动此表格以查看粘性标题行的实际效果

姓名 角色
Courtney Henry 管理员
汤姆·库克 成员
惠特尼·弗朗西斯 管理员
莱昂纳德·克拉斯纳 所有者
弗洛伊德·迈尔斯 成员
艾米丽·塞尔曼 成员
克里斯汀·沃森 管理员
艾玛·多西 成员
艾丽西亚·贝尔 管理员
珍妮·威尔逊 所有者
安娜·罗伯茨 成员
本杰明·拉塞尔 成员
杰弗里·韦伯 管理员
凯瑟琳·墨菲 成员
<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 ...">Name</th>
      <th class="sticky top-0 z-10 border-b border-gray-300 ...">Email</th>
      <th class="sticky top-0 z-10 border-b border-gray-300 ...">Role</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 ...">[email protected]</td>
      <td class="border-b border-gray-200 ...">Admin</td>
    </tr>
    <!-- ... -->
  </tbody>
</table>

你可能会认为你可以直接使用 border-collapse,因为你实际上不需要边框之间有任何间距,但你错了。如果没有 border-separateborder-spacing-0,边框会滚动而不是粘在标题下方。CSS 真有趣,不是吗?

查看 边框间距文档 以了解更多详细信息。

启用和可选变体

我们为 :enabled:optional 伪类添加了新的变体,它们在表单元素处于启用和可选状态时会针对这些元素。

“但是亚当,我为什么要使用这些,启用和可选甚至不是状态,它们是默认值。你甚至会制作网站吗?”

哎哟,这很痛,因为这是真的——我现在几乎只写邮件,并在 GitHub 上一遍又一遍地回答同样的问题。

但是看看这个禁用的按钮示例

<button type="button" class="bg-indigo-500 hover:bg-indigo-400 disabled:opacity-75 ..." disabled>
  Processing...
</button>

注意,当您将鼠标悬停在按钮上时,即使它被禁用,背景颜色仍然会发生变化?在此版本之前,您通常会像这样修复它

<button type="button" class="disabled:hover:bg-indigo-500 bg-indigo-500 hover:bg-indigo-400 disabled:opacity-75  ..." disabled>
  Processing...
</button>

但是使用新的 enabled 修饰符,您可以改为这样写

<button type="button" class="bg-indigo-500 hover:enabled:bg-indigo-400 disabled:opacity-75  ..." disabled>
  Processing...
</button>

我们没有在按钮被禁用时将悬停颜色覆盖回默认颜色,而是将 hoverenabled 变体组合在一起,以便在按钮被禁用时根本不应用悬停样式。我认为这样更好!

这是一个将新的optional修饰符与我们的兄弟状态功能结合在一起的示例,用于隐藏非必填字段的“必填”提示

必填
必填
<form>
  <div>
    <label for="email" ...>Email</label>
    <div>
      <input required class="peer ..." id="email" />
      <div class="peer-optional:hidden ...">
        Required
      </div>
    </div>
  </div>
  <div>
    <label for="name" ...>Name</label>
    <div>
      <input class="peer ..." id="name" />
      <div class="peer-optional:hidden ...">
        Required
      </div>
    </div>
  </div>
  <!-- ... -->
</form>

这样你就可以对所有表单组使用相同的标记,并让 CSS 处理所有条件渲染,而不是自己处理。很酷吧!

偏好对比度变体

你知道有一个prefers-contrast媒体查询吗?确实有,而且现在 Tailwind 默认支持它。

使用新的contrast-morecontrast-less变体,当用户请求更多或更少的对比度时修改你的设计,通常通过操作系统辅助功能偏好设置,例如 macOS 上的“增加对比度”。

尝试在你的开发者工具中模拟prefers-contrast: more,看看变化。

我们需要这个来窃取你的身份。

<form>
  <label class="block">
    <span class="block text-sm font-medium text-slate-700">Social Security Number</span>
    <input class="border-slate-200 placeholder-slate-400 contrast-more:border-slate-400 contrast-more:placeholder-slate-500"/>
    <p class="mt-2 opacity-10 contrast-more:opacity-100 text-slate-600 text-sm">
      We need this to steal your identity.
    </p>
  </label>
</form>

我写了一些文档,但说实话,我在这里写的比那里写的更多。

样式原生对话框背景

有一个非常新的HTML <dialog> 元素,具有令人惊讶的不错的浏览器支持,如果你喜欢走在技术前沿,值得尝试一下。

对话框有一个新的::backdrop伪元素,它在对话框打开时呈现,而 Tailwind CSS v3.1 添加了一个新的backdrop修饰符,你可以用它来设置这个元素的样式。

<dialog class="backdrop:bg-slate-900/50 ...">
  <form method="dialog">
    <!-- ... -->
    <button value="cancel">Cancel</button>
    <button>Submit</button>
  </form>
</dialog>

如果您想更深入地了解这个功能,我建议您阅读 MDN 对话框文档 — 这非常令人兴奋,但需要学习很多东西。

任意值,但用于变体

好的,这个对我来说是真正的亮点 — 您知道我们如何为您提供 addVariant API 来创建您自己的自定义变体吗?

tailwind.config.js
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>

您甚至可以使用此功能使用任意变体(如 [&>*])来定位子元素

<ul role="list" class="[&>*]:p-4 [&>*]:bg-white [&>*]:rounded-lg [&>*]:shadow space-y-4">
  <li class="flex">
    <img class="h-10 w-10 rounded-full" src="..." alt="" />
    <div class="ml-3 overflow-hidden">
      <p class="text-sm font-medium text-slate-900">Kristen Ramos</p>
      <p class="text-sm text-slate-500 truncate">[email protected]</p>
    </div>
  </li>
  <!-- ... -->
</ul>

您甚至可以为第二个子 li 中的第一个 p 设置样式,但仅在 hover 状态下

尝试将鼠标悬停在“Floyd Miles”文本上

<ul role="list" class="hover:[&>li:nth-child(2)>div>p:first-child]:text-indigo-500 [&>*]:p-4 [&>*]:bg-white [&>*]:rounded-lg [&>*]:shadow space-y-4">
  <!-- ... -->
  <li class="flex">
    <img class="h-10 w-10 rounded-full" src="..." alt="" />
    <div class="ml-3 overflow-hidden">
      <p class="text-sm font-medium text-slate-900">Floyd Miles</p>
      <p class="text-sm text-slate-500 truncate">[email protected]</p>
    </div>
  </li>
  <!-- ... -->
</ul>

现在,您应该这样做吗?可能不太经常,但老实说,当您尝试为无法直接更改的 HTML 设置样式时,它可能是一个非常有用的逃生舱口。它是一把锋利的刀,但最好的厨师不会用安全剪刀准备食物。

玩一玩它们,我敢打赌您会发现它们在需要时是一个很棒的工具。我们正在我们正在开发的一些新网站模板中使用它们,并且体验比创建自定义类要好得多。


这就是 Tailwind CSS v3.1!它只是一个次要版本更改,因此没有重大更改,您应该可以通过安装最新版本来更新您的项目

npm install tailwindcss@latest

有关所有更改的完整列表,包括错误修复和一些未在此处提及的小改进,请查看 GitHub 上的 发布说明

我已经为 Tailwind CSS v3.2 想好了很多想法(也许最终会有文字阴影?!),但现在我们正在努力推出这些新的 网站模板。在一两周内,我们将发布有关该主题的更多更新!