前置知识
什么是原子化 CSS
原子化 CSS 是一种 CSS 的架构方式,它倾向于小巧且用途单一的 class,并且会以视觉效果进行命名。
为什么使用 原子化 CSS
传统方案
制作原子化 CSS 的传统方案其实就是提供所有你可能需要用到的 CSS 工具。例如,你可能会用预处理器(这里选用的是 SCSS)生成如下代码:
// style.scss
@for $i from 1 through 10 {
.m-#{$i} {
margin: $i / 4 rem;
}
}
编译结果为:
.m-1 { margin: 0.25 rem; }
.m-2 { margin: 0.5 rem; }
/* ... */
.m-10 { margin: 2.5 rem; }
现在你可以直接使用 class="m-1"
来设置边距。但正如你所见,用这种方法的情况下,你不能使用除了 1 到 10 之外的边距,而且,即使你只使用了其中一条 CSS 规则,但还是要为其余几条规则的文件体积买单。如果之后你还想支持不同的 margin 方向,使用比如 mt
代表 margin-top
,mb
代表 margin-bottom
等,加上这 4 个方向以后,你的 CSS 大小会变成原来的 5 倍。如果再有使用到像 :hover
和 :focus
这样的伪类时,体积还会得更变大。以此类推,每多加一个工具类,往往意味着你 CSS 文件的大小也会随之增加。这也就是为什么传统的 Tailwind 生成的 CSS 文件会有数 MB 的大小。
为了解决这个问题,Tailwind 通过使用 PurgeCSS 来扫描你的打包产物并删除你不需要的规则。这得以使其在生产环境中 CSS 文件缩减为几 KB。然而,请注意,这个清除操作仅在生成构建下有效,而开发环境下仍要使用包含了所有规则巨大的 CSS 文件。这在 Webpack 中表现可能并不明显(项目过大也会有着巨大影响),但在 Vite 中却有着巨大的影响,毕竟其他内容的加载都非常迅捷。
Tailwind对比unocss
例如,我们知道 Tailwind 中的 border-2
标识边框宽度为 2px
,4
表示 4px
,6
表示 6px
,8
表示 8px
,但当你使用 border-10
却不起作用(你甚至需要一些时间来发现这件事!)。你可能会说这是故意而为之,以使得设计系统具有一致性。不如这样,我们来做个小测验,如果想要让 border-10
正常工作,应该如何做?
在你的全局样式中的某个位置添加这样一个工具类?
.border-10 {
border-width: 10px;
}
快速且直观,最重要的是,它的确解决了你的需求。但是,如果什么都需要我自己手动添加,那我们为什么还需要使用 Tailwind ?
可参考文章
重新构想原子化 CSS
UnoCSS官方中文文档 指南
自 2023 年 3 月起不再积极维护windicss官方文档 Getting Started | Windi CSS
使用unocss
在vscode编辑器中安装unocss插件 能友好的提示
npm i -D unocss
vite.config.ts
import unocss from 'unocss/vite'
plugins: [vue(), vueJsx(),unocss({
rules:[
//配置自定义规则
['U-flex', { display: "flex" }]
]
})],
main.ts 引入
import 'uno.css'
1 配置自定义规则
rules: [
['flex', { display: "flex" }]
]
<template>
<div
class="u-flex"
>
什么是原子化CSS
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
</script>
<style lang="less" scoped></style>
效果图:
2 配置动态css(使用正则表达式)
m-参数 例如 m-10 就是 margin:10px
rules: [
[/^m-(\d+)$/, ([, d]) => ({ margin: `${Number(d) * 10}px` })],
['flex', { display: "flex" }]
]
3 .shortcuts 可以自定义组合样式
plugins: [vue(), vueJsx(), unocss({
rules: [
['pink', { color: 'pink' }]
],
shortcuts: {
btn: "pink flex"
}
})],
4 unocss 预设
presets:[presetIcons(),presetAttributify(),presetUno()]
4.1.presetIcons Icon图标预设
图标集合安装
npm i -D @iconify-json/ic
首先我们去icones官网(方便浏览和使用iconify)浏览我们需要的icon,比如这里我用到了Google Material Icons图标集里面的baseline-add-circle图标
比如你想使用Element Plus的图标库 直接查询后能看到网址https://icones.js.org/collection/ep
能看到是/ep结尾的 下载命令就是
npm i -D @iconify-json/ep
不加/ep就是下载所有的图标库体积会特别大
4.2.presetAttributify 属性化模式支持
属性语义化 无须class
vite.config.ts
import { defineConfig, presetAttributify, presetUno } from 'unocss'
export default defineConfig({
presets: [
presetAttributify({ /* preset 选项 */}),
presetUno(),
// ...自定义 presets
],
rules:[]
})
<div font="black">btn</div>
<button
class="bg-blue-400 hover:bg-blue-500 text-sm text-white font-mono font-light py-2 px-4 rounded border-2 border-blue-200 dark:bg-blue-500 dark:hover:bg-blue-600"
>
未使用属性化模式支持 css Button
</button>
<button
bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
text="sm white"
font="mono light"
p="y-2 x-4"
border="2 rounded blue-200"
>
使用属性化模式支持Button
</button>
<div w20 h20 bg-blue-500>使用属性化模式支持Button 省略class后无类名提示。。。</div>
4.3.presetUno 工具类预设
tips:默认的预设是基于Windi CSS的注意margin 和border的单位是px,其他样式是rem
默认的 @unocss/preset-uno 预设是一系列流行的原子化框架的 通用超集,包括 Tailwind CSS、Windi CSS、Bootstrap、Tachyons 等。
例如,ml-3
(Tailwind CSS)、ms-2
(Bootstrap)、ma4
(Tachyons)和 mt-10px
(Windi CSS)都是有效的。
.ma4 { margin: 1rem; }
.ml-3 { margin-left: 0.75rem; }
.ms-2 { margin-inline-start: 0.5rem; }
.mt-10px { margin-top: 10px; }
4.4 Rem to px 预设
将所有工具类中的 rem 转换为 px。
pnpm add -D @unocss/preset-rem-to-px
// uno.config.ts
import { defineConfig } from 'unocss'
import presetRemToPx from '@unocss/preset-rem-to-px'
export default defineConfig({
presets: [
presetRemToPx(),
// ...other presets
],
})