初探Tailwind CSS
写CSS有些年头了,经历了不同的时期用不同的姿势来编写CSS,其目的就是给Web元素添加样式。但编写样式着实令人感到烦恼,甚至是效率低下,成本极高。也正因如此,社区中有很多CSS方法论和框架来帮助开发快速有效编写CSS。虽然这些方法论和框架有助于我们快速编写CSS,构建UI组件,但也有令人感到头痛之处,比如冗余的代码,代码的覆盖等。随着功能第一(Utility-First)CSS的出现,让我看到了编写CSS的另一种有效的方式,该方式也被认为是现代Web中构建Web界面最好的选择。其中Utility-First CSS的典型作品之一就是Tailwind CSS。接下来,我们就来了探讨Tailwind CSS,我们将了解基于组件的样式有哪些问题,以及为什么要基于Utility-First CSS来构建组件。
编写CSS的姿势
时至今日,编写CSS有很多方式,也可以基于一些CSS框架来编写。比如2019年CSS状态报告中也有相关的统计:
或许你在项目中已经用了一些CSS方法论,比如BEM、Atomic CSS、OOCSS、SMACSS和ITCSS等,也体验过了在项目中引用社区中优秀的CSS框架,比如大家熟悉的Bootstrap、Foundation等。
随着一些优秀的JavaScript框架(比如,React和Vue)等出现,我们构建Web的方式也变了,也致使我们编写CSS的方式也不同了,社区中有很多关于CSS-in-JS的讨论,同样也有不同的方式方法:
如果你面对众多的编写CSS的姿势和管理维护方式感到困惑的话,建议你可以按照下图的流程来做选择:
有关于这方面的讨论,这里就不做过多的阐述了,如果你感兴趣的话,可以阅读:
虽然这些CSS方法都在试图着帮助我们解决CSS编写和管理的问题,但是如果我们能够编写实用程序类(Utility Class),然后在我们的代码库中重复使用它们,就会更容易一些。这些实用工具类是详尽的,可以作为padding
、margin
、font-size
等方面的独立指南。
另外实用程序类(Utility Class)将解决重复样式的问题,因为我们不再需要编写任何自定义样式。此外,如果我们的UI风格遵循特定的标准,我们也可以在开发中遵循相同的标准。其中Tailwind CSS就是社区中目前具备这些特点的CSS框架之一。是不是对Tailwind CSS感到好奇,如果是的话,请继续往下阅读。
什么是Tailwind CSS?
**Tailwind CSS**官网是这么描述的:
一个实用的CSS框架,是一个高度可定制的,底层的CSS框架,它为你提供了所有的构建模块,可以快速构建定制设计,也不会有额外的自定义CSS需要去覆盖。
换句话说,Tailwind CSS是一个基于实用程序的底层CSS框架,旨在简化Web应用程序的构建,提高事度,减少编写定制CSS的关注,而不需要离开HTML代码的舒适区,同时实现出色的界面。
比如官网首页提供的示例,只需要使用几个类就可以设计出不同的卡片效果(不需要总是声明一个大的类来独立于你的HTML和写一堆属性来制作一些东西):
<div class="md:flex bg-white rounded-lg p-6">
<img class="h-16 w-16 md:h-24 md:w-24 rounded-full mx-auto md:mx-0 md:mr-6" src="avatar.jpg">
<div class="text-center md:text-left">
<h2 class="text-lg">Erin Lindford</h2>
<div class="text-purple-500">Customer Support</div>
<div class="text-gray-600">erinlindford@example.com</div>
<div class="text-gray-600">(555) 765-4321</div>
</div>
</div>
而且只需要改变HTML中的类名,就可以达到不同的效果:
其他CSS框架(比如我们熟悉的Bootstrap、Foundation、Bulma等)提供了各种预定义组件(比如Modal
、Button
、Alert
和Card
等)。但是有了Tailwind CSS,可以自己做,或者你被迫根据你的项目模型自己做。换句话说,你实际上拥有了组件,你可以在你选择的任何组件上利用你的定制能力。这意味着不再需要与框架斗争,也不需要试图找出需要覆盖哪些类才能获得最初目标的结果。
Tailwind CSS不像Bootstrap
当你看到CSS框架一词时,我想你马上会想到Twitter的 Bootstrap (或类似于Bootstrap的CSS框架)。但它们之间还是存在很大的差异的,其中最大的差异就是:Bootstrap是一组可设定样式笔主题的组件,Tailwind 是一组可配置的实用CSS类;Bootstrap帮助你预构建组件,Tailwind为你提供了快速构建自己组件。
用一个按钮的示例来展示他们之间的区别。
先来看HTML代码:
<!-- Bootstrap -->
<button type="button" class="btn btn-primary">Primary</button>
<!-- Tailwind -->
<button class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-2 rounded">Primary</button>
可以看到,在Bootstrap中,HTML要简洁的多,所以你可能会问,既然Bootstrap更简单,为什么不使用它呢?为了回答这个问题,我们来设想有这么一个场景:“如果你想让按钮在特定的页面(或组件)上稍微小一点”?你是否想要为这种独特的情况创建一个新的类,比如Bootstrap中的.btn-sm
。在这种情况下,在Tailwind CSS中只需要使用不同的padding
类,比如py-1
。相比之下要比Bootstrap容易地多,而且你不需要去修改或增加任何CSS代码,而只需要调整HTML中class
的值。
而且在Tailwind CSS中和Bootstrap(或类似于Bootstrap的其他CSS框架)最大的不同,在class
中可以设置一些状态的类,比如hover:bg-blue-600
。这在Bootstrap中从未有过的特性和功能。
另外,在Tailwind CSS中也提供了创建类的可能性,比如在HTML文件中重复多次使用的组,以为该组件创建一个类,比如.btn-blue
。那么在Tailwind CSS中可以像下在这样使用:
<!-- Extracting component classes: -->
<button class="btn btn-blue">Button</button>
<style>
.btn {
@apply font-bold py-2 px-4 rounded;
}
.btn-blue {
@apply bg-blue-500 text-white;
}
.btn-blue:hover {
@apply bg-blue-700;
}
</style>
有关于这方面的具体使用,后续会花更多的时间来和大家一起探讨。
接下来,我们再来看一下Bootstrap和Tailwind CSS两个框架中CSS的差异性。同样拿上面的按钮Demo为例:
我想你在上面的截图中已经看出他们之间的差异了:Bootstrap中类的样式是一个集合(会有一个或多个样式);而Tailwind CSS中的每个类对应的仅是一个样式。
Tailwind CSS不像 Atomic Design
Tailwind CSS也不像 Atomic Design。了解Atomic Design的同学都知道,在Atomic Design系统中,可以将元素划分为最小单元体,将其称为元子,这些元子可以组合成最终的页面。
但Tailwind CSS的类特别像Atomic Design中的 Atoms。前面的示例可以获知,在元素上运用很多个不同类就能达到想要的UI,甚至是页面的效果。但在Tailwind CSS中这些类不被称为是Atoms 类,而是被称为实用性类(Utility Class)。
Tailwind CSS不像 OOCSS
Tailwind CSS也不像OOCSS(Object Oriented CSS)。如果用实际来说的话,Bootstrap中的很多东西更像OOCSS,它里面的一些设计思路就有OOCSS的身影,而Tailwind CSS不像OOCSS,不过Tailwind CSS有OOCSS最核心的设计思想,那就是:内容和结构的分离。
在社区中很还很多优秀的CSS方法论和框架,它们有着类似的设计思路或者管理模式,这里就不一一和Tailwind CSS做对比。事实上也是如此,任何一个CSS框架都有着自己的优势和弊端,既然如此,那么为什么要使用Tailwind CSS框架呢?
为什么要用 Tailwind CSS?
在这里我并不想只为Tailwind CSS做推广。或者说,一听说到CSS框架,你的内心就有一种排斥。比如上面做的对比,你可能发现了Tailwind CSS些许优势,即可以做到开箱即用,但也难免要花费时间去了解框架中的功能性类,而且其应用方式也非常不同,自身也有一定的问题。
除此之外,你可能不想从一种熟悉的环境中跳出来去接受一个新的环境,或者还没有被自己说服自己去接受Tailwind CSS带来的好处。那么接下来,我们先抛开这一切,我们从客端上来看,为什么要去用Tailwind CSS。
没有命名约定
在项目中编写CSS最令人头痛的是命名的约定,比如说类的命名,特别是团队多人协助情景下。在很多时候,都在想着怎么给类命名,才不会产生冲突(或尽可能的避免冲突),在思考哪些类应该是通用的,哪些类是特定的。这些问题是CSS一直存在的问题,虽然说CSS-in-JS或者说CSS Modules方法可以帮助我们解决这方面的冲突。但我们在编写组件的时候,还是没有较好的方法可以让CSS和HTML完全解耦。
Tailwind CSS框架采用基于功能性类的方式完美的解决了这些问题,可以让你做到CSS和HTML的解耦,而且也可以做到样式上的开箱即用。
但Tailwind CSS也无法满足你所有的业务场景,你总是需要去添加一些自定义的样式,如果你有一套体系的或者标准的规范,那么就可以像Tailwind CSS框架一样,根据这些规范定制出更属于自己业务场景的功能性类集合。
或许你和我有同样的想法,在HTML中的同一个标签元素上写那么多个类,令你感到恶心,想要一个更清晰的类。那么在Tailwind CSS中你也可以这么做,而且把这种方式称为提取组件类,意思是,当你需要提取某些组件并在以后的设计中使用。针对这样的情景,可以使用Tailwind CSS的@apply
指令快速达成。
缓存的好处
在编写CSS(或使用任何其他传统的CSS框架)时,一旦设计做出调整,就必须对CSS做出相应的调整。但是使用Tailwind CSS时,你不需要为此担心,因为Tailwind CSS框架中内聚了很多功能类名,你只需要根据新的设计需求调整HTML中标签元素的类名。这也意味着你不必每次都要调整CSS,破坏CSS的缓存。
可配置
Tailwind CSS另一个优点是,一旦你习惯了语法,它可以加快开发速度。不需要经常在HTML和CSS文件之间来回切换,而且类编写起来很快很容易。如果你在代码编辑器中使用了相匹配的插件,比如VS Code中的 **Tailwind CSS IntelliSense**插件,在编码的时候就可以自动补全,编写起来会更快。
其缺点是需要在配置中进行一些初始化相关的配置工作。Tailwind CSS附带了一个config.js
配置文件,其中定义了所有的变量,比如颜色、排版、大小等等。这里有一个默认的配置,但是你很可能需要对它进行大量的定制,这样做确实是值得的。在编写任何代码之前,你可能会感觉花费了大量的时间来进行配置,但这个时间的花费是值得的,因为配置完成之后,在后面的编码阶段会变得更快,更容易。
config.js
具体如何配置,后面我们会介绍。
插件机制
因为Tailwind CSS是用JavaScript配置的,所以可以编写函数并将它们传递到配置中。它的优点是为你提供了所有的JavaScript能力,你还可以根据自己的需要编写自己定义的实用程序作为插件。比如:
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addBase, config }) {
addBase({
'h1': { fontSize: config('theme.fontSize.2xl') },
'h2': { fontSize: config('theme.fontSize.xl') },
'h3': { fontSize: config('theme.fontSize.lg') },
})
})
]
}
一般来说,在CSS中添加基本样式要比编写插件要简单得多。但在CSS中添加基本样式也有一些细节需要注意。比如,在平时编写CSS的时候,你可能会使用像Sass这样的处理器,并且在这方面有一定的积累,可以在需要时将它们应用到整个项目中。如果在项目中希望将这些与Tailwind CSS一起使用,可能会导致一定的混乱,因为你可能希望样式被覆盖,但它们并没有被覆盖(哪些样式能被覆盖,这取决于样式导入的顺序,这主要是样式级联和继承造成的)。了解到了这一点之后,我建议你编写自己自定义实用程序作为Tailwind CSS插件,而不是在直接引入一个Sass(或者你自己用其他处理器写的实用程序类)。你可以从这些输出以及所有Tailwind CSS的常规实用程序中获益。
当然,如果你碰到下面这样的场景,应该编写一个插件更合适:
- 你希望公开发布基本样式,并使其易于其他用户安装
- 你希望在公司的多个项目中重用基本样式,并希望共享JavaScript依赖项而不是CSS依赖项
虽然使用插件机制能让我们获益不少,但他也有一定的缺点和成本。那就是对于不太熟悉JavaScript的同学来说,成本更大。而且我还认为了解JavaScript(甚至精通JavaScript)的同学不一定能很好的掌握HTML和CSS。换句话说,不认为了解JavaScript应该是编写好的HTML和CSS的先决条件。
状态机制
前面我们有提到过,Tailwind CSS框架和其他的CSS框架有一个最大不同点,那就是Tailwind CSS提供了状态和断点语法,比如下面这样的示例:
<!-- 其他CSS框架状态的运用,比如Bootstrap -->
.button {
color: #fff;
&:hover {
color: #09f;
}
}
<!-- Tailwind CSS框架中的状态机制 -->
<div class="text-white hover:text-blue"></div>
性能
从理论上来说,实用程序类被设计成可重用的,因此你最终应该交付一个更小的CSS文件。文件越小,性能越好。然而,如果不加修改,Tailwind CSS框架会和其他的CSS框(比如Bootstrap)类似,会将所有类添加到样式文件中,其中会有大量未使用的CSS,除非通过一定的技术手段进行优化,将未使用到的类对应的CSS样式删除。就这一点而言,像Bootstrap这样的框架是很难做的,因为他的出发点就是预定一些样式和组件,以便更好的提供给开发者使用;但Tailwind CSS不同,可以采用一些方法来删除不必要的CSS,从而减少整个样式文件的大小。
在Tailwind CSS官方文档中推荐使用PurgeCSS这样的PostCSS插件,该插件对于Tailwind CSS特别有效,因为Tailwind CSS中有数千个类,而其中大多数都有可能在实际项目中用不到(这也是很多人排斥的原因之一)。
具体如何在项目中配置PurgeCSS,在后面的内容中将会涉及到。
什么时候不使用 Tailwind CSS?
你可能也会问?既然Tailwind CSS是一个实用性为最高宗旨的CSS框架,而且有着其独特的优势:能做到开箱即用,快速构建自己所需要的UI。是不是意味着应该在每个项目中都使用Tailwind CSS框架(或者说其他实用性CSS框架)。这当然不是。试想一下,虽然Bootstrap框架在业内非常的优秀,使用的人数众多,但这也并不意味着所有的项目中都要使用Bootstrap,那么Tailwind CSS也是类似的。在一些用例中(或场景中)是不应该使用Tailwind CSS的。
如果你在做一个小项目
当你正在构建一个小型的Web项目或应用时,它有一个非常短的期限,那么Tailwind CSS是不太适合的。在这些情景下,我更建议你使用类似Bootstrap、Foundation的CSS框架。这是因为它们带有预定义的现成组件或主题。如果使用Tailwind CSS,你必须创造性地创建自己的CSS。
如果你是一位CSS的初学者
CSS虽然简单,但要掌握它并不是件易事。
如果你想在Web项目中更好的使用Tailwind CSS的话,就首先要对CSS有所掌握。因为Tailwind CSS是了底层中提供了很多实用程序类,只有对CSS有所掌握(或具有扎实CSS知识)的人才能轻松地使用好Tailwind CSS框架构建Web项目。
如果你不喜欢在HTML标签元素中添加大量的类
通过前面的学习,我想你已经感受到了,在Web项目中使用Tailwind CSS框架的话,最大的感受就是在HTML中的标签元素中使用框架中预设好的实用程序的类。简单地说,就是要在HTML的元素中编写大量的类名,这使得HTML代码变得臃肿难看,有的时候也很难阅读。如果你讨厌这种方式(说实话,我以前也特讨厌这样的姿势),那么就不应该在开发中使用Tailwind CSS框架。
是不是感受到了Tailwind CSS和CSS禅意花园提到的理念刚好相反。在CSS禅意花园中提倡的是在相同的HTML中编写不同的CSS达到不一样的效果;Tailwind CSS提倡的是在相同的CSS框架上在不同的HTML中使用不同的类达到不一样的效果。
不应该在任何场景中使用
有些人特别喜欢Tailwind CSS这样的框架,因此主张在任何项目中都使用该框架。其实我是不推荐这样的方式。拿个示例来说吧。CSS Grid这样的现代Web布局方法,其实是非常的强大,假设你想在实用程序类中预定所有CSS Grid能实现的布局所需的类,那么这个实用程序类就会非常的大,甚至令你感到疯狂。除此之外,并不一定能能够充分的用好CSS Grid的能力。
正如Tailwind CSS中的Grid方面插件,它就这样描述过:
通过实用程序类来展示CSS Grid的所有功能是不现实的。
不过Tailwind CSS的网格插件并不具备所有Grid的能力,它只使用了CSS网格来代替使用浮动或Flexbox制作的网格布局。
这仅仅是其中一个示例,CSS的世界既是一个简单的世界也是一个复杂的世界,如果你说Tailwind CSS能涵盖所有CSS属性功能(即使用实用程序类来实现CSS所有属性功能)是不可能的,也是不实用的。因此在任何一个项目都都缺少不了自己定义的CSS。
开始使用 Tailwind CSS?
如果你坚持阅读到这里,说明你对Tailwind CSS有了一个基本了解。那么接下来要我们一起来看看怎么在项目中使用Tailwind CSS框架。
接下来将结合React的开发环境来向大家阐述,在项目中怎么使用Tailwind CSS。
为了设置我们的项目和节约一些时间,将使用create-react-app
来构建一个React应用程序。将基于其环境来配置Tailwind CSS所需的配置项。
安装Tailwind CSS
在命令终端执行下面的命令,构建一个React项目:
▶ npx create-react-app app-tailwind-css
然后进入新创建的项目app-tailwind-css
,并安装tailwindcss
:
▶ cd app-tailwind-css && npm i tailwindcss -D
接下来,使用@tailwind
指令将Tailwind CSS的base
、components
和utilities
引入到项目的CSS文件中。要做到这一点,需要在/src/styles/vendors.css
文件中添加以下代码:
// src/styles/vendors.css
@tailwind base;
@tailwind components;
@tailwind utilities;
接下来在package.json
文件的scripts
中添加build:style
:
// package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"build:style": "tailwind build src/styles/vendors.css -o src/styles/tailwind.css"
},
这个时候,你在命令终端执行下面的命令,就会在/src/styles/
目录下生成一个名为tailwind.css
样式文件:
▶ npm run build:style
这个时候就可以把新生成的tailwind.css
引入到项目中,比如/src/App.js
文件中:
// src/App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import './styles/tailwind.css'
这个时候你执行npm run start
,在浏览器中访问http://localhost:3001/
,看到的效果并没有任何变化:
我们的目的是,要在Create React App创建的项目中使用Tailwind CSS,为了验证前面的步骤是否生效,我们可以在/src/App.js
的<header>
元素上添加tailwind.css
(也就是Tailwind CSS)中的一个类,比如bg-blue-900
:
// src/App.js
<div className="App">
<header className="App-header bg-blue-900">
<!-- 省略不展示的代码 -->
</header>
</div>
这个时候,你可以看到<header>
元素的background-color
由#282c34
变成#2a4365
:
#2a4365
就是Tailwind CSS中的bg-blue-900
对应的backround-color
。这也说明tailwind.css
已在项目中生效了。
配置Tailwind CSS
默认情况下,Tailwind CSS的大小是78.0kb
(gzip),而Bootstrap的大小是22.7kb
(gzip)。但是,我们可以通过对Tailwind CSS进行配置,减少文件大小。这里不会对所有策略进行介绍。但是,我们将[使用Tailwind的配置文件进行配置]//tailwindcss.com/docs/configuration/),看看怎么减少文件大小。
首先,在命令终端执行下面的这个命令,将会在项目的根目录下创建一个名为tailwind.config.js
的配置文件:
▶ npx tailwind init
打开tailwind.config.js
文件,可以看到下面这段代码:
// tailwind.config.js
module.exports = {
theme: {
extend: {},
},
variants: {},
plugins: [],
}
接下来,我们一起来看,怎么在这个配置文件中添加相关的配置达到我们自己的诉求。
前面多次提到过Tailwind CSS内置了很多实用程序的类,而其中有很多类我们是不会用到的,为了让自己的CSS文件能更小一些,可以使用PurgeCSS来做优化。我们可以使用PurgeCSS的PostCSS插件版本(它也有Webpack版本)。这里我们以PostCSS插件为例。
在使用PostCSS插件之前,首先需要在项目的根目录下创建一个名为postcss.config.js
文件,同时在命令终端执行下面的命令来安装PurgeCSS:
▶ npm i @fullhuman/postcss-purgecss cssnano -D
打开postcss.config.js
文件,添加有关于PurgeCSS的相关配置:
// postcss.config.js
const purgecss = require("@fullhuman/postcss-purgecss")({
// 指定项目中所有模板文件的路径
content: [
"./src/**/*.html",
"./src/**/*.vue", //用于Vue项目
"./src/**/*.jsx",
"./src/**/*.js",
"./src/**/*.tsx",
"./src/**/*.ts",
"./public/index.html"
// etc.
],
// 包括在这个正则表达式中使用的任何特殊字符
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
});
module.exports = {
plugins: [...(process.env.NODE_ENV === "production" ? [purgecss, require('cssnano')] : [])]
};
我们需要做的另一件事是对package.json
中的一个脚本进行轻微修改。在我们的prebuild
中添加NODE_ENV=production
为Webpack设置环境变量,其中create-react-app
在底层中使用了该变量,并将触发PostCSS CLI在我们样式构建中使用PurgeCSS。
// package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"build:style": "tailwind build src/styles/vendors.css -o src/styles/tailwind.css",
"prebuild": "NODE_ENV=production npm run build:style"
},
在命令终端执行:
▶ npm run build && serve -s build
编译出来的结果:
有关于如何在Tailwind CSS中减少文件大小更详细的介绍,还可以阅读官网的相关介绍。
如果你查看代码,你会发现目前项目的样式在编译的时候并没有带上私有前缀:
我们需要在Tailwind CSS中配置Autoprefixer,因为Autoprefixer通常会跟踪caniuse.com的数据,查看哪些CSS属性需要添加私有前缀。只需在postcss.config.js
和package.json
配置即可:
// postcss.config.js
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
tailwindcss('./tailwind.config.js'),
require('autoprefixer'),
...(process.env.NODE_ENV === "production" ? [purgecss] : [])
]
};
// package.json
"browserslist": [
">1%",
"iOS >= 4",
"Firefox >= 20",
"Android > 4.0"
],
这个时候,你可以看到需要前缀的属性就会自动添加私有前缀了:
除了配置PostCSS相关的事项之外,还可以通过tailwind.config.js
配置文件覆盖Tailwind的默认调色板或者对调色板进行扩展,还可以禁用某些颜色。
在平时的开发中,你或者你的团队已经有一套适合自己团队的样式库,甚至是适合自己的实用程序类库。和Tailwind CSS框架可能会出现问题,Tailwind CSS框架中的实用程序类可能会干扰自己现有的类(特别是类名相同的时候,造成冲突)。对于这样的现象,我们可以在tailwind.config.js
配置文件中添加相应的配置,比如给Tailwind CSS框架中的类添加一个前缀来解决。
// tailwind.config.js
module.exports = {
prefix: 'u-',
theme: {
extend: {},
},
variants: {},
plugins: [],
}
保存上面的配置,重新执行npm run build:style
命令生成新的tailwind.css
文件。那么原有的类前面就会添加前缀u-
:
这个时候在引用Tailwind CSS的时候,就需要使用带有u-
前缀的类名了,比如前面示例中的bg-blue-900
,换成u-bg-blue-900
:
// /src/App.js
<div className="App">
<header className="App-header u-bg-blue-900">
<!-- 省略示例代码 -->
</header>
</div>
这个时候访问页面,看到的效果和前面展示的效果是一样的。
我们在编写CSS的时候,总是难免碰到选择器权重的问题,在使用Tailwind CSS的时候难免也会碰到这样的问题,如果希望让Tailwind CSS框中的类名权重更高,可以在配置文件中给tailwind.css
中的类名添加!important
来加重选择器权重:
// tailwind.config.js
module.exports = {
prefix: 'u-',
important: true,
theme: {
extend: {},
},
variants: {},
plugins: [],
}
然后执行npm run build:style
,编译之后tailwind.css
中的样式会像下面这样:
// src/styles/tailwind.css
.u-bg-black {
background-color: #000 !important;
}
但不建议通过给样式添加!important
来解决选择器权重的问题。这也不是最好的解决方案。
扩展Tailwind CSS
前面提到过,我们可能有自己的类库。在Tailwind CSS框架中,除了配置前缀来做区别之外,还可以扩展TTailwind CSS的实用性程序类。在扩展Tailwind CSS时,有一个小细节需要注意,新的实用程序类要放置在@tailwind
指令之后。在我们的示例中,就是在/src/styles/vendors.css
文件的@tailwind
指令后,比如像下面这样:
// /src/styles/vendors.css
@tailwind base;
@tailwind components;
@tailwind utilities;
.rotate-0 {
transform: rotate(0deg);
}
.rotate-90 {
transform: rotate(90deg);
}
.rotate-180 {
transform: rotate(180deg);
}
.rotate-270 {
transform: rotate(270deg);
}
编译之后,你会发现在tailwind.css
有对应的样式:
// src/styles/tailwind.css
.rotate-0 {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.rotate-90 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.rotate-180 {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.rotate-270 {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
如果你正在做一个响应式的Web应用,或者想令扩展的Tailwind CSS也具有响应式能力,可以在扩展Tailwind CSS的时候使用@responsive
指令,比如:
// /src/styles/vendors.css
@responsive {
.w-320 {
width: 320px;
}
.w-760 {
width: 760px;
}
.w-1024 {
width: 1024px;
}
}
编译出来的代码如下:
// src/styles/tailwind.css
.w-320 {
width: 320px;
}
.w-760 {
width: 760px;
}
.w-1024 {
width: 1024px;
}
@media (min-width: 640px) {
.sm\:w-320 {
width: 320px;
}
.sm\:w-760 {
width: 760px;
}
.sm\:w-1024 {
width: 1024px;
}
}
如果想扩展悬浮或聚焦等状态下的样式,可以使用@variants
指令:
@variants hover, focus {
.button {
color: #f36;
}
}
编译出来的结果:
.button {
color: #f36;
}
.hover\:button:hover {
color: #f36;
}
.focus\:button:focus {
color: #f36;
}
@variants
指令同样可以放在@responsive
,在对应的媒体查询中生成相应的样式代码。
除了在CSS文件中添加自己所需要的实用程序类扩展Tailwind CSS之外,还可以通过Tailwind CSS的插件机制来扩展Tailwind CSS,比如像下面这样:
// tailwind.config.js
module.exports = {
// a bunch of other tailwind settings
plugins: [
function({ addComponents }) {
const buttons = {
'.btn': {
padding: '.5rem 1rem',
borderRadius: '.25rem',
fontWeight: '600',
},
'.btn-primary': {
backgroundColor: '#4299e1',
color: '#fff',
'&:hover': {
backgroundColor: '#3182ce'
},
},
'.btn-secondary': {
backgroundColor: '#667eea',
color: '#fff',
'&:hover': {
backgroundColor: '#5a67d8'
},
},
}
addComponents(buttons)
}
]
}
有关于这方面更多的介绍,可以点击这里查阅。
在React的项目中使用Tailwind CSS
现在我们对Tailwind CSS有了一个基础性的了解,接下来,我们来看看在React中怎么使用Tailwind CSS来构建页面。
首先清理/src/App.js
,删除不必要的代码,你将看到的是一个最干净的代码:
// /src/App.js
import React from 'react';
import './styles/tailwind.css'
function App() {
return (
<div className="">
</div>
);
}
export default App;
接下来,在src/
目录下创建一个components
目录,并在该目录创建两个组件:Header
和Card
:
▶ cd src && mkdir components
▶ cd components && mkdir Header Card
▶ cd Header && touch index.js
▶ cd .. && cd Card && touch index.js
项目结构如下:
接下来,先来构建Header
组件。在Header/index.js
添加所需要的代码:
// /src/components/Header/index.js
import React from 'react';
function Header() {
return (
<header className="">
<h1 className="">
<svg role="img" aria-hidden="true" focusable="false" height="62.2" width="62.2" version="1.1" viewBox="0 0 62.2 62.2" xmlns="http://www.w3.org/2000/svg" x="0" y="0" xmlSpace="preserve">
<path d="M61.207,55.36L47.773,41.925c2.864-4.192,4.543-9.262,4.543-14.712c0-14.424-11.734-26.16-26.159-26.16 C11.734,1.053,0,12.79,0,27.213c0,14.423,11.734,26.158,26.158,26.158c6.53,0,12.502-2.408,17.09-6.379L56.41,60.155 c0.662,0.662,1.529,0.992,2.398,0.992c0.866,0,1.735-0.33,2.397-0.992C62.531,58.833,62.531,56.682,61.207,55.36z M40.921,44.524 c-3.979,3.397-9.133,5.457-14.766,5.457c-12.553,0-22.767-10.215-22.767-22.768c0-12.555,10.214-22.768,22.767-22.768 c12.557,0,22.77,10.213,22.77,22.768c0,4.596-1.373,8.876-3.729,12.46C44.007,41.487,42.566,43.122,40.921,44.524z"/>
<path d="M39.08,23.396l-2.409-1.855l-0.653-0.504v-5.79c0-0.819-0.666-1.483-1.484-1.483s-1.482,0.664-1.482,1.483v3.505 L26.9,14.017c-0.436-0.336-1.042-0.336-1.478,0l-9.916,7.634l-2.419,1.862l-2.809,2.163c-0.53,0.408-0.629,1.169-0.221,1.699 c0.408,0.529,1.169,0.629,1.699,0.221l1.33-1.024v12.88c0,0.67,0.543,1.211,1.212,1.211h1.174H37.87 c0.67,0,1.213-0.541,1.213-1.211V26.455l1.479,1.141c0.222,0.17,0.479,0.252,0.736,0.252c0.363,0,0.725-0.162,0.961-0.472 c0.41-0.531,0.312-1.291-0.219-1.7L39.08,23.396z"/>
</svg>
<span className="">Tailwind CSS</span>
</h1>
<nav role="navigation">
<ul>
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">CSS</a>
</li>
<li>
<a href="#">JavaScript</a>
</li>
<li>
<a href="#">React</a>
</li>
<li>
<a href="#">Vue</a>
</li>
</ul>
</nav>
</header>
);
}
export default Header;
并在/src/App.js
中引入Header
组件:
// /src/App.js
import React from 'react';
import Header from './components/Header';
import './styles/tailwind.css'
function App() {
return (
<div className="">
<Header />
</div>
);
}
export default App;
你可能看到了,在Header
组件中,我们还没有添加任何有关于Tailwind CSS的实用程序类,所以你在浏览器中看到的效果是没有任何样式风格的:
接下就在Header
组件的标签元素上添加Tailwind CSS框架中的类:
// src/components/Header/index.js
import React from 'react';
function Header() {
return (
<header className="flex items-center bg-gray-900 px-6 py-2 text-white">
<h1 className="flex items-center mr-6">
<svg className="fill-current h-8 w-8" role="img" aria-hidden="true" focusable="false" height="62.2" width="62.2" version="1.1" viewBox="0 0 62.2 62.2" xmlns="http://www.w3.org/2000/svg" x="0" y="0" xmlSpace="preserve">...</svg>
<span className="text-xl ml-2">Tailwind CSS</span>
</h1>
<nav role="navigation">
<ul className="flex items-center text-sm">
<li>
<a href="#" className="block hover:text-teal-200 p-4">Home</a>
</li>
<!-- ... -->
</ul>
</nav>
</header>
);
}
export default Header;
这个时候,你可以看到有一个带有样式的页头:
我们可以按上面的方式来写Card
组件:
// src/components/Card/index.js
import React from 'react';
function Card() {
return (
<div className="max-w-sm">
<div className="rounded overflow-hidden shadow-lg">
<img
className="w-full"
src="https://tailwindcss.com/img/card-top.jpg"
alt="Sunset in the mountains"
/>
<div className="px-6 py-4 bg-white">
<div className="font-bold text-xl mb-2">...</div>
<p className="text-gray-700 text-sm">...</p>
</div>
<div className="px-6 py-4 bg-gray-100">
<span className="inline-block bg-gray-300 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2">...</span>
<span className="inline-block bg-gray-300 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2">...</span>
<span className="inline-block bg-gray-300 rounded-full px-3 py-1 text-sm font-semibold text-gray-700">...</span>
</div>
</div>
</div>
);
}
export default Card;
在App.js
中引入Card
组件:
// src/App.js
import React from 'react';
import Header from './components/Header';
import Card from './components/Card';
import './styles/tailwind.css'
function App() {
return (
<div className="page">
<Header />
<main className="flex justify-around h-screen bg-gray-200 py-10 px-6" role="main">
<Card />
<Card />
<Card />
</main>
</div>
);
}
export default App;
此时你看到的效果如下:
整个过程下来,是不是感觉不需要写任何CSS代码就可以构建出想要的UI效果。这也是Tailwind CSS和其他CSS框架不同之处。
小结
在这篇文章中,我们学习了Tailwind CSS的基础知识,同时了解了如何在Reac中使用Tailwind CSS来美化页面。我们还注意到,我们可以更快地设计、开发Web应用程序,因为我们不必再担心编写定制的CSS样式。Web应用程序将变得更易于维护,因为我们不必再担心删除CSS样式。
当然,Tailwind CSS并不是解决所有CSS问题的灵丹妙药,在开发过程中难免是需要添加一些适合业务的类。甚至,你可能在第一次使用Tailwind CSS时,可能会觉得它是违反直觉的(在HTML中标签元素中要添加很多个类名),但是在你决定它是否是适合你的正确方法之前,它是值得坚持的。虽然我不会选择在每个项目中都使用它,但它有明显的好处。如果你对此感兴趣的话,不仿自己一试,只有试过了,才知道是否适合自己。