《Vue项目开发实战》第三章:UNOCSS与样式化定义
系列文章
《Vue项目开发实战》
https://blog.csdn.net/sen_shan/category_13075264.html
第二章:API接口与请求封装
https://blog.csdn.net/sen_shan/article/details/154638778
文章目录
目录
系列文章
文章目录
前言
安装
Vite 配置
配置文件
入口引入
项目引用
Styles
前言
本文详细介绍了Vue项目中UnoCSS的配置和使用方法,包括安装步骤、Vite配置、样式管理方案等。
重点内容有:
1)通过uno.config.ts文件配置UnoCSS预设和快捷方式;
2)建立原子化CSS文件(如_color-btn.css)统一管理Element-Plus组件样式;
3)使用CSS变量定义语义色板,实现主题切换和一键改色;
4)优化表格行颜色规则,解决Element默认样式问题。
文中提供了完整的代码示例,可帮助开发者快速实现样式统一管理和主题定制。
安装
npm i -D unocss
# 可选:图标、属性化、排版预设
npm i -D @unocss/preset-icons @unocss/preset-attributify @unocss/preset-typography
Vite 配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
export default defineConfig({
plugins: [vue(), UnoCSS()],
})
本项目配置文件如下:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
import * as path from 'path';
// https://vite.dev/config/
export default defineConfig({plugins: [vue(), UnoCSS()],resolve: {alias: {'@': '/src', // 配置 @ 别名指向 src 目录 '@config': path.resolve(__dirname, './config'), // ← 新增}},})
配置文件
项目根目录建立 uno.config.ts文件
import { defineConfig } from 'unocss'
import presetUno from '@unocss/preset-uno'
import presetIcons from '@unocss/preset-icons'
import presetAttributify from '@unocss/preset-attributify'export default defineConfig({presets: [presetUno(), presetIcons(), presetAttributify()],shortcuts: { btn: 'py-2 px-4 bg-blue-500 text-white rounded hover:bg-blue-600' },rules: [['m-1', { margin: '0.25rem' }]],theme: { colors: { primary: '#3b82f6' } }
})
入口引入
调整main.ts
import '@unocss/reset/tailwind.css' // 可选重置
import 'uno.css'
项目引用
<template><div class="p-4 bg-primary text-white rounded-lg shadow hover:shadow-xl transition"><div class="i-carbon-sun text-2xl mr-2" /> <!-- 图标 -->Hello UnoCSS + Vue3!</div><button class="btn mt-4">快捷按钮</button>
</template>
按照以上配置后,按钮默认变白,悬停才显蓝,针对此问题如如下调整
Styles
建立以下文件统一管理样式:
src\assets\atomic\_color-bg.css
src\assets\atomic\_color-border.css
src\assets\atomic\_color-btn.css
src\assets\atomic\_color-row.css
src\assets\atomic\_color-text.css
src\assets\atomic\_flex.css
src\assets\vars\_color-vars.css
src\assets\index.css
其中 _color-btn.css 内容如下:
/**** 按钮颜色***//* 直接覆盖 Element Plus 默认样式 */
/* 极简版 */
.el-popper {background: #eff1f3 !important;color: #000000 !important;font-style: italic !important;border-radius: 16px !important; /* 推荐:圆润但不失稳重 */
}
.el-popper .el-popper__arrow::before {border-radius: 2px !important; /* 让箭头根部也圆润 */
}
/* 让 EL 按钮 primary 恢复官方蓝 */
.el-button.el-button--primary {background-color: var(--el-color-primary) !important;border-color: var(--el-color-primary) !important;color: #fff !important;
}
.el-button.el-button--primary:hover {background-color: var(--el-color-primary-light-3) !important;border-color: var(--el-color-primary-light-3) !important;
}
/* 恢复 danger 按钮红色 */
.el-button.el-button--danger {background-color: var(--el-color-danger) !important;border-color: var(--el-color-danger) !important;color: #fff !important;
}
.el-button.el-button--danger:hover {background-color: var(--el-color-danger-light-3) !important;border-color: var(--el-color-danger-light-3) !important;
}
/* 禁用 danger → 官方浅红 */
body .el-button.el-button--danger.is-disabled,
body .el-button.el-button--danger:disabled {background-color: var(--el-color-danger-light-8) !important;border-color: var(--el-color-danger-light-6) !important;color: var(--el-color-danger) !important;opacity: 0.6;
}/* 禁用 primary → 官方浅蓝 */
body .el-button.el-button--primary.is-disabled,
body .el-button.el-button--primary:disabled {background-color: var(--el-color-primary-light-8) !important;border-color: var(--el-color-primary-light-6) !important;color: var(--el-color-primary) !important;opacity: 0.6;
}/* ========== 基础按钮 ========== */
body .el-button.el-button--default {background-color: var(--el-button-bg-color) !important;border-color: var(--el-button-border-color) !important;color: var(--el-button-text-color) !important;
}
body .el-button.el-button--default:hover {background-color: var(--el-button-hover-bg-color) !important;border-color: var(--el-button-hover-border-color) !important;color: var(--el-button-hover-text-color) !important;
}
body .el-button.el-button--default.is-disabled,
body .el-button.el-button--default:disabled {background-color: var(--el-button-disabled-bg-color) !important;border-color: var(--el-button-disabled-border-color) !important;color: var(--el-button-disabled-text-color) !important;opacity: var(--el-disabled-opacity);
}/* ========== 成功按钮 ========== */
body .el-button.el-button--success {background-color: var(--el-color-success) !important;border-color: var(--el-color-success) !important;color: #fff !important;
}
body .el-button.el-button--success:hover {background-color: var(--el-color-success-light-3) !important;border-color: var(--el-color-success-light-3) !important;
}
body .el-button.el-button--success.is-disabled,
body .el-button.el-button--success:disabled {background-color: var(--el-color-success-light-8) !important;border-color: var(--el-color-success-light-6) !important;color: var(--el-color-success) !important;opacity: 0.6;
}/* ========== 信息按钮 ========== */
body .el-button.el-button--info {background-color: var(--el-color-info) !important;border-color: var(--el-color-info) !important;color: #fff !important;
}
body .el-button.el-button--info:hover {background-color: var(--el-color-info-light-3) !important;border-color: var(--el-color-info-light-3) !important;
}
body .el-button.el-button--info.is-disabled,
body .el-button.el-button--info:disabled {background-color: var(--el-color-info-light-8) !important;border-color: var(--el-color-info-light-6) !important;color: var(--el-color-info) !important;opacity: 0.6;
}/* ========== 警告按钮 ========== */
body .el-button.el-button--warning {background-color: var(--el-color-warning) !important;border-color: var(--el-color-warning) !important;color: #fff !important;
}
body .el-button.el-button--warning:hover {background-color: var(--el-color-warning-light-3) !important;border-color: var(--el-color-warning-light-3) !important;
}
body .el-button.el-button--warning.is-disabled,
body .el-button.el-button--warning:disabled {background-color: var(--el-color-warning-light-8) !important;border-color: var(--el-color-warning-light-6) !important;color: var(--el-color-warning) !important;opacity: 0.6;
}
该样式把 Element-Plus 所有类型按钮(primary、success、warning…)在默认、悬停、禁用三种状态下的背景色、边框色、文字色一次性还原成官方设计变量,解决之前按钮变白的问题;同时把 popper 改成浅灰圆角斜体,保持视觉统一
_color-row.css 文件如下:
/* 表格行专用,覆盖 Element/Bootstrap 默认背景 *//* 1. 明显反差灰度 */
.row-gray-50 { background-color: #f2f2f2 !important; }
.row-white { background-color: #ffffff !important; }
/* 2. 关闭 Element 自带的淡入淡出,避免视觉拖影 */
.el-table__row > td { transition: background-color 0s !important; }
/* ========== 状态高亮(整行) ========== */
.el-table__row:hover > td.row-gray-50 { background-color: #c9c9c9 !important; } /* 深 20% */
.el-table__row:hover > td.row-white { background-color: #e6e6e6 !important; } /* 浅灰 15% */.el-table__row.row-success > td {background-color: var(--c-success-50, #d4f7d4) !important;
}
.el-table__row.row-primary > td {background-color: var(--c-info-50, #d4e6f7) !important;
}/* ========== 奇偶纹(只在无状态时生效) ========== */
.el-table__row.bg-gray-50:not(.row-success):not(.row-primary) > td {background-color: #fafafa !important;
}
.el-table__row.bg-white:not(.row-success):not(.row-primary) > td {background-color: #ffffff !important;
}/* ========== hover(状态行也一起变) ========== */
.el-table__row:hover > td {transition: background-color 0.2s;filter: brightness(0.95); /* 统一加深,无需单独写两行 */
}
“ Element 表格的行颜色”
既能手动给整行刷灰/白/状态色,又能在鼠标悬停时一键加深,同时把 Element 自带的过渡动画关掉,避免拖影闪屏。
逐句拆解功能:
1. row-gray-50 / row-white
给 <td> 挂这个 class,行立即变成 #f2f2f2 或纯白,用来做静态反差。
2. .el-table__row > td { transition: background-color 0s !important; }
强制取消 Element 默认的 200ms 背景渐变动效,解决快速滚屏时出现的“拖尾”或“闪灰”。
3. .el-table__row:hover > td.row-gray-50 …
当行本身已有“灰/白”标记时,悬停再把背景加深 15~20%,保持可读性。
4. .row-success / .row-primary
整行状态色,统一用项目 CSS 变量(缺省值分别为淡绿、淡蓝),业务只需给 <tr> 加对应 class 即可高亮成功/主要记录。
5. .bg-gray-50 / .bg-white 的“奇偶纹”规则
只有“未被状态行占用”的行才生效,用来做斑马线,避免和 success/primary 高亮冲突。
6. 最后的通用 hover
任何行(含已标记灰、白、状态色)悬停时:
先恢复 0.2s 过渡,让加深过程更顺滑;
再用 filter: brightness(0.95) 统一压暗 5%,省得为每种背景都写一条加深色值。
一句话总结:
“关动画、给静态色、留悬停加深、状态优先”,让表格行颜色既听话又不出拖影。
_color-vars.css
:root {/* 语义色 */--c-success: #52c41a;--c-info: #1890ff;--c-warning: #faad14;--c-error: #ff4d4f;--c-primary: #1890ff; /* 与 info 可分开 *//* 深浅梯度(可按 50-900 命名法继续加) */--c-success-50: #f6ffed;--c-success-100: #d9f7be;--c-info-50: #e6f7ff;--c-info-100: #bae7ff;/* …… */
}
语义色板 CSS 变量
版本:v1.0
适用范围:全站统一配色、主题切换、组件库二次封装
一、设计目标
1. 用变量名表达“用途”而非“色值”,实现“一处改色、全站生效”。
2. 与 Element-Plus / Ant Design 官方色板保持 1:1 映射,降低迁移成本。
3. 支持深浅梯度,兼顾“品牌主色”与“无障碍对比度”。
二、变量命名规范
--c-{语义}-{亮度}
│ │ └─ 可选,50/100…900,数字越大越深
│ └─ success | info | warning | error | primary
└─ c = color 缩写,防止与组件私有变量冲突
index.css内容:
/* 变量必须先引 */
@import './vars/_color-vars.css';/* 再引原子类 */
@import './atomic/_color-btn.css';
@import './atomic/_color-bg.css';
@import './atomic/_color-text.css';
@import './atomic/_color-border.css';
@import './atomic/_color-row.css';
@import './atomic/_flex.css';
main.ts引用
import '@/assets/styles/index.css';
