每个前端人都经历过的一个痛处就是,在写页面ui样式时不停的在html文件(或代码区域)和css文件(或代码区域)之间来回切换,这种聚焦点分离让ui样式的开发有点点烦。原子化css正是这一痛处的有效的解决方案。
简介
原子化的优点也即原子化,因为所有书写的css都是以最原子的形态出现,所以可复用性无解肥。
原子化中每个css属性和值都有一个对应简写的class来实现,通常这些简写也符合认知规律,所以书写起来并没有很大心智负担,熟能生巧(唯手熟耳)。
这有点类似在 html 中书写 style,不过更加简单和快捷。比如:
w-10
就是width: 100px
mx-10
就是margin-left: 10px; margin-right: 10px;
last-mr-0
就是:last-child { margin-right: 0; }
而且通过自定义规则配置,还能实现更多的简写,如:
wh-full
就是width: 100%; height: 100%
bb-1-red
就是border-bottom: 1px solid red;
f-b
就是display: flex; justify-content: space-between; align-items: center;
在实际应用中代码如下:
<div class="inline-block h-164 bg-#F2F3F5 rounded-4 p-20 pt-16!">
<div class="mb-8 text-14 text-#7A8699">示例(请按照示例上传真实、有效的集装箱照片):</div>
<div class="f-s">
<div class="relative w-100 h-100 mr-8 last-mr-0" v-for="item in sampleBoxPics" :key="item.id">
<img class="wh-full object-cover" :src="`https://filecdn.xxx.com/xxx/box_pic_${item.id}.png`" alt="" />
<div class="absolute bottom-0 w-full f-c bg-#1D2129/80 text-white text-12">{{ item.name }}</div>
</div>
</div>
</div>
安装配置(vue + vite 项目中):
安装 unocss 和工具类预设:
pnpm i -D unocss @unocss/preset-uno
在main.ts中引入uno.css
import { createApp } from 'vue'
import App from './App.vue'
import 'virtual:uno.css'
createApp(App).mount('#app')
在 vite.config.ts 文件中配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [
vue(),
UnoCSS(),
],
...
})
新建 uno.config.ts 文件并配置(此处是我个人的配置偏好,可以根据喜好自己配置,或者根据项目需要配置一些常用公共样式):
// uno.config.ts
import { defineConfig, presetUno } from 'unocss'
import presetRemToPx from '@unocss/preset-rem-to-px'
export default defineConfig({
presets: [
presetUno(),
// unocss 默认rem,转成px
presetRemToPx({
baseFontSize: 4,
}) as any,
],
shortcuts: {
'f-b': 'flex justify-between items-center',
'f-c': 'flex justify-center items-center',
'f-s': 'flex justify-start items-center',
'f-e': 'flex justify-end items-center',
'text-overflow': 'truncate',
'wh-full': 'w-full h-full',
},
rules: [
[/^b-(\d+)$/, match => ({ 'border-width': `${match[1]}px` })],
[/^b-(\d+)-#([\w]+)$/, match => ({ 'border': `solid ${match[1]}px #${match[2]}` })],
[/^bt-(\d+)-#([\w]+)$/, match => ({ 'border-top': `solid ${match[1]}px #${match[2]}` })],
[/^bb-(\d+)-#([\w]+)$/, match => ({ 'border-bottom': `solid ${match[1]}px #${match[2]}` })],
[/^bl-(\d+)-#([\w]+)$/, match => ({ 'border-left': `solid ${match[1]}px #${match[2]}` })],
[/^br-(\d+)-#([\w]+)$/, match => ({ 'border-right': `solid ${match[1]}px #${match[2]}` })],
[/^px-(\d+)$/, match => ({ 'padding-left': `${match[1]}px`, 'padding-right': `${match[1]}px` })],
[/^py-(\d+)$/, match => ({ 'padding-top': `${match[1]}px`, 'padding-bottom': `${match[1]}px` })],
[/^mx-(\d+)$/, match => ({ 'margin-left': `${match[1]}px`, 'margin-right': `${match[1]}px` })],
[/^my-(\d+)$/, match => ({ 'margin-top': `${match[1]}px`, 'margin-bottom': `${match[1]}px` })],
[/^pt-(\d+)$/, match => ({ 'padding-top': `${match[1]}px` })],
[/^pb-(\d+)$/, match => ({ 'padding-bottom': `${match[1]}px` })],
[/^pl-(\d+)$/, match => ({ 'padding-left': `${match[1]}px` })],
[/^pr-(\d+)$/, match => ({ 'padding-right': `${match[1]}px` })],
[/^mt-(\d+)$/, match => ({ 'margin-top': `${match[1]}px` })],
[/^mb-(\d+)$/, match => ({ 'margin-bottom': `${match[1]}px` })],
[/^ml-(\d+)$/, match => ({ 'margin-left': `${match[1]}px` })],
[/^mr-(\d+)$/, match => ({ 'margin-right': `${match[1]}px` })],
],
})
vscode 还有 UnoCSS 扩展,可以预览编译后的class:
演练
有兴趣的少侠可以点击 此处 进行在线演练,零配置体验unocss。
也可以在 这里 查看类名书写后编写的结果。
而我最常用的其实是 tailwindcss文档,在这里可以查看各种css属性的书写方式(unocss是兼容tailwindcss的,而unocss官网貌似并没有提供此类文档)。
缺点
原子化css在编写复杂的样式效果时,会造成 html 的 class 名非常长,而且 vue react 等框架中,都会有部分 js 逻辑注入 html 中,这样 html 文件会变得臃肿不堪。
原子化css违背了组件化的设计思想,比如你用unocss写了一个组件,后来发现比较通用想发包就比较麻烦了。
维护项目时,不再可以通过 css 名来定位代码位置,接手陌生项目时会比较痛苦。
最后
虽然存在很多问题,但是原子化带来的好处是无可比拟的。而且他让你的项目避免了很多重复混乱的css命名。