Tailwind CSS 入门

Tailwind这个CSS的框架不算是什么新东西了,不过也一直没有去研究过,最近有需要就看了下,看起来还是比较简单的。

这东西看起来就是个新的DSL之类的,提供了许多常用且内置的css样式,封装成语法,然后提供一个PostCSS插件,把封装好的语法又处理回普通的css。

我们需要做的事就是安装Tailwind的PostCSS插件,然后使用他封装好的DSL即可。

什么是PostCSS

在 Web 应用开发中,CSS 代码的编写是重要的一部分。CSS 规范从最初的 CSS1 到现在的 CSS3,再到 CSS 规范的下一步版本,规范本身一直在不断的发展演化之中。这给开发人员带来了效率上的提高。不过与其他 Web 领域的规范相似的处境是,CSS 规范在浏览器兼容性方面一直存在各种各样的问题。不同浏览器在 CSS 规范的实现方面的进度也存在很大差异。另外,CSS 规范本身的发展速度与社区的期待还有一定的差距。这也是为什么 SASS 和 LESS 等 CSS 预处理语言可以流行的重要原因。SASS 和 LESS 等提供了很多更实用的功能,也体现了开发人员对 CSS 语言的需求。本文中要介绍的 PostCSS 是目前流行的一个对 CSS 进行处理的工具。PostCSS 依托其强大的插件体系为 CSS 处理增加了无穷的可能性。

PostCSS 本身是一个功能比较单一的工具。它提供了一种方式用 JavaScript 代码来处理 CSS。它负责把 CSS 代码解析成抽象语法树结构(Abstract Syntax Tree,AST),再交由插件来进行处理。插件基于 CSS 代码的 AST 所能进行的操作是多种多样的,比如可以支持变量和混入(mixin),增加浏览器相关的声明前缀,或是把使用将来的 CSS 规范的样式规则转译(transpile)成当前的 CSS 规范支持的格式。从这个角度来说,PostCSS 的强大之处在于其不断发展的插件体系。目前 PostCSS 已经有 200 多个功能各异的插件。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

PostCSS 从其诞生之时就带来了社区对其类别划分的争议。这主要是由于其名称中的 post,很容易让人联想到 PostCSS 是用来做 CSS 后处理(post-processor)的,从而与已有的 CSS 预处理(pre-processor)语言,如 SASS 和 LESS 等进行类比

实际上,PostCSS 的主要功能只有两个:第一个就是前面提到的把 CSS 解析成 JavaScript 可以操作的 AST,第二个就是调用插件来处理 AST 并得到结果。因此,不能简单的把 PostCSS 归类成 CSS 预处理或后处理工具。PostCSS 所能执行的任务非常多,同时涵盖了传统意义上的预处理和后处理。PostCSS 是一个全新的工具,给前端开发人员带来了不一样的处理 CSS 的方式。

如何使用PostCSS

PostCSS 一般不单独使用,而是与已有的构建工具进行集成。PostCSS 与主流的构建工具,如 Webpack、Grunt 和 Gulp 都可以进行集成。完成集成之后,选择满足功能需求的 PostCSS 插件并进行配置。

Webpack 中使用 postcss-loader 来执行插件处理。在清单 1 中,postcss-loader 用来对.css 文件进行处理,并添加在 style-loader 和 css-loader 之后。通过一个额外的 postcss 方法来返回所需要使用的 PostCSS 插件。require(‘autoprefixer’) 的作用是加载 Autoprefixer 插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var path = require('path');

module.exports = {
context: path.join(__dirname, 'app'),
entry: './app',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
}
]
},
postcss: function () {
return [require('autoprefixer')];
}
}

如何启用并设置Tailwind PostCSS

通过 npm 安装 Tailwind

对于大多数项目(并利用 Tailwind 的自定义功能),您需要通过 npm 安装 Tailwind 及其依赖项。

1
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

由于 Tailwind 不会自动添加浏览器引擎前缀到生成的 CSS 中,我们建议您安装 autoprefixer 去处理这个问题,就像上面的代码片段所展示的那样。

作为 PostCSS 插件来添加 Tailwind

将 tailwindcss 和 autoprefixer 添加到您的 PostCSS 配置中。 多数情况下,这是项目根目录下的 postcss.config.js 文件,但也可能是 .postcssrc 文件或是由 package.json 文件中的 postcss 键所指定。

1
2
3
4
5
6
7
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}

创建您的配置文件

如果您想要自定义您的 Tailwind 安装,可以使用 Tailwind CLI 工具生成一份配置文件,这个命令行工具已包含在了 tailwindcss 这个 npm 包里了。

1
npx tailwindcss init

这将会在您的工程根目录创建一个最小的 tailwind.config.js 文件。

1
2
3
4
5
6
7
8
9
10
// tailwind.config.js
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {},
plugins: [],
}

包含 Tailwind 到您的 CSS 中

如果您尚未创建一个 CSS 文件,请使用 @tailwind 指令注入 Tailwind 的基础 (base),组件 (components) 和功能 (utilities) 样式:

1
2
3
4
/* ./your-css-folder/styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

Tailwind 将在构建时将这些指令替换为基于您配置的设计系统生成的所有样式。

如果您使用的是 postcss-import(或背后使用它的工具,例如 Webpacker for Rails),请使用我们的导入而不是 @tailwind 指令来避免在导入任何其他文件时出现问题:

1
2
3
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

如果您使用的是像 React 或 Vue 这样的 JavaScript 框架,支持直接将 CSS 文件导入到 JS 中,那么您也可以完全跳过创建 CSS 文件,而直接导入 tailwindcss / tailwind.css,而后者已经安装了所有这些指令:

1
2
// app.js
import "tailwindcss/tailwind.css"

生成您的 CSS

实际构建项目的方式将取决于您使用的工具。 您的框架可能包含诸如 npm run dev 之类的命令,以启动在后台编译 CSS 的开发服务器,您可能自己在运行 webpack,或者您正在使用 postcss-cli 并运行诸如 postcss styles.css -o compiled.css 之类的命令。

使用其他预处理器优化

由于 Tailwind 是一个 PostCSS 插件,没有什么可以阻止您使用 Sass,Less,Stylus 或其他预处理器,就像您可以使用其他 PostCSS 插件,如 Autoprefixer。

重要的是要注意,您不需要在Tailwind中使用预处理器—您通常在 Tailwind 项目中写很少的 CSS,所以使用预处理器并不像在一个您写了很多自定义 CSS 的项目中那样有利。

构建时导入

预处理器提供的最有用的功能之一是能够将您的 CSS 组织成多个文件,并在构建时通过提前处理 @import 语句而不是在浏览器中结合它们。

用于处理 PostCSS 的规范插件是 postcss-import。

要使用它,请通过 npm 安装该插件:

1
npm install postcss-import

然后把它作为 PostCS 配置中的第一个插件:

1
2
3
4
5
6
7
8
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
]
}

关于 postcss-import,需要注意的一个重要问题是,它严格遵守 CSS 规范,不允许在任何地方使用 @import 语句,除非在文件的顶部。

内置Nesting插件以支持@apply等语法

为了增加对嵌套声明的支持,我们推荐我们捆绑的 tailwindcss/nesting 插件,这是一个 PostCSS 插件,它可以包装 PostCSS 嵌套或 PostCSS 嵌套,并作为一个兼容层来确保你选择的嵌套插件正确理解 Tailwind 的自定义语法,比如@application 和@screen。

1
2
3
4
5
6
7
8
9
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss/nesting'),
require('tailwindcss'),
require('autoprefixer'),
]
}

Variables

These days CSS variables (officially known as custom properties) have really good browser support, so you don’t need a preprocessor to use variables at all.

1
2
3
4
5
6
7
8
9
10
:root {
--theme-color: #52b3d0;
}

/* ... */

.btn {
background-color: var(--theme-color);
/* ... */
}

We use CSS variables extensively within Tailwind itself, so if you can use Tailwind, you can use native CSS variables.

You may also find that most of the things you’ve used variables for in the past can be replaced with Tailwind’s theme() function, which gives you access to all of your design tokens from your tailwind.config.js file directly in your CSS:

1
2
3
4
5
.btn {
background-color: theme('colors.blue.500');
padding: theme('spacing.2') theme('spacing.4');
/* ... */
}

Vendor prefixes

For automatically managing vendor prefixes in your CSS, you should use Autoprefixer.

To use it, install it via npm: —> 您可以使用 postcss-preset-env 插件为您的项目添加对即将到来的 CSS 特性的支持。

要使用它,请通过 npm 安装它:

1
npm install autoprefixer

Then add it to the very end of your plugin list in your PostCSS configuration:

1
2
3
4
5
6
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
]
}

生产优化

使用默认配置,TailwindCSS 的开发版本是3645.2kB未压缩,294.2kB用Gzip进行压缩,72.8kB用Brotli进行压缩。

这听起来可能很庞大,那是因为设计就很庞大。

为了使开发经验尽可能的富有成效,Tailwind 为您生成了成千上万的功能类,其中大部分您可能不会真正使用。

把 Tailwind 想象成一个巨大的乐高盒子—您把它倾倒在地板上,建造您想建造的东西,然后当您完成后,您把所有您不用的碎片放回盒子里。

例如,Tailwind 为您的间距尺度中的每一个尺寸,为您可能想要应用边距的元素的每一个侧面,在您的项目中使用的每一个断点生成边距实用程序。这导致了数以百计的不同组合,这些组合都是重要的,但不可能都是需要的。

当构建生产时,您应该总是使用 Tailwind 的 purge 选项来 tree-shake 优化未使用的样式,并优化您的最终构建大小当使用 Tailwind 删除未使用的样式时,很难最终得到超过 10kb 的压缩 CSS。

编写可清除的 HTML

在开始使用 Purge 功能之前,重要的是要了解它是如何工作的,并建立正确的心理模型,以确保您在为生产构建时永远不会意外地删除重要的样式。

PurgeCSS(我们在引擎下使用的库)在寻找 HTML 中的类的方式上故意非常幼稚。它并不试图解析您的 HTML 并查找类的属性,也不动态执行您的 JavaScript —它只是在整个文件中查找符合这个正则表达式的任何字符串。

1
/[^<>"'`\s]*[^<>"'`\s:]/g

这基本上可以匹配任何由空格、引号或角括号分隔的字符串,包括 HTML 标签、属性、类,甚至是您标记中的实际书面内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="md:flex">
<div class="md:flex-shrink-0">
<img class="rounded-lg md:w-56" src="/img/shopping.jpg" alt="Woman paying for a purchase">
</div>
<div class="mt-4 md:mt-0 md:ml-6">
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">
Marketing
</div>
<a href="/get-started" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">
Finding customers for your new business
</a>
<p class="mt-2 text-gray-600">
Getting a new business off the ground is a lot of hard work.
Here are five ideas you can use to find your first customers.
</p>
</div>
</div>

这意味着,重要的是避免在您的模板中使用字符串连接动态创建类字符串,否则 PurgeCSS 将不知道保存这些类。

如,不要使用字符串连接:

1
<div class="text-{{  error  ?  'red'  :  'green'  }}-600"></div>

而是动态选择一个完整的类名

1
<div class="{{  error  ?  'text-red-600'  :  'text-green-600'  }}"></div>

只要一个类名出现在您的模板中,PurgeCSS 就不会删除它。

删除未使用的CSS

基本用途
要开始使用,请使用 purge 选项为您所有的模板文件提供一个路径数组。

1
2
3
4
5
6
7
8
9
10
11
// tailwind.config.js
module.exports = {
purge: [
'./src/**/*.html',
'./src/**/*.vue',
'./src/**/*.jsx',
],
theme: {},
variants: {},
plugins: [],
}

例如,如果您的项目中有一个 JS 文件,在您的 HTML 中动态切换一些类,您应该确保在这个列表中包括该文件。

现在,每当您在编译 CSS 时将 NODE_ENV 设置为 productionTailwind 将自动从您的 CSS 中清除未使用的样式。

手动启用

如果您想手动控制是否应该删除未使用的样式(而不是隐性地依赖环境变量),您可以使用一个对象语法,并提供 enabled 选项,使用 content 选项指定您的模板。

1
2
3
4
5
6
7
8
// tailwind.config.js
module.exports = {
purge: {
enabled: true,
content: ['./src/**/*.html'],
},
// ...
}

我们建议只在生产中移除未使用的样式,因为在开发中移除它们意味着您需要在任何时候改变您的模板时重新编译,并且在启用 PurgeCSS 的情况下编译速度要慢得多。

如何使用Tailwind

功能类优先

1
2
3
4
5
6
7
8
9
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4">
<div class="flex-shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-gray-500">You have a new message!</p>
</div>
</div>

在上面的示例中,我们使用了:

  • 使用 Tailwind 的 flexboxpadding 功能类 (flex, flex-shrink-0, 和 p-6) 来控制整体的卡片布局

  • 使用 max-widthmargin 功能类 (max-w-smmx-auto) 来设置卡片的宽度和水平居中

  • 使用 background color, border radius, 和 box-shadow 功能类 (bg-white, rounded-xl, 和 shadow-md) 设置卡片的外观样式

  • 使用 widthheight 功能类 (w-12 and h-12) 来设置 logo 图片的大小

  • 使用 space-between 功能类 (space-x-4) 来处理 logo 和文本之间的间距

  • 使用 font sizetext color,和 font-weight 功能类 (text-xl,text-blackfont-medium 等等) 给卡片文字设置样式

这种方法使我们无需编写一行自定义的 CSS 即可实现一个完全定制的组件设计。

我知道您在想:“这太繁琐了,真是一团糟!” 您是对的,这有点丑陋。实际上,当您第一次看到它时,几乎不可能认为这是一个好主意—您必须实际尝试一下。

但是,一旦您以这种方式实际构建了一些东西,您就会很快注意到一些真正重要的优点:

  • 您没有为了给类命名而浪费精力。 不需要仅仅为了设置一些样式而额外添加一些像 sidebar-inner-wrapper 这样愚蠢的类名,不必再为了一个 flex 容器的完美抽象命名而倍受折磨。

  • 您的 CSS 停止增长。 使用传统方法,每次添加新功能时 CSS 文件都会变大。使用功能类,所有内容都是可重用的,因此您几乎不需要编写新的CSS。

  • 更改会更安全。 CSS 是全局性的,您永远不知道当您进行更改时会破坏掉什么。您 HTML 中的类是本地的,因此您可以更改它们而不必担心其他问题。

当您意识到在 HTML 中使用预定义的功能类是多么的富有成效时,以任何其他方式工作都感觉像是折磨。

响应式设计

Tailwind 中的每个功能类都可以有条件的应用于不同的断点,这使得您可以轻松的构建复杂的响应式界面而不用离开 HTML。

  1. 根据常用的设备分辨率方案,默认内置了 5 个断点:
断点前缀最小宽度CSS
sm640px@media (min-width: 640px) { … }
md768px@media (min-width: 768px) { … }
lg1024px@media (min-width: 1024px) { … }
xl1280px@media (min-width: 1280px) { … }
2xl1536px@media (min-width: 1536px) { … }
要添加一个仅在特定断点生效的功能类,只需要在该功能类前加上断点名称,后面跟 : 字符。
1
2
<!-- Width of 16 by default, 32 on medium screens, and 48 on large screens -->
<img class="w-16 md:w-32 lg:w-48" src="...">

这适用于框架中的每一个功能类,这意味着您可以在给定的断点更改任何东西,甚至包括字符间距和光标样式之类的内容。

  1. 自定义断点

您可以在 tailwind.config.js 文件中完全自定义您的断点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// tailwind.config.js
module.exports = {
theme: {
screens: {
'tablet': '640px',
// => @media (min-width: 640px) { ... }

'laptop': '1024px',
// => @media (min-width: 1024px) { ... }

'desktop': '1280px',
// => @media (min-width: 1280px) { ... }
},
}
}

Tailwind还支持许多其他常见的功能,比如,深色模式,提取组件,自定义功能类等,还提供了诸如@apply等函数与指令,具体文档可以参考下面的文档链接。

参考文章: