uni-scss 全局辅助样式库解析:hello-uniapp 中的颜色、间距、圆角与按钮体系
uni-scss 全局辅助样式库解析:hello-uniapp 中的颜色、间距、圆角与按钮体系
uni-scss(又名 uni-sass)是 uni-ui 生态提供的一套全局 SCSS 辅助样式库,通过简单的类名与 Sass 变量即可完成颜色、边距、圆角、阴影、文本排版等常见布局操作。本文以 hello-uniapp 仓库中 uni_modules/uni-scss 的实际源码为主线,从版本演进、目录结构、变量体系、类名生成机制到 demo 应用逐层拆解,读完你可以掌握这套样式库的设计思路,并能在自己的 uni-app 项目中直接引用、覆写与定制主题。
一、版本演进:从 1.0.0 到 1.0.3 的变更脉络
uni_modules/uni-scss/changelog.md 完整记录了这套样式库的发布历史,是理解其能力边界与兼容性要求的第一手资料:
| 版本 | 发布日期 | 变更内容 | 影响面 |
|---|---|---|---|
| 1.0.0 | 2021-11-18 | 初始版本发布(init) | 建立变量体系与辅助类名体系 |
| 1.0.1 | 2021-11-22 | 修复 vue3 中 scss 语法兼容问题 | Vue3 工程可正常编译 SCSS |
| 1.0.2 | 2021-11-22 | 修复 / 符号在 vue 不同版本兼容问题引起的报错 |
根因是 SCSS 除法运算符在新旧 dart-sass / node-sass 中的写法差异 |
| 1.0.3 | 2022-01-21 | 优化组件示例 | 与 uni-ui 各组件联调演示更完整 |
值得注意的是 1.0.2 的修复点:/ 作为除法符号在 Sass 不同版本中的处理并不一致,新版本 Sass 已废弃裸除法并要求使用 math.div()。这一点在源码中留有佐证——styles/setting/_variables.scss 文件顶部被注释掉的 // @use "sass:math"; 以及 // 'sm': math.div($uni-radius-root, 2),说明开发者保留了迁移痕迹,圆角档位中 sm 档也因此暂未开放。
从 package.json 还可以确认工程约束:该模块的 engines.HBuilderX 要求 ^3.1.0,即需要 HBuilderX 3.1.0 及以上版本才能获得完整的编译支持;同时其 uni_modules 平台声明显示,Vue2 / Vue3 均支持,H5(含 PC 端 Chrome、IE、Edge、Firefox、Safari 与移动端浏览器)、微信/阿里/百度/字节/QQ 小程序均标记为可用(y),App 端 app-vue 可用、app-nvue 为未知(u),这正对应了源码中大量 #ifndef APP-NVUE 条件编译注释——nvue 下部分类名需要特殊处理。
二、目录结构与加载入口
uni-scss 在 hello-uniapp 中的目录结构如下:
uni_modules/uni-scss/
├── changelog.md # 版本变更记录
├── index.scss # 顶层入口(仅一行 @import)
├── variables.scss # 对外暴露的变量清单(供直接覆写)
├── theme.scss # 主题色概览(展示用精简变量集)
├── readme.md # 使用说明
├── package.json # 模块元信息与平台支持声明
└── styles/
├── index.scss # 汇总导入 6 个 setting 文件
├── setting/
│ ├── _variables.scss # 全部 Sass 变量(含默认值 !default)
│ ├── _border.scss # .uni-border 边框类
│ ├── _color.scss # 颜色类名生成 + 阴影/蒙版类
│ ├── _space.scss # 间距类名生成(margin/padding)
│ ├── _radius.scss # 圆角类名生成
│ ├── _text.scss # 文本排版类名(h1~h6 等)
│ └── _styles.scss # 按钮(.uni-btn)样式体系
└── tools/
└── functions.scss # map-deep-merge 工具函数
加载链路非常清晰:index.scss(顶层)→ styles/index.scss → 6 个 setting/_*.scss;而 _variables.scss 又会 @import '../tools/functions.scss' 引入 map 合并工具函数。
在 hello-uniapp 项目中,这套样式在全局入口 App.vue 中加载:
<style lang="scss">
@import '@/uni_modules/uni-scss/index.scss';
/* uni.css - 通用组件、模板样式库,可以当作一套ui库应用 */
@import './common/uni.css';
</style>
注意两点:一是 <style> 必须声明 lang="scss",否则 Sass 语法无法编译;二是 App.vue 中通过 @/uni_modules/uni-scss/index.scss 路径引用,@/ 指向项目根目录,符合 uni_modules 的引用规范。加载后,全部辅助类名(如 uni-primary、uni-mt-5、uni-radius)即可在任意页面直接使用。
三、变量体系:全量色板、间距、圆角与阴影
styles/setting/_variables.scss 是整套样式的心脏,几乎每个变量都带有 !default 标记,意味着你可以先声明同名变量再导入,实现"覆写主题"。
3.1 主色与辅助色(行为色)
| 变量 | 默认值 | 派生变量 |
|---|---|---|
$uni-primary |
#2979ff |
$uni-primary-disable(lighten 20%)、$uni-primary-light(lighten 25%) |
$uni-success |
#18bc37 |
$uni-success-disable、$uni-success-light |
$uni-warning |
#f3a73f |
$uni-warning-disable、$uni-warning-light |
$uni-error |
#e43d33 |
$uni-error-disable、$uni-error-light |
$uni-info |
#8f939c |
$uni-info-disable、$uni-info-light |
派生色通过 Sass 内置 lighten() 函数按百分比提亮得到:disable 提亮 20%,light 提亮 25%。这与顶层 variables.scss 中的 mix(#fff, $uni-primary, 50%) 写法略有差异(mix 是按比例混合白色),但语义一致,均用于表达禁用态与浅色态。
3.2 中性色、边框色与常规色
// 中性色(文字层级)
$uni-main-color: #3a3a3a; // 主要文字
$uni-base-color: #6a6a6a; // 常规文字
$uni-secondary-color: #909399; // 次要文字
$uni-extra-color: #c7c7c7; // 辅助说明
// 边框颜色(从深到浅)
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
$uni-bg-color: #f7f7f7;
3.3 间距、阴影与蒙版
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
// 阴影
$uni-shadow-sm: 0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base: 0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg: 0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4);
两个基础变量值得单独说明:$uni-space-root: 2 是间距"基础倍数",所有间距类名的数值都要乘以它;$uni-radius-root: 5px 是圆角基础值。另外,_variables.scss 中还定义了一套完整的标题字号 map $uni-headings(h1 32px/300、h2 28px/300、h3 24px/400、h4 20px/400、h5 16px/400、h6 14px/500、subtitle 12px、body 14px、caption 12px),供文本排版类使用。
四、类名生成机制:一行类名搞定布局
4.1 间距类:uni-m{a|t|r|b|l|x|y}-{0..16}
_space.scss 用两层循环批量生成间距类:外层遍历 m(margin)和 p(padding),内层遍历方向 t/r/b/l/x/y/a(top/right/bottom/left/x 轴/y 轴/all),数值从 0 到 16。实际像素值 = $i * $uni-space-root,即 uni-mt-5 = margin-top: 10px(5 × 2)。同时每个正向类都配套生成负值类 -n 后缀版本(如 uni-mt-n5 = margin-top: -10px)。
以 pages/extUI/color/color.nvue 中的实际用法为例:
<view class="uni-ma-5">
<view class="box uni-radius">
<view class="item-box uni-primary-bg">
<text class="uni-body uni-white">primary</text>
</view>
</view>
</view>
4.2 圆角类:uni-radius[-{方向}][-{档位}]
_radius.scss 基于 $uni-radius map 生成圆角类,档位定义如下:
| 档位 | 值 |
|---|---|
| 0(无后缀) | 0 |
| null(无档位) | $uni-radius-root = 5px |
lg |
10px(root × 2) |
xl |
30px(root × 6) |
pill |
9999px(胶囊) |
circle |
50%(圆形) |
方向支持 t/r/b/l/tl/tr/br/bl 八个方位,因此你可以写出 uni-radius-t-lg(顶部大圆角)、uni-radius-circle(圆形)等组合。sm 档被注释为 TODO 暂不支持,原因是其依赖 math.div() 除法计算。
4.3 颜色类:uni-{key} 与 uni-{key}-bg
_color.scss 将 30 个颜色变量(主色、辅助色、中性色、边框色、常规色的全部 key)通过 @each 批量生成前景色类与背景色类:
@each $key, $child in $uni-ui-color {
.uni-#{$key} { color: $child; }
.uni-#{$key}-bg { background-color: $child; }
}
于是 uni-primary 控制文字颜色、uni-primary-bg 控制背景色,uni-success、uni-warning、uni-error、uni-info 及 uni-main-color、uni-border-1 等一应俱全。同文件还固化了 uni-shadow-sm/base/lg 与 uni-mask 类。pages/extUI/color/color.nvue 页面就是这套色板的完整演示:主色、辅助色、中性色、分隔线、常规色、阴影六个区块逐一渲染。
4.4 文本排版类:uni-h1 ~ uni-h6、uni-body
_text.scss 遍历 $uni-headings map 生成 .uni-h1 到 .uni-caption 等排版类,每个类展开为 font-size / font-weight / line-height。这里有一个典型的平台差异处理:非 nvue 平台直接输出 .uni-h1 类;而 #ifdef APP-NVUE 分支下类名被限定为 .container .uni-h1(需放在 .container 容器内),以规避 nvue 样式作用域限制。
4.5 按钮体系:.uni-btn
_styles.scss(整体包裹在 #ifndef APP-NVUE 中)提供了一套完整的按钮样式,hello-uniapp 的 pages/extUI/button/button.vue 对此做了详尽演示。其设计要点:
- 基础类
.uni-btn定义默认外观,并通过&::after { border: none; }去掉原生 button 的伪元素边框(解决小程序/App 端按钮自带边框问题); - 通过
type属性驱动配色:type="primary|success|warning|error|info"分别调用is-color()/is-plain()两个 mixin; - 支持
plain(镂空,由is-plainmixin 实现浅色背景 + 主题色文字边框)、loading、disabled三种状态; - 尺寸控制:
size="mini"走原生尺寸,.uni-btn-small(14px)、.uni-btn-mini(12px)为类名微调,.uni-btn-radius提供 999px 胶囊圆角。
所有按钮状态都基于主题色变量动态计算,例如禁用态通过 mix($color, #fff) 淡化背景、mix(darken($color,10%), #fff) 淡化边框,因此改一处主题变量即可让整套按钮风格随之变化。
五、主题定制:覆写变量与全局生效
uni-scss 的 !default 设计使其天然支持主题覆写。两种典型做法:
方式一:全局覆写(推荐)。在你项目根目录的 uni.scss 中先定义同名变量,再让 uni-app 自动注入。hello-uniapp 根目录的 uni.scss 本身就是一套独立的 uni-app 内置变量($uni-color-primary: #007aff 等),而 uni-scss 的变量($uni-primary)则服务于 uni-ui 组件体系。二者命名不同、职责互补——前者是 uni-app 框架内置约定,后者是 uni-ui 组件使用的辅助样式库。
方式二:局部覆写。在组件 <style lang="scss"> 内先声明变量再 @import '@/uni_modules/uni-scss/index.scss',可只影响该组件作用域。
从仓库证据看,uni-scss 的主题能力已被 uni-ui 组件广泛依赖:多个组件的 changelog 明确记载"支持使用 uni-scss 控制主题色"(如 uni-calendar/changelog.md、uni-data-checkbox/changelog.md、uni-data-picker/changelog.md);uni-pagination/changelog.md 还记录过一次"未对主题色设置默认色,导致未引入 uni-scss 变量文件报错"的修复,反证了变量体系对组件的重要性。此外 uni-badge、uni-card、uni-collapse、uni-countdown、uni-dateformat 等多个组件的 package.json 均把 uni-scss 声明为依赖,说明它是 uni-ui 组件族的公共样式底座。
六、快速上手清单
- 确认 HBuilderX 版本 ≥ 3.1.0(见
package.json的 engines 声明); - 在 App.vue 的
<style lang="scss">中@import '@/uni_modules/uni-scss/index.scss';; - 页面模板中直接使用辅助类:
uni-mt-5、uni-px-2、uni-radius-lg、uni-primary-bg、uni-shadow-base、uni-btn等; - 需要换肤时,在引入前覆写
$uni-primary、$uni-success等!default变量; - nvue 页面注意条件编译差异(间距/颜色类可用,
.uni-btn按钮与部分排版类不生效); - 参考仓库中的现成 demo:color.nvue 看色板与阴影,button.vue 看按钮全形态。
这套以"变量 + 类名生成循环"为核心的样式架构,用极少的源码量覆盖了页面开发中最频繁的样式诉求,也让主题定制成本降到最低——这正是它成为 uni-ui 组件族公共依赖的原因所在。