文章目录
- 入门
- 安装
- IDE 设置
- 使用预编译器
- 生产环境优化
- 基础概念
- 分层
- 指令
- @tailwind
- @layer
- @apply
- @config
- 函数
- theme()
- screen()
- 基础案例
- 怎么设置属性任意值?
- hover 父元素时,怎么选中子元素添加样式?
- 添加 animation 动画
- 配置主题
Tailwind CSS 中文网
Tailwind Play
入门
安装
三种使用方式:
- cli
- 结合 postcss
- cdn
cli 方式就和命令行使用 scss、tsc 这些工具一样,需要手动执行监听文件改变的命令,实时编译。这种方式只适合做 demo 时的简单使用。
想要正儿八经的使用,比如和构建工具结合,就要搭配 postcss 一起使用。
pnpm install -D tailwindcss postcss autoprefixer
pnpm tailwindcss init --postcss
tailwindcss 初始化后会生成 postcss 和 tailwindcss 的配置文件。
然后在 tailwindcss.config.js 的 content 选项中配置需要编译的模版文件路径。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {},
},
plugins: [],
}
将指令添加到主 css 文件:
@tailwind base;
@tailwind components;
@tailwind utilities;
此时会出现 css 无法识别 tailwind 指令的问题。
解决办法:
解决 vscode Unknown at rule @xxx 的警告
IDE 设置
vscode 安装 tailwind 插件可以获得提示和高亮。并且官方提供了一个 Prettier 插件,它会自动按照官方推荐的类顺序对你写的类进行排序。
pnpm add -D prettier prettier-plugin-tailwindcss
{
"plugins": [
"prettier-plugin-tailwindcss"
]
}
注意:项目中声明了 prettier 的配置文件的,那 vscode settings.json 中的 prettier 配置就会被覆盖。
所以项目中的配置文件除了声明使用 prettier-plugin-tailwindcss 插件外,还要补充其他额外的配置。除非你起初使用的 prettier 配置就是 prettier 默认的配置。
另外配置文件可能出现 json schema 验证失败的问题。
解决"无法从“https://json.schemastore.org/xxx”加载架构"的问题
使用预编译器
由于 Tailwind 是一个 PostCSS 插件,没有什么能阻止你将它与 Sass、Less、Stylus 或其他预处理器一起使用。
虽然可以,但非常不建议和预编译器一起使用。
当需要使用某些预编译器的功能时,你应该高度考虑依赖其他 PostCSS 插件来添加你使用的预处理器功能,而不是使用单独的 预处理器。
- postcss 插件列表:postcss/docs/plugins.md at main · postcss/postcss
预编译器最常见的几个功能:
- css 拆分成多个文件导入
- 选择器嵌套
- 变量
- 浏览器前缀
这 4 个功能对应的 postcss 解决方案:
- postcss 插件:postcss-import
- 安装使用。
- 官方基于 postcss-nested(默认) 或 postcss-nesting 封装的插件:tailwindcss/nesting
- 已经内置,可直接使用,并且可配置应用哪个postcss-nesting 插件。不过需要安装使用。
- 如果使用了 postcss 预设: postcss-preset-env。则要手动关掉预设中的嵌套功能,让官方的嵌套插件生效。
- 直接使用 css 变量
- postcss 插件:autoprefixer
- 安装使用,并且添加在插件末尾使用。其实 init 时,已经添加在末尾。
postcss-import 它严格遵守 CSS 规范, @import
语句必须在第一行使用。
这个问题容易在两个地方忽视:一是和常规 CSS 写在一起时,二是和 tailwind 主 css 文件写在一起时。
无论是 .box {} 这样的常规 CSS 还是 @tailwind 指令,@import 都必须写在第一行。
为了解决这个容易忽视的问题,最好的办法就是拆成单独文件写。
/* components.css */
@import "./components/buttons.css";
@import "./components/card.css";
/* components/buttons.css */
.btn {
padding: theme('spacing.4') theme('spacing.2');
/* ... */
}
使用 postcss-nesting 作为嵌套实现,并关闭 postcss 预设插件中的嵌套功能:
// postcss.config.js
module.exports = {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': 'postcss-nesting',
tailwindcss: {},
'postcss-preset-env': {
features: { 'nesting-rules': false },
},
}
}
总结 postcss 配置:
pnpm add -D postcss-import
pnpm add -D autoprefixer
export default {
plugins: {
"postcss-import": {},
"tailwindcss/nesting": {},
tailwindcss: {},
autoprefixer: {}
}
};
硬要和预编译器一起使用,具体参考文档。
生产环境优化
对于尽可能小的生产构建,我们建议使用 cssnano 等工具缩小 CSS,并使用 Brotli 压缩 CSS。
如果你使用的是 Tailwind CLI,则可以通过添加 --minify 标志来缩小 CSS:
npx tailwindcss -o build.css --minify
如果你已将 Tailwind 安装为 PostCSS 插件,请将 cssnano 添加到插件列表的末尾:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {})
}
}
如果你使用的是框架,请查看文档,因为这通常会在生产中自动为你处理,你甚至不需要对其进行配置。
基础概念
分层
首先我们要明白,tailwind 能通过类的方式来写样式,是因为它已经提供了这些写好了 css 的类。并且 tailwind 把这些类分成了三层。
Tailwind 将其生成的样式组织成三个不同的 “layers” — 这是 ITCSS 推广的概念。
base
层用于重置规则或应用于纯 HTML 元素的默认样式。components
层用于你希望能够使用工具覆盖的基于类的样式。utilities
层用于小型、单一用途的类,这些类应始终优先于任何其他样式。
ITCSS(Inverted Triangle CSS)是一种CSS架构方法,它通过将CSS代码组织成一系列层次来提高CSS的可维护性和可扩展性。这些层次从宽泛的、全局的设置到非常具体、局部的样式,形成一个倒三角形的结构。
每一层都有其明确的职责,如下:
- Settings:包含设计中的变量,如颜色、字体和断点。
- Tools:包含辅助函数、混合宏和实用工具类。
- Generic:包含重置、标准化样式和排版规则。
- Base:包含元素的样式,如按钮、表单和网格系统。
- Objects:包含设计中的布局模式,如媒体对象和列表。
- Components:包含更复杂的功能模块,如按钮组、轮播和导航。
- Utilities:包含最具体的设计调整,如间距、文本样式和可见性。
ITCSS的目标是通过限制CSS的特异性、减少依赖性、避免重叠和冲突,以及提供清晰的代码组织结构,来创建一个易于管理和扩展的CSS代码库。这种方法特别适合大型项目和团队协作,因为它有助于确保一致性和减少不必要的复杂性。
指令
tailwind 总共就提供了 4 个指令。
@tailwind
@tailwind 指令就像是导入语句 import,将 Tailwind 提供的 base、components、utilities 和 variants 样式插入到你的 CSS 中。
@layer
自定义样式的时候,我们可能会添加一些自定义类。@layer 指令就是用来告诉 tailwind 这些自定义的类应该属于三层中的哪一层,tailwind 你要按这一层的规矩管理它。
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
}
@layer components {
.btn-blue {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}
}
@layer utilities {
.filter-none {
filter: none;
}
.filter-grayscale {
filter: grayscale(100%);
}
}
@apply
@apply 指令如上所示,就是可以在自定义的 css 中使用 tailwind 提供的类。而且它不仅仅局限于 tailwind 提供的类,自定义的类也可以提取其中的样式进行复用。
- 不过要注意:从类中提取的样式会删掉 !important。
@layer base {
h1 {
@apply text-2xl;
}
}
.foo {
color: blue !important;
}
.bar {
@apply foo;
}
还有一点,就是 @apply 指令在 Vue 组件中无法提取应用其他 css 文件中自定义的类。比如在主 css 文件 main.css 中自定义了一个 card 类,在组件中无法 @apply 应用 card 类。
这是因为每个 Vue 组件中
解决办法是在 tailwind 插件中添加自定义的 css 类,这样就能全局共享了。
const plugin = require('tailwindcss/plugin')
module.exports = {
// ...
plugins: [
plugin(function ({ addComponents, theme }) {
addComponents({
'.card': {
backgroundColor: theme('colors.white'),
borderRadius: theme('borderRadius.lg'),
padding: theme('spacing.6'),
boxShadow: theme('boxShadow.xl'),
}
})
})
]
}
但老实说,最好的解决办法就是根本不做这种奇怪的事情。因为你完全可以在 html 模版上写类,压根不需要
@config
@config 指令指定 Tailwind 在编译该 CSS 文件时应使用哪个配置文件。这对于需要为不同的 CSS 入口点使用不同的配置文件的项目很有用。
你提供给 @config 指令的路径是相对于该 CSS 文件的,并且将优先于 PostCSS 配置或 Tailwind CLI 中定义的路径。
@config "./tailwind.admin.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;
@config "./tailwind.site.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;
函数
Tailwind 添加了一些自定义函数,用来在自定义样式时,在 css 中获取 tailwind 提供的样式中的一些值。比如使用 tailwind 提供的间距,颜色等。
theme()
theme() 读取 tailwind 类中的样式。使用.
表示法读取值。
- 如果类中就带了点,避免歧义使用
[]
获取
.content-area {
height: calc(100vh - theme(spacing.12));
}
.content-area {
height: calc(100vh - theme(spacing[2.5]));
}
- 访问嵌套颜色值时不要使用破折号语法,要把破折号换成点
/* 错误 */
.btn-blue {
background-color: theme(colors.blue-500);
}
/* 正确 */
.btn-blue {
background-color: theme(colors.blue.500);
}
- 要调整使用 theme 检索到的颜色的透明度,请使用斜杠后跟你要使用的透明度值:
.btn-blue {
background-color: theme(colors.blue.500 / 75%);
}
screen()
screen() 复用 tailwind 提供的断点,直接在媒体查询中使用。当想要媒体查询时,不用自己去查看 tailwind 编译的断点结构,然后复制使用。
/* 自己手写 */
@media (min-width: 640px) {
/* ... */
}
/* 直接用 tailwind 的断点修饰符 */
@media screen(sm) {
/* ... */
}
基础案例
tailwind 默认提供了样式重置。
怎么设置属性任意值?
所有的任意值,也可以说自定义的属性值,都是用[]
包裹标记。
比如想要设置背景颜色为 #123456,bg-[#123456]
。并且能自动区分,如text-[2em]
是文字大小,text-[#123456]
是文字颜色。
若是 tailwind 没有提供的属性,则全用[]
包裹。如文字阴影:[text-shadow:0_3rem_#fff]
在[]
中,多个属性值之间的空格用_
代替。[]
中其实就相当于直接写 css 属性值,所以也支持 css 的函数。如 var、calc。
text-[var(--color)]
hover:shadow-[0_0_25px_var(--color),0_0_100px_var(--color)]
hover 父元素时,怎么选中子元素添加样式?
group 标记父元素,然后 group:hover: 给子元素设置样式。如group:hover:text-red
。
其他的,如兄弟选择器等,看文档。
添加 animation 动画
tailwind 默认提供了 4 个动画,分别是:
- spin 旋转
- ping 放大并透明,爆开的效果
- pulse 脉动,呼吸灯一样的效果
- bounce 弹跳
<div class="animation-pulse">ikun</div>
显然这些动画是不够的,要自定义 animation 动画,则要去配置文件中配置 keyframes。并且可以在 animation 选项中像使用 css 一样声明使用 keyframes 动画。这样就可以以 animation-xxx 原子类的方式在 html 中使用动画了。
- 注意所有的配置都是 js 对象写法。
module.exports = {
theme: {
extend: {
keyframes: {
wiggle: {
'0%, 100%': { transform: 'rotate(-3deg)' },
'50%': { transform: 'rotate(3deg)' },
}
},
animation: {
wiggle: 'wiggle 1s ease-in-out infinite',
}
}
}
}
<div class="animation-wiggle">ikun</div>
如果不想在 animation 选项中配置出对应的动画工具类,也可以通过animation-[]
在 html 中像 css 那样使用:
<span
style="--i: 123"
class="
inline-block
animate-[floatDown_0.3s_calc(var(--i)*50ms)_ease]
group-hover:animate-[floatUp_0.3s_ease_calc(var(--i)*50ms)_forwards]"
>
ikun
</span>
注意:inline 元素如 span 无法应用动画,要改成 block 或者 inline-block。
配置主题
tailwind 允许在配置文件中配置主题。其实主要是两块内容:
- 修改或覆盖 tailwind 提供的主题。比如修改 tailwind 默认提供的断点分界线
- 扩展工具类,extend。
如果你想保留主题选项的默认值,但还想添加新值,请在配置文件中的 theme.extend 键下添加扩展。该键下的值将与现有的 theme 值合并,并自动成为可供你使用的新类。
例如,这里我们扩展 fontFamily 属性以添加 font-display 类,该类可以更改元素上使用的字体:
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
fontFamily: {
display: 'Oswald, ui-serif', // Adds a new `font-display` class
}
}
}
}
将其添加到主题后,你可以像任何其他字体系列工具一样使用它:
<h1 class="font-display">
This uses the Oswald font
</h1>
扩展屏幕断点:
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
screens: {
'3xl': '1600px', // Adds a new `3xl:` screen variant
}
}
}
}
<blockquote class="text-base md:text-md 3xl:text-lg">
Oh I gotta get on that internet, I'm late on everything!
</blockquote>