Tailwind CSS v3.2: 动态断点、多配置和容器查询,太棒了!

Adam Wathan
Tailwind CSS v3.2

Tailwind CSS v3.2 以绝对 庞大的 新内容到来,包括对动态断点、单个项目中的多个配置文件、嵌套组、参数化变体、容器查询等的支持。

一如既往,请查看 发布说明 以获取每一个琐碎的修复和改进,但这里是重点回顾:

通过从 npm 安装最新版本的 tailwindcss 来升级你的项目:

npm install -D tailwindcss@latest

或在 Tailwind Play 中尝试新功能,你可以立即在浏览器中尝试一切。


使用 @config 在一个项目中多个配置文件

我们添加了一个新的 @config 指令,你可以在 CSS 文件中使用它来指定该文件要使用的 Tailwind CSS 配置:

@config "./tailwind.admin.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;

这使得在单一项目中构建多个具有独立 Tailwind 配置的样式表变得容易。例如,你可能为网站面向客户的部分有一个配置文件,而为管理员/后端区域有另一个配置文件。

你总是可以通过足够的 webpack 巫术来做到这一点,但新的 @config 指令让每个人都能轻松使用,即使在你对构建工具配置没有太多控制的项目中也是如此。


基于支持的样式与 supports-*

你现在可以根据用户浏览器是否支持某个特性有条件地样式化内容,使用 supports-[...] 变体,该变体在底层生成 @supports 规则

<div class="flex supports-[display:grid]:grid ...">
<!-- ... -->
</div>

supports-[...] 变体接受你在方括号中可以使用的任何内容,如属性/值对,甚至使用 andor 的表达式。

如果你只需要检查某个属性本身是否受支持,你甚至可以仅指定属性名称,Tailwind 会为你自动填充:

<div class="bg-black/75 supports-[backdrop-filter]:bg-black/25 supports-[backdrop-filter]:backdrop-blur ...">
<!-- ... -->
</div>

ARIA 属性变体

你现在可以根据 ARIA 属性 使用新的 aria-* 变体有条件地样式化内容。

例如,你可以根据 aria-checked 状态是否为 true 更新元素的背景颜色:

<span class="bg-gray-600 aria-checked:bg-blue-600" aria-checked="true" role="checkbox">
<!-- ... -->
</span>

默认情况下,我们为最常用的布尔 ARIA 属性包含了修饰符:

修饰符CSS
aria-checked&[aria-checked="true"]
aria-disabled&[aria-disabled="true"]
aria-expanded&[aria-expanded="true"]
aria-hidden&[aria-hidden="true"]
aria-pressed&[aria-pressed="true"]
aria-readonly&[aria-readonly="true"]
aria-required&[aria-required="true"]
aria-selected&[aria-selected="true"]

你可以通过编辑 tailwind.config.js 文件中的 theme.ariatheme.extend.aria 来自定义可用的 aria-* 修饰符:

tailwind.config.js
module.exports = {
theme: {
extend: {
aria: {
asc: 'sort="ascending"',
desc: 'sort="descending"',
},
},
},
};

如果你需要使用一次性的 aria 修饰符,这个修饰符在你的主题中没有意义,或者用于需要特定值的更复杂的 ARIA 属性,请使用方括号通过任何任意值动态生成属性。

发票 #客户金额
#100Pendant Publishing$2,000.00
#101Kruger Industrial Smoothing$545.00
#102J. Peterman$10,000.25
<table>
<thead>
<tr>
<th
aria-sort="ascending"
class="aria-[sort=ascending]:bg-[url('/img/down-arrow.svg')] aria-[sort=descending]:bg-[url('/img/up-arrow.svg')]"
>
发票 #
</th>
<!-- ... -->
</tr>
</thead>
<!-- ... -->
</table>

ARIA 状态修饰符还可以通过 group-aria-*peer-aria-* 修饰符来定位父级和兄弟元素:

<table>
<thead>
<tr>
<th aria-sort="ascending" class="group">
发票 #
<svg
class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"
>
<!-- ... -->
</svg>
</th>
<!-- ... -->
</tr>
</thead>
<!-- ... -->
</table>

数据属性变体

你现在可以根据 数据属性 使用新的 data-* 变体有条件地样式化内容。

由于按定义没有标准的 data-* 属性,我们仅支持任意值,例如:

<!-- 将应用 -->
<div data-size="large" class="data-[size=large]:p-8">
<!-- ... -->
</div>
<!-- 不会应用 -->
<div data-size="medium" class="data-[size=large]:p-8">
<!-- ... -->
</div>
<!-- 生成的 CSS -->
<style>
.data-\[size\=large\]\:p-8[data-size="large"] {
padding: 2rem;
}
</style>

你可以在 tailwind.config.js 文件的 theme 部分下,根据项目中使用的常见数据属性选择器配置快捷方式:

// tailwind.config.js
module.exports = {
theme: {
data: {
checked: 'ui~="checked"',
},
},
// ...
};
<div data-ui="checked active" class="data-checked:underline">
<!-- ... -->
</div>

这些变体也像框架中的许多其他变体一样,支持 group-*peer-* 变体:

<div data-size="large" class="group">
<div class="group-data-[size=large]:p-8">
<!-- 将应用 `p-8` -->
</div>
</div>
<div data-size="medium" class="group">
<div class="group-data-[size=large]:p-8">
<!-- 将不会应用 `p-8` -->
</div>
</div>

最大宽度和动态断点

我们添加了一个新的 max-* 变体,让你可以根据配置的断点应用最大宽度媒体查询:

<div class="max-lg:p-8">
<!-- 在 `lg` 断点生效之前将应用 `p-8` -->
</div>

作为一般规则,我个人仍然建议使用最小宽度断点,但此功能确实解锁了一个有用的工作流好处,即不必在不同的断点上 撤消 某些样式。

例如,没有此功能时,你经常会这样做:

<div class="md:sr-only xl:not-sr-only">
<!-- ... -->
</div>

有了这个功能,你可以通过在原始声明上堆叠 max-* 变体来避免撤消该样式:

<div class="md:max-xl:sr-only">
<!-- ... -->
</div>

此外,我们还添加了对任意值的支持,以及只接受任意值的新 min-* 变体,因此你可以这样使用:

<div class="min-[712px]:max-[877px]:right-16 ...">
<!-- ... -->
</div>

重要的是要注意,这些功能仅在你的项目使用简单的 screens 配置时可用。

这些功能比看起来复杂得多,因为需要确保所有这些媒体查询在最终的 CSS 中按预期的方式进行排序,以便在浏览器中获得期望的行为。因此,目前,它们仅在你的 screens 配置是简单的字符串值对象时有效,如默认配置:

// tailwind.config.js
module.exports = {
theme: {
screens: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
},
},
};

如果你有一个复杂的配置,其中已经定义了最大宽度断点,或者基于范围的媒体查询,或 任何 其他内容,而不仅仅是字符串,这些功能将不可用。我们可能将来能够解决这个问题,但这确实引发了许多关于 CSS 应该如何排序的问题,而我们目前没有答案。

因此,目前(也可能永远如此),如果你想使用这些功能,你的 screens 配置需要简单。我的希望是这些功能能让复杂的 screens 配置变得不必要。


动态 group-* 和 peer-* 变体

现在可以动态创建自定义 group-*peer-* 变体,只需在方括号之间传递你自己的选择器以“分组”或“同侪化”:

<div class="group is-published">
<div class="group-[.is-published]:block hidden">已发布</div>
</div>

为了获得更多控制,您可以使用 & 字符标记 .group.peer 在最终选择器中与您传递的选择器的相对位置:

<div>
<input type="text" class="peer" />
<div class="peer-[:nth-of-type(3)_&]:block hidden">
<!-- ... -->
</div>
</div>

说真的,你可能一辈子只会用到这些功能三次,但这仍然非常酷。希望我们能够将此作为一个构建模块,使 grouppeer 在将来能够更自动地与第三方插件注册的变体一起使用。


使用 matchVariant 的动态变体

你可能注意到了这些新功能中有很多新的 variant-[...] 语法 — 这一切都是通过新的 matchVariant 插件 API 提供的,使创建我们所称的“动态变体”成为可能。

以下是为某个想象中的工具提示库创建 placement-* 变体的示例,该库使用 data-placement 属性告诉你工具提示当前的位置:

let plugin = require("tailwindcss/plugin");
module.exports = {
// ...
plugins: [
plugin(function ({ matchVariant }) {
matchVariant(
"placement",
(value) => {
return `&[data-placement=${value}]`;
},
{
values: {
t: "top",
r: "right",
b: "bottom",
l: "left",
},
},
);
}),
],
};

上述定义的变体将为你提供类似 placement-tplacement-b 的变体,但也会支持方括号中的任意部分,因此,如果这个虚构的工具提示库还有其他潜在值,你又不觉得需要为其创建内置值,你仍然可以这样做:

<div class="placement-[top-start]:mb-2 ...">
<!-- ... -->
</div>

在使用此 API 定义自定义变体时,通常很重要的是你对生成的 CSS 的顺序有一些控制,以确保每个类相对于来自同一变体的其他值具有正确的优先级。为此,你可以在定义变体时提供一个 sort 函数:

matchVariant("min", (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a) - parseInt(z);
},
});

使用变体修饰符的嵌套组和多个同侪支持

有时,当你拥有多个嵌套的 group 块时,可能会遇到问题,因为 Tailwind 没有真正的方法来区分它们。

为了解决这个问题,我们添加了对 变体修饰符 的支持,这是你可以添加到变体末尾的新的动态块(灵感来自我们可选的不透明度修饰符语法),你可以使用它来给每个组/同侪一个自己的标识符。

这看起来是这样的:

<div class="group/sidebar ...">
<!-- ... -->
<div class="group/navitem ...">
<a href="#" class="opacity-50 group-hover/navitem:bg-black/75 group-hover/sidebar:opacity-75">
<!-- ... -->
</a>
</div>
<!-- ... -->
</div>

这让你可以在飞行中为每个组提供一个清晰的名称,这在上下文中是有意义的,Tailwind 会生成必要的 CSS 使其工作。

我非常高兴能够为此提供解决方案,因为这是我多年来一直尝试解决的一个好方法,这是我们首次提出真正能提供我认为应该有的力量和灵活性的方法。


容器查询

我几乎不敢相信,但 容器查询 终于真实存在,浏览器支持接近于使这些准备好投入生产 — 实际上,如果您正在构建一个 Electron 应用程序,您今天就可以使用这些功能。

今天,我们发布了 @tailwindcss/container-queries,这是一个新的第一方插件,它为框架添加了容器查询支持,使用新的 @ 语法将其与正常媒体查询区分开来:

<div class="@container">
<div class="block @lg:flex">
<!-- ... -->
</div>
</div>

开箱即用,我们包括了一组与我们的默认 max-width 比例相匹配的容器大小:

名称
xs20rem
sm24rem
md28rem
lg32rem
xl36rem
2xl42rem
3xl48rem
4xl56rem
5xl64rem
6xl72rem
7xl80rem

你可以使用 tailwind.config.js 文件中的 containers 键配置可用的值:

// tailwind.config.js
module.exports = {
theme: {
extend: {
containers: {
"2xs": "16rem",
// 等等...
},
},
},
};

我们还支持任意值,使用 @[...] 语法:

<div class="@container">
<div class="block @[618px]:flex">
<!-- ... -->
</div>
</div>

...和使用与我们现在为 group-*peer-* 变体提供的相同变体修饰符语法的命名容器:

<div class="@container/main">
<!-- ... -->
<div>
<div class="block @lg/main:flex">
<!-- ... -->
</div>
</div>
</div>

现在我们从简单的基于最小宽度的容器查询开始,但我们计划逐渐扩展范围,当我们感觉我们真的解决了这些 API 时,所有内容将被纳入核心。

有关完整的文档,请查看 Github 上的插件


所以你看,这就是 Tailwind CSS v3.2!重大改进但只是小版本更改,因此没有重大更改,你应该能够通过简单地更新依赖项来更新项目:

npm install -D tailwindcss@latest

是的,我听到你在后面说,仍然没有文本阴影,但嘿,至少你可以在不离开 HTML 的情况下样式化复选框的兄弟元素,当复选框的父元素是列表中的第三个子元素。优先事项,朋友们。

Get all of our updates directly to your inbox.
Sign up for our newsletter.