
没有什么比开发一个重大新产品更能让你发现自己工具中缺少的功能了,所以我们利用了一些这些灵感,并将其转化为这个——Tailwind CSS v3.4。
🌐 There's nothing like building a major new product for finding all the features you wish you had in your own tools, so we capitalized on some of that inspiration and turned it into this — Tailwind CSS v3.4.
一如既往,改进范围广泛,从多年来让你感到不满的方面,到支持你从未听说过、甚至可能在工作中用不到的 CSS 功能。
🌐 As always the improvements range from things you've been angry about for years, to supporting CSS features you've never even heard of and probably can't even use at work.
- 动态视口单位: 在移动设备上也能正常工作的全高元素。
- 新的
:has()变体: 根据子元素为父元素设置样式。 - 使用
*变体来为子级们造型: 我们可能会后悔给你这个。 - 新的
size-*工具: 最终可以同时设置宽度和高度。 - 使用
text-wrap工具实现的平衡标题: 不再需要调整最大宽度或响应式换行。 - 子网格支持: 你一直难以理解的网格功能,现在终于在 Tailwind CSS 中实现了。
- 扩展的最小宽度、最大宽度和最小高度刻度: 现在
min-w-12是一个真实的类。 - 扩展不透明度刻度: 用于那些60%或70%都不太合适的时刻。
- 扩展
grid-rows-*量表: 不妨让它与列尺度一致。 - 新的
forced-colors变体: 轻松为强制颜色模式微调你的网站。 - 新的
forced-color-adjust工具: 用于更加精细地调整强制颜色。
所有的好东西都在那个列表里,但可以查看一下更新日志,了解一些没有足够吸引力而没能出现在这篇文章里的细节。
🌐 All the good stuff is in that list, but check out the release notes for a couple more details that weren't exciting enough to earn a spot in this post.
通过从 npm 安装最新版本的 tailwindcss 来升级你的项目:
🌐 Upgrade your projects by installing the latest version of tailwindcss from npm:
npm install tailwindcss@latest或者在浏览器中直接试用 Tailwind Play 的所有新功能。
🌐 Or try out all of the new features on Tailwind Play, right in your browser.
动态视口单位(Dynamic viewport units)
当浏览器加入 vh 单位时,我们都非常兴奋——终于可以构建全高的应用布局,不用再在 17 层 DOM 中穿透 height: 100% 了!但移动设备及其该死的消失菜单栏破坏了所有乐趣,有效地让 vh 单位只是对本可能如此美好的未来的残酷提醒。
🌐 When the vh unit was added to browsers we all got so excited — finally a way to build full-height application layouts and stuff without drilling height: 100% through 17 layers of DOM! But mobile devices and their damn disappearing menu bars spoiled all the fun, effectively making the vh unit just a cruel reminder of a future that could've been so great.
好吧,我们现在有了新的未来——dvh、lvh 和 svh 旨在适应那些正在消失的浏览器界面元素,Tailwind CSS v3.4 开箱即支持它们:
🌐 Well we've got a new future now — dvh, lvh, and svh are designed to accommodate that disappearing browser chrome and Tailwind CSS v3.4 supports them out of the box:
在视口中上下滚动以隐藏/显示浏览器界面
<div class="h-dvh"> <!-- ... --></div>我们默认添加了以下新类:
🌐 We've added the following new classes by default:
| CSS | |
|---|---|
h-svh 级 | 高度:100svh |
高-高-高 | 高度:100LVH |
H-DVH | 高度:100DVH |
明-H-斯维赫 | 最小身高:100SVH |
明-H-LVH | 最低身高:100LVH |
明-H-DVH | 最低高度:100DVH |
马克斯-H-SVH | 最大高度:100svh |
最大-H-LVH | 最大高度:100LVH |
马克斯-H-DVH | 最大高度:100DVH |
如果你需要其他值,你也可以随意使用像 min-h-[75dvh] 这样的任意值。
🌐 If you need other values, you can always use arbitrary values too like min-h-[75dvh].
现在这些在浏览器上的支持相当不错,所以除非你需要支持 Safari 14,否则可以立即开始使用它们。
🌐 Browser support is pretty great for these nowadays, so unless you need to support Safari 14 you can start using these right away.
新的 :has() 变种(New :has() variant)
:has() 伪类 是自 flexbox 以来 CSS 中添加的最强大的功能。你可以第一次根据元素的 子元素 来进行样式设置,而不仅仅是根据其父元素。它甚至可以根据后续的兄弟元素来设置样式。
🌐 The :has() pseudo-class is the most powerful thing that's been added to CSS since flexbox. For the first time ever, you can style an element based on its children, not just based on its parents. It even makes it possible to style based on subsequent siblings.
以下是示例,如果父级组件中的单选按钮被选中,则父级组件会显示一个彩色环:
🌐 Here's an example where the parent gets a colored ring if the radio button inside of it is checked:
<label class="has-[:checked]:bg-indigo-50 has-[:checked]:text-indigo-900 has-[:checked]:ring-indigo-500 ..."> <svg fill="currentColor"> <!-- ... --> </svg> Google Pay <input type="radio" class="accent-indigo-500 ..." /></label>在过去几个月我们一直在开发这个新的 UI 工具包时,我感觉每周都能为 :has() 找到一个新的用例,它已经替代了我们代码中大量的 JavaScript。
🌐 I feel like I've found a new use-case for :has() every week while working on this new UI kit we've been building for the last few months, and it's replaced a crazy amount of JavaScript in our code.
例如,我们的文本输入在设计上相当复杂,需要一个小的封装元素来构建。如果没有 :has(),我们无法根据输入的 :disabled 状态来为封装元素设置样式,但现在我们可以做到:
🌐 For example, our text inputs are pretty complicated design-wise and require a little wrapper element to build. Without :has(), we had no way of styling the wrapper based on things like the :disabled state of the input, but now we can:
export function Input({ ... }) { return ( <span className="has-[:disabled]:opacity-50 ..."> <input ... /> </span> )}这个技术相当前沿,但截至今天,它已经在所有主流浏览器的最新版本中得到支持。等几周,让 Firefox 用户更新到今天的版本,我们就可以尽情使用它了。
🌐 This one is pretty bleeding edge but as of literally today it's now supported in the latest version of all major browsers. Give it a few weeks for any Firefox users to install today's update and we should be able to go wild with it.
使用 * 变体为子元素设置样式(Style children with the * variant)
这是人们一直以来梦寐以求的 — 一种使用工具类来为父级组件设置子级样式的方法。
🌐 Here's one people have wanted for literally ever — a way to style children from the parent using utility classes.
我们新增了一个针对直接子元素的 * 变体,让你可以这样操作:
🌐 We've added a new * variant that targets direct children, letting you do stuff like this:
Categories
<div> <h2>Categories:<h2> <ul class="*:rounded-full *:border *:border-sky-100 *:bg-sky-50 *:px-2 *:py-0.5 dark:text-sky-300 dark:*:border-sky-500/15 dark:*:bg-sky-500/10 ..."> <li>Sales</li> <li>Marketing</li> <li>SEO</li> <!-- ... --> </ul></div>一般来说,我建议直接为子元素设置样式,但当你无法控制这些元素,或者需要根据元素所处的上下文进行条件调整时,这种方法会很有用。
🌐 Generally I'd recommend just styling the children directly, but this can be useful when you don't control those elements or need to make a conditional tweak because of the context the element is used in.
它也可以与其他变体组合使用,例如 hover:*:underline 会在子元素被悬停时应用样式。
🌐 It can be composed with other variants too, for instance hover:*:underline will style any child when the child is hovered.
这里有一种很酷的方法,我们用它在正在开发的新 UI 工具包中有条件地为不同的子元素添加布局样式:
🌐 Here's a cool way we're using that to conditionally add layout styles to different child elements in the new UI kit we're working on:
function Field({ children }) { return ( <div className="data-[slot=description]:*:mt-4 ..."> {children} </div> )}function Description({ children }) { return ( <p data-slot="description" ...>{children}</p> )}function Example() { return ( <Field> <Label>First name</Label> <Input /> <Description>Please tell me you know your own name.</Description> </Field> )}看到那个疯狂的 data-[slot=description]:*:mt-4 类了吗?它首先会选择所有直接子元素(那就是 *: 部分),然后使用 data-[slot=description] 将它们过滤,只保留带有 data-slot="description" 属性的项目。
🌐 See that crazy data-[slot=description]:*:mt-4 class? It first targets all direct children (that's the *: part), then filters them down to just items with a data-slot="description" attribute using data-[slot=description].
这样可以轻松地只针对特定的子元素,而无需一路下降到原始的任意变体。
🌐 This makes it easy to target only specific children, without having to drop all the way down to a raw arbitrary variant.
期待看到大家做的那些让我后悔添加这个功能的糟糕事情。
🌐 Looking forward to seeing all the horrible stuff everyone does to make me regret adding this feature.
新的 size-* 工具(New size-* utilities)
你每次需要调整头像大小时都厌倦了输入 h-5 w-5,你我都清楚这一点。
🌐 You're sick of typing h-5 w-5 every time you need to size an avatar, you know it and I know it.
在 Tailwind CSS v3.4 中,我们终于添加了一个新的 size-* 工具类,可以同时设置宽度和高度:
🌐 In Tailwind CSS v3.4 we've finally added a new size-* utility that sets width and height at the same time:
<div> <img class="h-10 w-10" ...> <img class="h-12 w-12" ...> <img class="h-14 w-14" ...> <img class="size-10" ...> <img class="size-12" ...> <img class="size-14" ...></div>我们一直想加入这个功能,但总是纠结于确切的名称——与 w-* 或 h-* 相比,size-* 打起来感觉太麻烦,而 s-* 又显得太神秘了。
🌐 We've wanted to add this forever but have always been hung up on the exact name — size-* felt like so much to type compared to w-* or h-* and s-* felt way too cryptic.
使用了几周之后,我可以明确地说,即使名字更长,它也比单独的宽度和高度工具要好得多。非常方便,尤其是当你将它与不同的变体结合使用或使用复杂的任意值时。
🌐 After using it for a few weeks though I can say decisively that even with the longer name, it's way better than separate width and height utilities. Super convenient, especially if you're combining it with variants or using a complex arbitrary value.
使用 text-wrap 工具的平衡标题(Balanced headlines with text-wrap utilities)
你花了多少时间去摆弄 max-width 或插入响应式换行,希望让首页上的小标题能漂亮地换行?现在你可以一分时间都不用花,因为浏览器可以用 text-wrap: balance 为你处理这些问题:
🌐 How much time have you spent fiddling with max-width or inserting responsive line breaks to try and make those little section headings wrap nicely on your landing pages? Well now you can spend zero time on it, because the browser can do it for you with text-wrap: balance:
Beloved Manhattan soup stand closes
New Yorkers are facing the winter chill with less warmth this year as the city's most revered soup stand unexpectedly shutters, following a series of events that have left the community puzzled.
<article> <h3 class="text-balance ...">Beloved Manhattan soup stand closes<h3> <p>New Yorkers are facing the winter chill...</p></article>我们还添加了 text-pretty,它尝试使用 text-wrap: pretty 避免段落末尾出现孤立的单词:
🌐 We've also added text-pretty which tries to avoid orphaned words at the end of paragraphs using text-wrap: pretty:
Beloved Manhattan soup stand closes
New Yorkers are facing the winter chill with less warmth this year as the city's most revered soup stand unexpectedly shutters, following a series of events that have left the community puzzled.
<article class="text-pretty ..."> <h3>Beloved Manhattan soup stand closes<h3> <p>New Yorkers are facing the winter chill...</p></article>这些功能的优点在于,即使有人使用旧版浏览器访问你的网站,他们也会回退到常规的换行行为,因此现在开始使用这些功能是完全安全的。
🌐 The nice thing about these features is that even if someone visits your site with an older browser, they'll just fallback to the regular wrapping behavior so it's totally safe to start using these today.
子网格支持(Subgrid support)
子网格 (Subgrid) 是一项较新的 CSS 功能,它允许元素从其父元素继承网格的列或行,从而可以将其子元素放置在父网格中。
🌐 Subgrid is a fairly recent CSS feature that lets an element sort of inherit the grid columns or rows from its parent, make it possible to place its child elements in the parent grid.
<div class="grid grid-cols-4 gap-4"> <!-- ... --> <div class="col-span-3 grid grid-cols-subgrid gap-4"> <div class="col-start-2">06</div> </div> <!-- ... --></div>我们在正在开发的新 UI 工具包中使用了子网格,例如在下拉菜单中,这样如果任何项目有图标,所有其他项目都会缩进,以保持文本对齐:
🌐 We're using subgrid in the new UI kit we're working on for example in dropdown menus, so that if any item has an icon, all of the other items are indented to keep the text aligned:
<div role="menu" class="grid grid-cols-[auto_1fr]"> <a href="#" class="col-span-2 grid-cols-subgrid"> <svg class="mr-2">...</svg> <span class="col-start-2">Account</span> </a> <a href="#" class="col-span-2 grid-cols-subgrid"> <svg class="mr-2">...</svg> <span class="col-start-2">Settings</span> </a> <a href="#" class="col-span-2 grid-cols-subgrid"> <span class="col-start-2">Sign out</span> </a></div>当所有项目都没有图标时,第一列会缩小到 0px,并且文本会完全左对齐。
🌐 When none of the items have an icon, the first column shrinks to 0px and the text is aligned all the way to left.
查看 MDN 关于子网格的文档 以获取完整的入门指南 —— 这个功能一开始可能有点难以理解,但一旦掌握,它会彻底改变你的使用体验。
🌐 Check out the MDN documentation on subgrid for a full primer — it's a bit of a tricky feature to wrap your head around at first, but once it clicks it's a game-changer.
扩展的最小宽度最大宽度和最小高度缩放比例(Extended min-width, max-width, and min-height scales)
我们终于将 min-width、max-width 和 min-height 量表扩展到了完整的间距量表,因此像 min-w-12 这样的类现在真的可以使用了:
🌐 We've finally extended the min-width, max-width, and min-height scales to include the full spacing scale, so classes like min-w-12 are actually a real thing now:
<div class="min-w-12"> <!-- ... --></div>我们应该在 v3.0 中就这么做,但一直没时间 - 很抱歉,不客气。
🌐 We should've just done this for v3.0 but never really got around to it — I'm sorry and you're welcome.
扩展的透明度缩放比例(Extended opacity scale)
我们还扩展了透明度比例,使其包含开箱即用的 5 个步骤:
🌐 We've also extended the opacity scale to include every step of 5 out of the box:
<div class="opacity-35"> <!-- ... --></div>希望这意味着你的标记中少了一些随意的数值。我接下来要处理你那2.5%了。
🌐 Hopefully that means a few less arbitrary values in your markup. I'm coming for you next 2.5%.
扩展 grid-rows-* 刻度(Extended grid-rows-* scale)
我们还将内置的网格行数从 6 行增加到 12 行,原因如下:
🌐 We've also bumped the baked-in number of grid rows from 6 to 12 because why not:
<div class="grid grid-rows-9"> <!-- ... --></div>也许我们会更疯狂,在下一个版本中将其增加到 16 个字节。
🌐 Maybe we'll get even crazier and bump it to 16 in the next release.
新的 forced-colors 变种(New forced-colors variant)
听说过强制配色模式吗?你的网站在这个模式下可能看起来很糟糕。
🌐 Ever heard of forced colors mode? Your site probably looks pretty bad in it.
现在你至少不能责怪我们了,因为 Tailwind CSS v3.4 包含一个用于强制颜色模式调整样式的 forced-colors 变体:
🌐 Well now you can't blame us at least, because Tailwind CSS v3.4 includes a forced-colors variant for adjusting styles for forced colors mode:
<form> <input type="checkbox" class="appearance-none forced-colors:appearance-auto ..." /></form>它对于微调完全自定义的控件非常有用,尤其是结合任意值和对 CSS 系统颜色 的基本了解时。
🌐 It's really useful for fine-tuning totally custom controls, especially combined with arbitrary values and a working knowledge of CSS system colors.
新的 forced-color-adjust 工具(New forced-color-adjust utilities)
我们还新增了 forced-color-adjust-auto 和 forces-color-adjust-none 工具,用于控制强制颜色模式如何影响你的设计:
🌐 We've also added new forced-color-adjust-auto and forces-color-adjust-none utilities to control how forced colors mode affects your design:
<fieldset> <legend>Choose a color</legend> <div class="forced-color-adjust-none ..."> <label> <input class="sr-only" type="radio" name="color-choice" value="white" /> <span class="sr-only">White</span> <span class="size-6 rounded-full bg-white"></span> </label> <label> <input class="sr-only" type="radio" name="color-choice" value="gray" /> <span class="sr-only">Gray</span> <span class="size-6 rounded-full bg-gray-300"></span> </label> <!-- ... --> </div></fieldset>这些应该谨慎使用,但当无论如何都必须以特定颜色渲染某些内容时,它们会非常有用,例如,选择某人在网上商店购买的商品的颜色。
🌐 These should be used pretty sparingly, but they can be useful when it's critical that something is rendered in a specific color no matter what, like choosing the color of something someone is buying in an online store.
想了解更多关于这些强制颜色的内容,我推荐阅读 Polypane 博客上的《强制颜色解析:实用指南》(https://polypane.app/blog/forced-colors-explained-a-practical-guide/)——这是我在这个话题上找到的最有用的文章。
🌐 To learn more about all this forced colors stuff, I recommend reading "Forced colors explained: A practical guide" on the Polypane blog — by far the most useful post I've found on this topic.
如果你一直在密切关注,你可能会对 Oxide 感到好奇,这是我们在今年夏天的 Tailwind Connect 上预览的引擎改进。
🌐 If you've been paying close attention, you might be wondering about Oxide, the engine improvements we previewed at Tailwind Connect this summer.
我们最初计划在 v3.4 中推出这些改进,但还有一些问题需要解决,同时其他许多改进也在不断积累,所以我们觉得把所有改进一次性发布比延迟推出更合理。Oxide 的相关内容仍在开发中,将成为明年 Tailwind CSS 新版本的主要改进亮点。
🌐 We'd originally slated those improvements for v3.4, but we have a few things still to iron out and so many of these other improvements had been piling up that we felt it made sense to get it all out the door instead of holding it back. The Oxide stuff is still coming, and will be the headlining improvement for the next Tailwind CSS release in the new year.
同时,请使用 npm 更新到最新版本,深入了解 Tailwind CSS v3.4:
🌐 In the mean time, dig in to Tailwind CSS v3.4 by updating to the latest version with npm:
$ npm install tailwindcss@latest有了 :has() 和新的 * 版本,你的 HTML 将比以往任何时候都更加难以控制。
🌐 With :has() and the new * variant, your HTML is about to get more out of control than ever.