核心概念 Core Concepts
功能类优先 Utility-First Fundamentals
在一组受约束的原始功能类的基础上构建复杂的组件。
受约束 (设计)
原子功能类(可组合) (原子化css)
使用传统方式时,定制的设计需要定制的 CSS
使用功能类构建自定义设计而无需编写 CSS
与传统css方式
优点:
- 不用浪费大量精力给类命名
- css 文件不用一直增长。使用传统方法,每次添加新功能css 文件都会变大。使用功能类,所有内容可重用,几乎不需要编写新的css。 tree-shaking 后,压缩后css体积可以达到10kb以下。
- 更改安全。 css 全局的,更改css文件可能会影响其他。通过更改html中的类修改样式,不用担心会影响到其他。
与传统内联样式
优点:
基于约束的设计。
功能类是从预定义的设计系统中选择样式,构建的ui 更统一。内联样式,样式任意设置。响应式的设计。
内联样式不能使用媒体查询,但 Tailwind 可通过响应式功能类(responsive utilities) 构建响应式的界面。
sm:py-4 sm:flex sm:items-center
Hover, focus, 以及其它状态变体。
内联样式无法设置 hover 或者 focus 这样的状态, 但 Tailwind 的状态变体(state variants)使用功能类可以非常容易的为这些状态设置样式。
hover:text-white hover:bg-purple-600
可维护性问题
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"></button>
管理常用的重复的功能类组合
通过提取组件(通常作为模板片段或者组件)鹤 利用编辑器和语言特点循环。
维护功能优先的css 项目比维护大型css 代码库容易。html比css维护容易得多。
响应式设计 (变体)
Tailwind 中的每个功能类都可以有条件的应用于不同的断点(breakpoints)。
在html中通过添加响应式变体前缀 + 功能类,实现不同分辨率设备上属性样式切换。
根据常用的设备分辨率方案,默认内置了 5 个断点:
断点前缀 | 最小宽度 | CSS |
---|---|---|
sm | 640px | @media (min-width: 640px) { ... } |
md | 768px | @media (min-width: 768px) { ... } |
lg | 1024px | @media (min-width: 1024px) { ...} |
xl | 1280px | @media (min-width: 1280px) { ...} |
2xl | 1536px | @media (min-width: 1536px) { ...} |
<img class="w-16 md:w-32 lg:w-48" src="...">
移动优先:这意味着未加前缀的功能类 (像 uppercase) 在所有的屏幕上都有效,而加了前缀的功能类(如 md:uppercase)仅在指定断点及以上的屏幕上生效。 默认为min-width
定位移动设备 为移动设备设计样式,应使用无前缀的功能类,而不是带
sm:
前缀的,sm
是在小断点处,而不是在小屏幕上。
注意:× 不要用sm: 定位移动设备,√ 应该使用无前缀的功能类来定位移动设备,并在较大的断点处覆盖推荐做法: 先为移动设备布局,然后在其他断点处覆盖更改
定位单个断点 tailwind的断点只有min-width, 没有max-width; 这意味着在较小的断点上添加 的任何功能类都将在更大的断点上生效。
如果只想在一个断点上应用某个功能类,解决方案是在更大的断点上添加另一个功能类,用来抵消前一个功能类的效果。
<div class="bg-green-500 md:bg-red-500 lg:bg-green-500">
<!-- ... -->
</div>
tailwindcss 中 断点可实现重写、扩展、设置pc优先、多范围断点、完全自定义媒体查询(css媒体查询)。
配置屏幕尺寸时 注意顺序
断点:https://www.tailwindcss.cn/docs/breakpoints
version: 3.1.7
设置hover、focus 等样式(修饰符)
使用功能类设置hover、focus等元素样式。
通过在类名的前面添加一个相对应状态的修饰符,设置该状态下的样式。 tailwind中的每个功能类能被条件性地设置。
input: hover:bg-purple-700
output:
.hover\:bg-purple-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(126 34 206 / var(--tw-bg-opacity));
}
<form>
<input class="border border-transparent focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent ...">
<button class="bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 ...">
Sign up
</button>
</form>
与传统css 添加相比
hover 传统写法 需要设置指定类名,然后给类名添加hover 状态设置样式。 hover tailwind中,在html 中添加hover状态样式,该样式在默认况下,不会生效。
This is what we mean when we say a utility class can be applied conditionally — by using modifiers you can control exactly how your design behaves in different states, without ever leaving your HTML.
多种修饰可叠加 在同一个功能类
dark:md:hover:bg-fuchsia-600
多个修饰符叠加 调用是由内到外。
// These modifiers:
`dark:group-hover:focus:opacity-100`
// ...are applied like this:
dark(groupHover(focus('opacity-100')))
注意一些特殊叠加顺序 例如dark
的顺序,
如果dark 模式为class dark类需要设置在html 上,dark 应该设置在最外层才起作用。
/* dark:group-hover:opacity-100 */
.dark .group:hover .dark\:group-hover\:opacity-100 {
opacity: 1;
}
/* group-hover:dark:opacity-100 */
.group:hover .dark .group-hover\:dark\:opacity-100 {
opacity: 1;
}
修饰符 种类
伪类
伪元素
媒体查询
属性选择
特殊变体(dark, 响应式变体)
自定义变体 [&:nth-child(3)]:
、 addVariant plugin API
<li class="[&:nth-child(3)]:underline">{item}</li>
If you need spaces in your selector, you can use an underscore. You can also use at-rules like @media or @supports in arbitrary variants
<button type="button" class="[@media(any-hover:hover){&:hover}]:opacity-100">
<!-- ... -->
</button>
let plugin = require('tailwindcss/plugin')
module.exports = {
// ...
plugins: [
plugin(function ({ addVariant }) {
// Add a `third` variant, ie. `third:pb-0`
addVariant('third', '&:nth-child(3)')
})
]
}
这些修饰符 也可以作用在自定义的类中,使用layers 与 plugin 添加的自定义功能类。
深色模式
Tailwind 包含一个 dark 变体,当启用深色模式时,您可以为您的网站设置不同的样式。
默认情况下,使用prefers-color-scheme
用户偏好设置,也可使用class 模式手动设置切换暗黑模式。
class 模式需要在html 标签添加dark 类名,如果配置了prefix,dark 也需要加前缀。
// tailwind.config.js
module.exports = {
darkMode: 'media', // prefers-color-scheme
// darkMode: 'class' // <html class="dark"></html> class 模式,可手动切换模式
// darkMode: ['class', '[data-mode="dark"]'] // 使用自定义的dark 模式选择器名称设置
// ...
}
js 判断系统偏好
window.matchMedia('(prefers-color-scheme: dark)').matches
样式复用
多光标编辑
循环遍历
创建组件/模板片段
不要根据css 类提取复杂组件。要使用模板片段或者js组件, HTML结构与css一起结合。通过
@apply
提取类 (不提倡多使用,适用按钮,表单控件等小且高度可复用的组件)
不要过早抽象,为了看起来干净整洁过早使用@apply,虽然html模板中充斥着tailwind类难看,但是在大量自定义css项目中进行更改更糟糕。
如果过渡使用@apply 违背tailwind初衷,造成命名困难,维护困难,css bundle 变大等问题。
自定义与扩展
自定义主题 tailwind.config.js -> theme
使用任意值
使用任意值 class="text-[f60]"
.text-\[\#f60\] {
--tw-text-opacity: 1;
color: rgb(255 102 0 / var(--tw-text-opacity));
}
如果多处使用 class="text-[f60]"
css 文件只生成一个
使用任意属性
<div class="[mask-type:luminance]"><div>
也可用于设置css 变量: <div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]"></div>
可以添加各种修饰符
任意变量使用语法
[]
需要空格时候 用
_
代替 有些下划线转义成空格无效的情况下,tailwind 会保留下划线,不会转换成空格需要使用下划线时候
_
使用反斜杠转义下划线<h1 class="before:content-['hello\_world']">测试文字</h1>
解析模糊歧义属性值 text-black 与 text-lg 都是
text-
命名,但分别表示color 与 font-size。如果通过[]
设置值 会自动根据传入的值判断生成什么类。如果传入的是变量或者难以判断传入的css值属于哪种类型,可以在值之前添加css数据类型来提示。 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
<!-- 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>
@layer 使用@layer指令在css 中添加自定义样式
@layer
指令 通过自动将样式定位到相应的@tailwind 指令来控制声明顺序,并且能够为自定义的css 启用修改器与tree-shaking等功能。
3 个不同的层:base | components | utilities
base: 重置和默认样式
/* 注意顺序 */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
/* ... */
}components: 基于类的样式
utilities: 小的、单一功能类,层级应始终优先于其他样式,方便覆盖
任何添加到
base
,components
, orutilities
layers的样式,会启用tree-shaking, 只有在被使用监测到时候才会被编译到css bundle中。如果有不想被tree-shaking 移除的未使用到的样式(js 特殊设置等)不要使用
@layer
. 注意样式定义位置 如果是自定义组件类需要编写在组件下面, 功能类上面, 确保原子类的优先级大于组件类。
使用多个css文件
写多个css 文件时候,需要每个css文件都注入@tailwind...层 ,不然,使用@layer @variants
之类的就会报错;
可以通过 postcss-import
插件帮助解决@import 导入问题,但是@import 被要求放在文件顶部, 这样生成的bundle样式顺序就会可能存在问题。
https://tailwindcss.com/docs/using-with-preprocessors#build-time-imports
推荐做法
@import "tailwindcss/base";
@import "./custom-base-styles.css";
@import "tailwindcss/components";
@import "./custom-components.css";
@import "tailwindcss/utilities";
@import "./custom-utilities.css";
layers 和 per-component CSS(组件内<style>
块)
组件内<style>
中不能使用 @layer
能使用theme(), 但不推荐样式写在组件的style 中,而是推荐写在html行内
使用插件
也可以使用插件添加自定义样式。
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',
}
})
})
]
}
函数与指令
tailwind 暴露在css 中的函数与指令。
指令
自定义的 tailwind中
@
规则,可以在css 中提供特定功能。
@tailwind
插入
base
,components
,utilities
andvariants
样式。(注意注入位置顺序与生成的css样式作用位置)
/**
* 注入 重置样式/默认样式 和 通过插件注册的base styles
*/
@tailwind base;
/**
* 注入 组件类 和 通过插件注册的 component classes
*/
@tailwind components;
/**
* 注入原子功能类 和 通过插件注册的 utility classes
*/
@tailwind utilities;
/**
*控制各种变体/修饰符的注入位置, 如果忽略 tailwind 默认插入这些修饰类 在样式表最后面
*/
@tailwind variants;
@layer
声明自定义样式时候,指明属于是哪层的css, Tailwind会自动将样式移到
@tailwind
相对应的该层插入位置,而不用担心自定义样式的编写位置。
通过@layer
添加的自定义样式,(tree-shaking自动生效) 只有在HTML的中使用了才会被打包到bundle 中,与默认classes 一样。
通过@layer
添加的自定义样式,(modifiers自动生效) 可以添加修饰类前缀。
@apply
将现有的功能类内联到自定义的css 中。
如果自定义的css中想添加tailwind 中的设计的功能类。可以使用@apply
通过@apply
内联的规则,默认移除!important
避免特殊问题。
@layer components {
.test-imp {
@apply red;
color: blue;
}
}
@layer utilities {
.red {
color: red !important;
}
}
/* 输出 red 的!important 已移除,被后面的 blue 覆盖 */
.test-imp {
color: red;
color: blue;
}
可以将!important
添加在 @apply
后面
.test-imp {
@apply red !important;
color: blue;
}
/* 输出 */
.test-imp {
color: red !important;
color: blue;
}
如果是使用Sass/SCSS, 需要使用其自己的插值特点生效。
@apply
与 per-component CSS
像Vue和Svelte 等组件框架支持在每个组件文件中的<style>
块中添加样式。 如果你在这些组件的<style>
块中使用@apply
来使用全局css中定义的自定义类,将报错不存在该类。
这是因为在底层,像Vue和Svelte 等框架是独立处理每个<style>
块,并且针对每个块单独运行postcss插件。
这意味着如果你有10个组件且每个组件都有一个<style>
块, tailwind 将会被独立运行10次,并且相互没有关联,没有影响。
因此当你想要在组件的css块中使用@apply
引用在全局自定义的类时候,会报错,因为Tailwind在当前组件的css 中找不到自定义的全局类,因为Tailwind 处理当前组件css 与 全局main.css
是完全隔离的。
解决方案就是通过plugins添加全局自定义类,这样Tailwind 处理任何 使用到此配置文件的文件都可以访问这些样式。但是最好是不要有这些奇怪的行为。
Functions
Tailwind 提供一些自定义函数,你可以在css通过这些函数来访问Tailwind中设定的特定的值。 这些函数在构建时进行评估,在最终css中被静态值替换。
theme()
使用
.
或者[]
,访问Tailwind 配置值。
.content-area {
height: calc(100vh - theme(spacing.12));
}
/* 带 . 的值 可以使用 [] 访问 */
.content-area {
height: calc(100vh - theme(spacing[2.5]));
}
/* 不要用下划线访问color值 颜色是嵌套object语法定义的 */
.btn-blue {
background-color: theme(colors.blue.500);
}
/* 设置颜色不透明度 可以通过斜线 + opacity值 设置 */
.btn-blue {
background-color: theme(colors.blue.500 / 75%);
}
screen()
在css中写媒体查询时候,可以用断点名称,设定屏幕范围值。它将在构建时解析该断点下的屏幕值,生成与断点匹配的媒体查询。
@media screen(sm) {
/* ... */
}
/* 输出 */
@media (min-width: 640px) {
/* ... */
}