Tailwind CSS 使用预处理器
使用预处理器
一个使用 Tailwind 与常见的 CSS 预处理器,如 Sass,Less 和 Stylus 的指南
由于 Tailwind 是一个 PostCSS 插件,没有什么可以阻止您使用 Sass,Less,Stylus 或其他预处理器,就像您可以使用其他 PostCSS 插件,如 Autoprefixer。
重要的是要注意,您不需要在Tailwind中使用预处理器—您通常在 Tailwind 项目中写很少的 CSS,所以使用预处理器并不像在一个您写了很多自定义 CSS 的项目中那样有利。
本指南只是作为一个参考,供那些需要或想将 Tailwind 与预处理器整合的人使用。
使用PostCSS作为您的预处理器
如果您在一个全新的项目中使用 Tailwind,并且不需要将它与任何现有的 Sass/Less/Stylus 样式表集成,您应该高度考虑依靠其他 PostCSS 插件来添加您所使用的预处理器功能,而不是使用一个单独的预处理器。
这有几个好处。
- 您的构建速度会更快。因为您的 CSS 不需要被多个工具解析和处理,所以只使用 PostCSS,您的 CSS 会编译得更快。
- 因为 Tailwind 添加了一些新的非标准关键字到 CSS 中(如
@tailwind
, @apply
, theme()
等),您经常不得不用烦人的,不直观的方式来写您的 CSS,以得到一个预处理器给您预期的输出。而使用 PostCSS 则可以避免这种情况。
关于可用的 PostCSS 插件,请参见 PostCSS GitHub repository,但这里有几个重要的插件,我们在自己的项目中使用,并且可以推荐。
构建时导入
预处理器提供的最有用的功能之一是能够将您的 CSS 组织成多个文件,并在构建时通过提前处理 @import
语句而不是在浏览器中结合它们。
用于处理 PostCSS 的规范插件是 postcss-import。
要使用它,请通过 npm 安装该插件:
npm install postcss-import
然后把它作为 PostCS 配置中的第一个插件:
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
]
}
关于 postcss-import
,需要注意的一个重要问题是,它严格遵守 CSS 规范,不允许在任何地方使用 @import
语句,除非在文件的顶部。
无法工作,@import 语句必须放在第一位。
/* components.css */
.btn {
@apply px-4 py-2 rounded font-semibold bg-gray-200 text-black;
}
/* Will not work */
@import "./components/card";
解决这个问题最简单的方法就是永远不要在同一个文件中混合常规 CSS 和导入。取而代之的是,为您的导入文件创建一个主入口文件,并将所有实际的 CSS 保存在单独的文件中。
为导入和实际的 CSS 使用单独的文件。
/* components.css */
@import "./components/buttons.css";
@import "./components/card.css";
/* components/buttons.css */
.btn {
@apply px-4 py-2 rounded font-semibold bg-gray-200 text-black;
}
/* components/card.css */
.card {
@apply p-4 bg-white shadow rounded;
}
您最可能遇到这种情况的地方是在您的主 CSS 文件中,其中包括您的 @tailwind
声明。
无法工作,@import 语句必须在前面。
@tailwind base;
@import "./custom-base-styles.css";
@tailwind components;
@import "./custom-components.css";
@tailwind utilities;
@import "./custom-utilities.css";
您可以通过为每个 @tailwind
声明创建单独的文件,然后在主样式表中导入这些文件来解决此问题。为了简化这一点,我们为每个开箱即用的 @tailwind
声明提供了单独的文件,您可以直接从 node_modules
导入这些文件。
postcss-import
插件非常智能,可以自动在 node_modules
文件夹中查找文件,因此您无需提供整个路径——例如“tailwindcss/base”
就足够了。
导入我们提供的 CSS 文件
您可以通过把您的 @tailwind
声明放在他们自己的文件中来解决这个问题。为了方便,我们为每个 @tailwind
声明提供了单独的文件,您可以直接从 node_modules
导入。
@import "tailwindcss/base";
@import "./custom-base-styles.css";
@import "tailwindcss/components";
@import "./custom-components.css";
@import "tailwindcss/utilities";
@import "./custom-utilities.css";
嵌套
要添加对嵌套声明的支持,我们推荐我们捆绑的 tailwindcss/nesting
插件,这是一个 PostCSS 插件,它包装了 postcss-nested 或 postcss-nesting 并充当兼容层,以确保您选择的嵌套插件正确理解 Tailwind 的自定义语法,例如@apply
和 @screen
。
它直接包含在 tailwindcss
包本身中,因此要使用它,您只需将其添加到 PostCSS 配置中,位于 Tailwind 之前的某个位置:
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss/nesting'),
require('tailwindcss'),
require('autoprefixer'),
]
}
默认情况下,它在后台使用 postcss-nested 插件,该插件使用类似 Sass 的语法,并且是 Tailwind CSS 插件 API 中支持嵌套支持的插件。
如果你更喜欢使用 postcss-nesting(它基于工作中的 CSS 嵌套规范),首先安装插件:
npm install postcss-nesting
然后将插件本身作为参数传递给 PostCSS 配置中的 tailwindcss/nesting
:
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss/nesting')(require('postcss-nesting')),
require('tailwindcss'),
require('autoprefixer'),
]
}
如果出于某种原因您需要使用一个非常特定版本的 postcss-nested
并且想要覆盖我们与 tailwindcss/nesting
本身捆绑的版本,这也会很有帮助。
请注意,如果您在项目中使用 postcss-preset-env,则应确保禁用嵌套并让 tailwindcss/nesting
为您处理它:
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss/nesting')(require('postcss-nesting')),
require('tailwindcss'),
require('postcss-preset-env')({
features: { 'nesting-rules': false }
}),
]
}
变量
如今,CSS 变量(官方称为自定义属性)具有非常好的浏览器支持,因此您根本不需要预处理器来使用变量。
:root {
--theme-color: #52b3d0;
}
/* ... */
.btn {
background-color: var(--theme-color);
/* ... */
}
我们在 Tailwind 本身中广泛使用 CSS 变量,因此如果您可以使用 Tailwind,则可以使用原生 CSS 变量。
您可能还会发现,您过去使用变量的大部分内容都可以替换为 Tailwind 的 theme()
函数,该函数使您可以直接在 CSS 中访问 tailwind.config.js
文件中的所有设计标记:
.btn {
background-color: theme('colors.blue.500');
padding: theme('spacing.2') theme('spacing.4');
/* ... */
}
供应商前缀
要在 CSS 中自动管理供应商前缀,您应该使用 Autoprefixer。
要使用它,请通过 npm 安装它:您可以使用 postcss-preset-env 插件为您的项目添加对即将到来的 CSS 特性的支持。
npm install autoprefixer
然后将它添加到 PostCSS 配置中插件列表的最后:
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
]
}
使用 Sass、Less 或 Stylus
要使用 Tailwind 的预处理工具,如 Sass,Less,或 Stylus,您需要添加一个额外的构建步骤到您的项目中,让您通过 PostCSS 运行您的预处理 CSS。如果您在项目中使用 Autoprefixer,您已经有了类似这样的设置。
确切的说明将取决于您使用的构建工具,所以请参阅我们的安装文档来了解更多关于将 Tailwind 整合到您现有的构建过程中。
关于使用 Tailwind 与预处理器的最重要的事情是,预处理器,如Sass,Less和Stylus单独运行,在Tailwind之前。这意味着您不能将 Tailwind 的theme()
函数的输出输入到 Sass 颜色函数中,例如,因为 theme()
函数在您的 Sass 被编译成 CSS 并输入 PostCSS 之前不会被实际评估。
不行,Sass先被处理
.alert {
background-color: darken(theme('colors.red.500'), 10%);
}
为了获得最有凝聚力的开发体验,建议您专门使用 PostCSS
。
除此之外,每个预处理器在与 Tailwind 一起使用时,都有自己的一两个怪癖,下面用变通方法概述一下。
Sass
当使用Sass的 Tailwind 时,使用 !important
与 @apply
需要您使用插值来正确编译。
.alert {
@apply bg-red-500 !important;
}
使用插值作为解决方法
.alert {
@apply bg-red-500 #{!important};
}
Less
当使用 Tailwind 和 Less 一起使用时,您不能嵌套 Tailwind 的 @screen
指令。
无法工作,Less 无法检查到这是一个媒体查询
.card {
@apply rounded-none;
@screen sm {
@apply rounded-lg;
}
}
取而代之的是,使用常规的媒体查询和 theme()
函数来引用您的屏幕尺寸,或者干脆不要嵌套您的@screen
指令。
使用常规的媒体查询和 theme()
.card {
@apply rounded-none;
@media (min-width: theme('screens.sm')) {
@apply rounded-lg;
}
}
在顶层使用 @screen 指令
.card {
@apply rounded-none;
}
@screen sm {
.card {
@apply rounded-lg;
}
}
Stylus
当使用 Tailwind 和 Stylus 时,您不能使用 Tailwind的 @apply
功能,如果不把整个 CSS 规则包裹在 @css
中,那么 Stylus 就会把它当作字面 CSS。
无法工作,Stylus 与 @apply 冲突
.card {
@apply rounded-lg bg-white p-4
}
使用 @css 来避免被 Stylus 处理
@css {
.card {
@apply rounded-lg bg-white p-4
}
}
然而,这有一个重要的代价,那就是您不能在 @css
块中使用任何 Stylus 功能。
另一个选择是使用 theme()
函数代替 @apply
,并以长格式写出实际的 CSS 属性。
使用 theme() 代替 @apply
.card {
border-radius: theme('borderRadius.lg');
background-color: theme('colors.white');
padding: theme('spacing.4');
}
除此之外,Stylus 不支持嵌套 @screen
指令(就像 Less 一样)。
无法工作,Stylus 检查不出这是一个媒体查询
.card {
border-radius: 0;
@screen sm {
border-radius: theme('borderRadius.lg');
}
}
取而代之的是,使用常规的媒体查询和 theme()
函数来引用您的屏幕尺寸,或者干脆不要嵌套您的 @screen
指令。
使用常规的媒体查询和 theme()
.card {
border-radius: 0;
@media (min-width: theme('screens.sm')) {
border-radius: theme('borderRadius.lg');
}
}
在顶层使用 @screen 指令
.card {
border-radius: 0;
}
@screen sm {
.card {
border-radius: theme('borderRadius.lg');
}
}
更多建议: