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

日期

好吧,又到了那个时候了!我们很快就会从“我真的不知道我们还能在新的 Tailwind 版本中添加什么”转变为“哇,这实际上是大量的新东西——我们最好在事情完全失控之前标记一个版本”。

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-[...]` 变体接受你在 `@supports (...)` 中使用的任何内容,放在方括号之间,例如属性/值对,甚至使用 `and` 和 `or` 的表达式。

如果你只需要检查属性本身是否受支持,你甚至可以只指定属性名称,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 属性,请使用方括号使用任意值动态生成属性。

发票号 客户 金额
#100 Pendant Publishing $2,000.00
#101 Kruger Industrial Smoothing $545.00
#102 J. 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-* 修饰符来定位父元素和兄弟元素。

<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-* 变体根据 数据属性 有条件地设置样式。

由于默认情况下没有标准的 data-* 属性,我们只支持开箱即用的任意值,例如

<!-- 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 键下配置项目中使用的常见数据属性选择器的快捷方式。

// 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">
    <!-- 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-*` 变体,它允许您根据配置的断点应用最大宽度媒体查询。

<div class="max-lg:p-8">
  <!-- Will apply `p-8` until the `lg` breakpoint kicks in -->
</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",
    },
  },
};

如果您有一个复杂的配置,其中您已经定义了 `max-width` 断点,或者基于范围的媒体查询,或者任何除了字符串之外的东西,这些功能将不可用。我们将来可能会解决这个问题,但这会产生很多关于如何排序 CSS 的问题,我们还没有答案。

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


动态 group-* 和 peer-* 变体

现在可以通过将您自己的选择器传递到方括号之间来动态创建自定义 `group-*` 和 `peer-*` 变体,以实现“分组”或“同行化”。

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

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

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

说真的,你可能一生中只用过这些功能三次,但这仍然很酷。希望我们能以此为基础,在未来让 `group` 和 `peer` 与第三方插件注册的变体更自动地协同工作。


使用 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-t` 和 `placement-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 和支持多个 peer

当你在彼此之间嵌套多个 `group` 块时,有时会遇到问题,因为 Tailwind 无法真正区分它们。

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

它看起来像这样

<div class="group/sidebar ...">
  <!-- ... -->
  <div class="group/navitem ...">
    <a
      href="#"
      class="opacity-50 group-hover/sidebar:opacity-75 group-hover/navitem:bg-black/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',
        // etc...
      },
    },
  },
}

我们还支持使用 `@[...]` 语法来使用任意值。

<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>

目前,我们从简单的基于 `min-width` 的容器查询开始,但我们计划随着时间的推移扩展其范围,并且当我们感觉已经真正确定了 API 时,我们将将其全部引入核心。

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


所以这就是 Tailwind CSS v3.2!重大改进,但只是一个小版本更改,因此没有重大更改,您只需更新依赖项即可更新项目。

npm install -D tailwindcss@latest

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