Tailwind CSS v3——核心思想(三)自定义样式
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
系列文章可以查看《Tailwind》专栏
参考:
Tailwind 支持多种简单的方式添加自定义样式,例如在配置文件 tailwind.config.js
中进行配置即可自定义基础类,还有通过 top-[117px]
的方式来临时使用任意样式。此外它也支持插件,而且提供了一些官方插件,可以实现更复杂的功能。
自定义基础类
可以在配置文件 tailwind.config.js
的主题属性 theme
中定制颜色、间隔、字体、断点等基础类。而且可以通过覆写默认的预设值和扩展添加新值两种方式。
💡 所有配置都是可选的,如果基础类在配置文件中没有设置,则会使用 Tailwind 的预设值。
module.exports = {
theme: {
// 直接在 theme 属性中设置的基础类会完全覆盖原有的预设基础类
screens: {
sm: '480px',
md: '768px',
lg: '976px',
},
colors: {
'blue': '#1fb6ff',
'pink': '#ff49db',
'orange': '#ff7849',
},
fontFamily: {
sans: ['Graphik', 'sans-serif'],
serif: ['Merriweather', 'serif'],
},
// 在 theme 属性的 extend 属性下添加的基础类会以扩展添加新值的方式来添加自定义基础类
extend: {
spacing: {
'128': '32rem',
'144': '36rem',
},
borderRadius: {
'4xl': '2rem',
}
}
}
}
使用任意值
Tailwind 支持以 utility-[value]
的形式来临时使用任意样式值,其中 utility
表示基础类,后面用 -
连字符相连的,在方括号 []
中的 value
就是该样式的值。而且这种形式也支持使用状态变量,例如 hover:utility-[value]
设置在鼠标悬停时元素的样式
<!-- 将字体大小设置为 22px -->
<div class="text-[22px] lg:top-[34px]">Hello World</div>
<!-- 其中最常用的是用于设置伪元素的 content 内容 -->
<div class="before:content-['Ha']">
<!-- ... -->
</div>
💡 如果样式值需要使用空格,常见于设置简写属性的样式值时,此时需要将空格替换为下划线 _
,Tailwind 在编译时才可以正确识别再自动转换为空格。
<div class="grid grid-cols-[1fr_500px_2fr]">
<!-- ... -->
</div>
而对于那些下划线是合法值,但空格是非法的属性,如 url
则 Tailwind 在编译时会自动进行判断,不会对下划线进行转换。
<!-- 不会对下划线进行转换 -->
<div class="bg-[url('/what_a_rush.png')]">
<!-- ... -->
</div>
只有在一些特殊的情况下(下划线和空格都是合法的样式值),需要用转义符 \
显式地告知编译器不需要对自定义的样式值中的下划线进行转换
<div class="before:content-['hello\_world']">
<!-- ... -->
</div>
💡 有些基础类前缀可以用于设置不同类型的样式,例如 text-
前缀,它既有 text-lg
用以设置字体大小,也有 text-black
用以设置字体的颜色,一般 Tailwind 会自动根据方括号 [value]
内的任意值 value
的形式自动判断开发者是在设置哪一个类型样式
<!-- Will generate a font-size utility -->
<div class="text-[22px]">...</div>
<!-- Will generate a color utility -->
<div class="text-[#bada55]">...</div>
但是如果开发者是通过 CSS 变量来传递任意值的时候,而且所要设置的基础类可以对应于多种类型的样式属性时,编译器就无法预判我们实际上是要设置哪一种样式属性了,这时我们需要在 CSS 变量前添加提示 hint(以冒号 :
分隔),给编译器足够的指引
<!-- Will generate a font-size utility -->
<div class="text-[length:var(--my-var)]">...</div>
<!-- Will generate a color utility -->
<div class="text-[color:var(--my-var)]">...</div>
甚至可以用类似的形式设置任意的样式,当 Tailwind 没有相应的基础类,而且只是临时使用(不必在 Tailwind 配置文件中进行繁琐的设置),在方括号 []
中设置属性及其属性值。该方式类似行内样式 inline style,但是它还有一个优势就是可以使用状态变量,以设置特定状态下元素的样式。
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]">
<!-- ... -->
</div>
样式表添加 CSS
还有一种添加自定义样式的简单直接方式,就是在样式表中写样式了。
/* 📄 main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
.my-custom-style {
/* ... */
}
⚠️ 其中有一点值得注意的是,由于样式表中 CSS 代码的顺序对于样式的优先级影响很大,因此 Tailwind 提供了指令 @layer
用以将自定义的样式代码添加到其三个模块/容器 base
、components
、utilities
之一,这三个模块一般是依次编译到样式表中的,应该恰当地选择容器否则就有可能出现与预期不相符的样式覆盖现象。
-
base
模块包含一些重置样式 preflight,以保证网页在不同浏览器中显示保持一致。如果希望为页面整体添加一些默认的样式,例如字体 font family、标题大小等,可以将这些自定义的样式代码添加到base
容器中。💡 而一个简单的替代实现方式是将这些设置,应用到页面的根元素
<html>
或<body>
元素中,而不需要在样式表中写代码。@tailwind base; @tailwind components; @tailwind utilities; @layer base { h1 { font-size: 1.5rem; } h2 { /* 可以在样式表中通过指令 @apply 使用基础类来设置样式 */ @apply text-xl; } /* ... */ }
-
components
模块十分简单,它包含的是一个类名为container
类的样式。一般在该容器中添加复杂的样式,以应用于页面的一些视觉组件上,如按钮、表单、卡片等。💡 如果希望在样式表中使用 Tailwind 的基础类(所对应的样式)可以使用
@apply
,如果希望引用基础类预设的样式值可以使用theme()
函数/* 📄 main.css */ @tailwind base; @tailwind components; @tailwind utilities; @layer components { .card { /* 通过 theme() 函数可以使用基础类的某个样式值 */ background-color: theme('colors.white'); border-radius: theme('borderRadius.lg'); padding: theme('spacing.6'); box-shadow: theme('boxShadow.xl'); } .select-dropdown { /* 通过 @apply 可以使用基础类所对应的样式 */ @apply rounded-b-lg shadow-md; } /* ... */ }
-
utilities
模块包含的是原子化的样式(每一个基础类都只实现一个基础的样式功能),应该最后加载的。这样在其中定义的样式就有最高的优先级,即确保基础类应用到 HTML 页面时,可以覆盖其他样式。<!-- Will look like a card, but with square corners --> <div class="card rounded-none"> <!-- ... --> </div>
在该容器中定义的样式应该是 low level 单一功能的样式
@tailwind base; @tailwind components; @tailwind utilities; @layer utilities { .content-auto { content-visibility: auto; } }
💡 所有使用 @layer
添加的样式,它们的类名在应用到 HTML 页面时,也像 Tailwind 内置的基础类一样,都支持使用状态变量(这是使用普通方式添加的样式所不具有的优势)
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.content-auto {
content-visibility: auto;
}
}
<div class="lg:dark:content-auto">
<!-- ... -->
</div>
💡 而且使用指令 @layer
添加自定义样式,也会在编译时自动进行简化 purge 处理,只有在 HTML 页面的元素中使用了类名,相应的自定义样式才会被编译到最终的样式表中。如果希望自定义的样式最后总是编译到样式表中,则可以不使用指令 @layer
直接写在主样式表中(也需要注意 CSS 代码添加的顺序,一般应该保证 @tailwind utilities
模块最后引入)
@tailwind base;
@tailwind components;
/* This will always be included in your compiled CSS */
.card {
/* ... */
}
@tailwind utilities;
⚠️ 如果使用多个样式表,并希望在其中使用了指令 @layer
将某些自定义的样式插入到指定的容器中,则需要先将这些样式表导入到主样式表(带有指令 @tailwind
的样式表),然后再执行编译操作,否则会触发 @layer
无法配对 @tailwind
指令的错误。
可以使用 postcss-import
插件来进行预处理。在终端输入以下命令安装 postcss-import
插件依赖包
npm install -D postcss-import
然后在 PostCSS 配置文件 postcss.config.js
声明插件
// 📄 postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
]
}
然后就可以在不同的样式表的顶部导入所依赖的 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;
}
/* components.css */
@import "./components/buttons.css";
@import "./components/card.css";
💡 在主样式表中,如果希望导入的模块和 Tailwind 的模块有先后次序,也可以使用 @import
的方式导入 Tailwind 的三个模块(而不使用 @tailwind
指令来导入,因为 @import
指令必须在样式表的顶部)
/* 📄 main.css */
@import "tailwindcss/base";
@import "./custom-base-styles.css";
@import "tailwindcss/components";
@import "./custom-components.css";
@import "tailwindcss/utilities";
@import "./custom-utilities.css";
⚠️ 使用 Vue、React 等前端框架,在单文件组件文档中,支持使用 <style>
标签来为组件添加样式,在其中也可以使用 @apply
来提取其模板中的基础类组合,但是不支持使用指令 @layer
将自定义的样式添加到指定的容器,因为每一个单文件组件的 <style>
标签内的样式都是独立编译的,它们无法读取其他样式表的信息,也就无法指定到主样式表的容器中,这只会让我们失去控制自定义的样式(与 Tailwind 的默认样式)的优先级。
插件添加 CSS
还可以通过编写插件来添加自定义样式(而不是使用样式表)。在 Tailwind 的配置文件 tailwind.config.js
中引入 tailwindcss/plugin
模块的 plugin
方法创建插件。它提供了一些钩子函数,用以将自定的样式添加到 base
、components
或 utilities
中
// 📄 tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
// ...
plugins: [
plugin(function ({ addBase, addComponents, addUtilities, theme }) {
addBase({
'h1': {
fontSize: theme('fontSize.2xl'),
},
'h2': {
fontSize: theme('fontSize.xl'),
},
})
addComponents({
'.card': {
backgroundColor: theme('colors.white'),
borderRadius: theme('borderRadius.lg'),
padding: theme('spacing.6'),
boxShadow: theme('boxShadow.xl'),
}
})
addUtilities({
'.content-auto': {
contentVisibility: 'auto',
}
})
})
]
}
转载自:https://juejin.cn/post/7072173663851642893