
没有什么比构建 一款重要的新产品 更能让你找到所有你希望在自己的工具中拥有的功能了,所以我们汲取了一些灵感,将其转化为 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.
-
动态视口单位: 在移动设备上真正可用的全高元素。
¥Dynamic viewport units: Full-height elements that actually work on mobile.
-
新的
:has()
变体: 基于子元素设置父元素的样式。¥New
:has()
variant: Style parent elements based on their children. -
使用
*
变体的子元素样式: 我们可能会后悔给你这个。¥Style children with the
*
variant: We'll probably regret giving you this one. -
新的
size-*
实用程序: 终于可以同时设置宽度和高度了。¥New
size-*
utilities: Set width and height at the same time, finally. -
使用
text-wrap
实用程序平衡标题: 无需再调整最大宽度或响应式换行符。¥Balanced headlines with
text-wrap
utilities: No more max-width tweaking or responsive line breaks. -
子网格支持: 你难以理解的网格功能,终于在 Tailwind CSS 中实现了。
¥Subgrid support: That grid feature you struggle to understand, finally in Tailwind CSS.
-
扩展了最小宽度、最大宽度和最小高度的比例: 现在
min-w-12
是一个真正的类。¥Extended min-width, max-width, and min-height scales: Now
min-w-12
is a real class. -
扩展了不透明度的比例: 适用于 60% 或 70% 都不完全正确的情况下。
¥Extended opacity scale: For those moments when neither 60% or 70% were quite right.
-
扩展
grid-rows-*
比例: 不妨让它与列比例匹配。¥Extended
grid-rows-*
scale: Might as well make it match the column scale. -
新的
forced-colors
变体: 轻松调整你的网站以支持强制颜色模式。¥New
forced-colors
variant: Easily fine-tune your site for forced colors mode. -
新的
forced-color-adjust
实用程序: 如果你希望进行更严格的颜色微调,可以使用 插件来实现。¥New
forced-color-adjust
utilities: For even more forced colors fine-tuning.
所有好东西都包含在该列表中,但请查看 发行说明 了解更多细节,它们可能不够精彩,不足以在这篇文章中提及。
¥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)
¥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:
在视口中上下滚动可隐藏/显示浏览器 UI
<div class="h-dvh"> <!-- ... --></div>
我们默认添加了以下新类:
¥We've added the following new classes by default:
类 | CSS |
---|---|
h-svh | height: 100svh |
h-lvh | height: 100lvh |
h-dvh | height: 100dvh |
min-h-svh | min-height: 100svh |
min-h-lvh | min-height: 100lvh |
min-h-dvh | min-height: 100dvh |
max-h-svh | max-height: 100svh |
max-h-lvh | max-height: 100lvh |
max-h-dvh | max-height: 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)
¥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)
¥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.
以下是我们正在进行的一种很酷的工作方式:
¥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)
¥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)
¥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 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>
例如,我们正在 下拉菜单 中改进,这样如果任何项目有图标,所有其他项目都会缩进以保持文本对齐:
¥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)
¥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)
¥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)
¥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)
¥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)
¥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 博客上的 “强制颜色解释:实用指南” - 这是迄今为止我发现的关于这个主题最有用的文章。
¥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.