Tailwind CSS v3.2:动态断点、多配置和容器查询,我的天哪!

Adam Wathan
Tailwind CSS v3.2

Tailwind CSS v3.2 现已发布,包含大量新功能,包括支持动态断点、单个项目中的多个配置文件、嵌套组、参数化变体、容器查询等等。

¥Tailwind CSS v3.2 is here with an absolutely massive amount of new stuff, including support for dynamic breakpoints, multiple config files in a single project, nested groups, parameterized variants, container queries, and more.

一如既往,你可以查看 release notes 中每个细节的修复和改进,以下是精彩片段:

¥As always check out the release notes for every nitty-gritty fix and improvement, but here's the highlight reel:

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

¥Upgrade your projects by installing the latest version of tailwindcss from npm:

npm install -D tailwindcss@latest

或者,直接在浏览器中体验 Tailwind Play 中的新功能,你可以立即尝试所有功能。

¥Or play with the new features in Tailwind Play where you can try everything out instantly, right in the browser.


使用 @config 在一个项目中使用多个配置文件(Multiple config files in one project using @config)

¥Multiple config files in one project using @config

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

¥We've added a new @config directive that you can use in a CSS file to specify which Tailwind CSS config to use for that file:

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

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

¥This makes it a lot easier to build multiple stylesheets in a single project that have separate Tailwind configurations. For example, you might have one config file for the customer-facing part of your site, and another config for the admin/backend area.

从技术上讲,你一直能够通过足够的 webpack 技巧做到这一点,但新的 @config 指令使其变得非常简单,每个人都可以使用,即使在你无法控制构建工具配置的项目中也是如此。

¥You've always technically been able to do this with enough webpack wizardry, but the new @config directive makes it super easy and accessible to everyone, even in projects where you don't have as much control over the build tool configuration.


使用支持 * 的基于浏览器支持的样式(Browser-support-based styling with supports-*)

¥Browser-support-based styling with supports-*

现在,你可以使用 supports-[...] 变体,根据用户浏览器是否支持某项功能,有条件地设置样式,这会在后台生成 @supports rules

¥You can now conditionally style things based on whether a certain feature is supported in the user's browser with the supports-[...] variant, which generates @supports rules under the hood.

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

supports-[...] 变体接受方括号中任何与 @supports (...) 一起使用的内容,例如属性/值对,甚至使用 andor 的表达式。

¥The supports-[...] variant takes anything you'd use with @supports (...) between the square brackets, like a property/value pair, and even expressions using and and or.

如果你只需要检查某个属性本身是否受支持,你甚至可以只指定属性名称,Tailwind 会为你填写所有信息:

¥If you only need to check if a property itself is supported, you can even just specify the property name and Tailwind will fill in the blanks for you:

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

ARIA 属性变体(ARIA attribute variants)

¥ARIA attribute variants

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

¥You can now conditionally style things based on ARIA attributes with the new aria-* variants.

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

¥For example, you can update the background color of an element based on whether the aria-checked state is true:

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

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

¥By default we've included modifiers for the most common boolean ARIA attributes:

ModifierCSS
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-* 修饰符:

¥You can customize which aria-* modifiers are available by editing theme.aria or theme.extend.aria in your tailwind.config.js file:

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

如果你需要使用一次性的 aria 修饰符(该修饰符没有必要包含在主题中),或者对于需要特定值的更复杂的 ARIA 属性,请使用方括号使用任意值动态生成属性。

¥If you need to use a one-off aria modifier that doesn’t make sense to include in your theme, or for more complex ARIA attributes that take specific values, use square brackets to generate a property on the fly using any arbitrary value.

Invoice #ClientAmount
#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')]"
>
Invoice #
</th>
<!-- ... -->
</tr>
</thead>
<!-- ... -->
</table>

ARIA 状态修饰符还可以使用 group-aria-*peer-aria-* 修饰符来定位父元素和同级元素:

¥ARIA state modifiers can also target parent and sibling elements using the group-aria-* and peer-aria-* modifiers:

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

数据属性变体(Data attribute variants)

¥Data attribute variants

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

¥You can now conditionally style things based on data attributes with the new data-* variants.

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

¥Since there are no standard data-* attributes by definition, we only support arbitrary values out of the box, for example:

<!-- Will apply -->
<div data-size="large" class="data-[size=large]:p-8">
<!-- ... -->
</div>
<!-- Will not apply -->
<div data-size="medium" class="data-[size=large]:p-8">
<!-- ... -->
</div>
<!-- Generated CSS -->
<style>
.data-\[size\=large\]\:p-8[data-size="large"] {
padding: 2rem;
}
</style>

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

¥You can configure shortcuts for common data attribute selectors you're using in your project under the data key in the theme section of your tailwind.config.js file:

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

这些变体与框架中的许多其他变体一样,也可以用作 group-*peer-* 变体:

¥These variants also work as group-* and peer-* variants like many other variants in the framework:

<div data-size="large" class="group">
<div class="group-data-[size=large]:p-8">
<!-- Will apply `p-8` -->
</div>
</div>
<div data-size="medium" class="group">
<div class="group-data-[size=large]:p-8">
<!-- Will not apply `p-8` -->
</div>
</div>

最大宽度和动态断点(Max-width and dynamic breakpoints)

¥Max-width and dynamic breakpoints

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

¥We've added a new max-* variant that lets you apply max-width media queries based on your configured breakpoints:

<div class="max-lg:p-8">
<!-- Will apply `p-8` until the `lg` breakpoint kicks in -->
</div>

一般来说,我个人仍然建议使用最小宽度断点,但此功能确实带来了一个有用的工作流程优势,那就是无需在不同的断点处撤消某些样式。

¥As a general rule I would still recommend using min-width breakpoints personally, but this feature does unlock one useful workflow benefit which is not having to undo some style at a different breakpoint.

例如,如果没有此功能,你通常会执行以下操作:

¥For example, without this feature you often end up doing things like this:

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

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

¥With this feature, you can avoid undoing that style by stacking a max-* variant on the original declaration:

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

除此之外,我们还添加了对任意值的支持,以及一个只接受任意值的新 min-* 变体,因此你可以执行以下操作:

¥Along with this, we've added support for arbitrary values, and a new min-* variant that only accepts arbitrary values, so you can do things like this:

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

需要注意的是,只有当你的项目使用简单的 screens 配置时,这些功能才可用。

¥It's important to note that these features will only be available if your project uses a simple screens configuration.

这些功能比看起来要复杂得多,因为需要确保所有这些媒体查询在最终的 CSS 中都按预期的方式排序,以便在浏览器中提供预期的行为。目前,只有当你的 screens 配置是包含字符串值的简单对象(例如默认配置)时,它们才会起作用:

¥These features are a lot more complicated than they look due to needing to ensure that all of these media queries are sorted in the final CSS in a way that gives you the expected behavior in the browser. So for now, they will only work if your screens configuration is a simple object with string values, like the default configuration:

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

如果你的配置比较复杂,已经定义了 max-width 断点、基于范围的媒体查询,或者除了字符串之外的其他任何内容,则这些功能将不可用。我们将来或许能够解决这个问题,但这会引发很多关于 CSS 排序的问题,目前我们还没有答案。

¥If you have a complex configuration where you already have max-width breakpoints defined, or range-based media queries, or anything other than just strings, these features won't be available. We might be able to figure that out in the future but it just creates so many questions about how the CSS should be ordered that we don't have answers for yet.

因此,就目前而言(甚至可能永远如此),如果你想使用这些功能,你的 screens 配置需要简洁。我希望这些功能可以让复杂的 screens 配置变得不必要。

¥So for now (and possibly forever), if you want to use these features, your screens configuration needs to be simple. My hope is that these features make complex screens configurations unnecessary anyways.


动态 group-* 和 peer-* 变体(Dynamic group-* and peer-* variants)

¥Dynamic group-* and peer-* variants

现在可以通过在方括号中传递你自己的选择器("groupified" 或 "peerified")来动态创建自定义 group-*peer-* 变体:

¥It's now possible to create custom group-* and peer-* variants on the fly by passing your own selector to be "groupified" or "peerified" between square brackets:

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

为了更好地控制,你可以使用 & 字符来标记 .group.peer 在最终选择器中相对于你传入的选择器的位置:

¥For more control, you can use the & character to mark where .group or .peer should end up in the final selector relative to the selector you are passing in:

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

说实话,这些功能你一辈子可能只会用到三次,但它仍然很酷。希望我们可以以此为基础,使 grouppeer 将来能够更自动化地与第三方插件注册的变体协同工作。

¥Let's be serious you're probably going to use these features like three times in your entire life but it's still pretty cool. Hoping we can use this as a building block to make group and peer work more automatically with variants registered by third-party plugins in the future.


使用 matchVariant 的动态变体(Dynamic variants with matchVariant)

¥Dynamic variants with matchVariant

你可能已经在很多新功能中注意到了新的 variant-[...] 语法 - 这一切都源于新的 matchVariant 插件 API,这使得我们称之为 "动态变体" 的功能成为可能。

¥You've probably noticed this new variant-[...] syntax in a lot of these new features — this is all powered by a new matchVariant plugin API that makes it possible to create what we're calling "dynamic variants".

以下是为某个虚构的工具提示库创建 placement-* 变体的示例,该库使用 data-placement 属性来指示工具提示的当前位置:

¥Here's an example of creating a placement-* variant for some imaginary tooltip library that uses a data-placement attribute to tell you where the tooltip is currently positioned:

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 这样的变体,但也支持方括号中的任意部分。因此,如果这个虚构的工具提示库还有其他潜在值,而你觉得不需要为其创建内置值,你仍然可以这样做:

¥The variant defined above would give you variants like placement-t and placement-b, but would also support the arbitrary portion in square brackets, so if this imaginary tooltip library had other potential values that you didn't feel the need to create built-in values for, you could still do stuff like this:

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

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

¥When defining a custom variant with this API, it's often important that you have some control over which order the CSS is generated in to make sure each class has the right precedence with respect to other values that come from the same variant. To support this, there's a sort function you can provide when defining your variant:

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

使用变体修饰符支持嵌套组和多个同级元素(Nested group and multiple peer support using variant modifiers)

¥Nested group and multiple peer support using variant modifiers

有时,当你有多个 group 代码块嵌套在一起时,你可能会遇到问题,因为 Tailwind 没有真正的方法来消除它们之间的歧义。

¥Sometimes you can run into problems when you have multiple group chunks nested within each other because Tailwind has no real way to disambiguate between them.

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

¥To solve this, we're adding support for variant modifiers, which are a new dynamic chunk that you can add to the end of a variant (inspired by our optional opacity modifier syntax) that you can use to give each group/peer your own identifier.

它的样子如下:

¥Here's what it looks like:

<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 使其正常工作。

¥This lets you give each group a clear name that makes sense for that context on the fly, and Tailwind will generate the necessary CSS to make it work.

我非常高兴能有解决方案,因为多年来我一直在努力寻找一个好的方法来解决它,而这是我们想到的第一个真正提供我认为它应该具备的强大功能和灵活性的解决方案。

¥I'm really excited to have a solution out there for this because it's something I've been trying to land on a good approach for solving for several years, and this is the first thing we've come up with that really feels like it offers the power and flexibility I think it should.


容器查询(Container queries)

¥Container queries

我简直不敢相信,容器查询 终于来了,而且浏览器支持也已经非常接近正式版了 - 事实上,如果你正在构建 Electron 应用,现在就可以使用它们了。

¥I can barely believe it but container queries are finally real and the browser support is dangerously close to making these ready for production — in fact if you're building an Electron app you could use these today.

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

¥Today we're releasing @tailwindcss/container-queries which is a new first-party plugin that adds container query support to the framework, using a new @ syntax to differentiate them from normal media queries:

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

我们提供了一组与默认 max-width 比例匹配的开箱即用容器尺寸:

¥Out-of-the-box we include a set of container sizes that match our default max-width scale:

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

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

¥You can configure which values are available using the containers key in your tailwind.config.js file:

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

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

¥We also include support for arbitrary values, using the @[...] syntax:

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

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

¥...and named containers using the same variant modifier syntax we're now shipping for group-* and peer-* variants:

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

目前,我们先从基于 min-width 的简单容器查询开始,但我们计划随着时间的推移扩展范围,当我们感觉真正掌握了 API 之后,我们会将其全部纳入核心。

¥Right now we're starting with simple min-width based container queries, but we plan to expand the scope over time, and when it feels like we've really nailed the APIs we'll bring it all into core.

完整文档请查看 on GitHub 插件。

¥For complete documentation, check out the plugin on GitHub.


好了,这就是 Tailwind CSS v3.2!虽然进行了重大改进,但只是小版本变更,因此没有重大更改,你只需更新依赖即可更新项目:

¥So there you have it — Tailwind CSS v3.2! Major improvements but just a minor version change, so no breaking changes and you should be able to update your project by just updating your dependency:

npm install -D tailwindcss@latest

是的,我在后面听到了,仍然没有文本阴影,但是嘿,至少当复选框的父级是列表中的第三个子级时,你可以为复选框的兄弟级设置样式,而无需离开你的 HTML。优先考虑的人。

¥Yeah I hear you in the back, still no text shadows, but hey at least you can style the sibling of a checkbox when the checkbox's parent is the third child in a list without leaving your HTML. Priorities people.

TailwindCSS v4.1 中文网 - 粤ICP备13048890号