Skip to content

样式规范

核心原则

BEM 定义语义,UnoCSS 补充微调,SCSS 只做脏活。

层级职责示例
BEM组件语义锚点profile-cardprofile-card__avatar
UnoCSS简单布局微调(≤3 个属性)flex items-center gap-16rpx
SCSS伪类/动画/穿透等原子类做不了的事:deep()@keyframes

选型决策

场景方案示例
简单布局(1-2 个属性)原子类class="flex items-center"
组件样式(3+ 属性)BEMclass="profile-card"
重复出现的组合Shortcuts 收敛class="flex-center"
主题相关CSS 变量 + BEMbackground: var(--color-primary)
vue
<!-- ✅ 组件样式归 BEM,微调用原子类 -->
<view class="profile-card">
  <image class="profile-card__avatar" :src="user.avatar" />
  <text class="profile-card__name">{{ user.name }}</text>
</view>

<!-- ✅ 简单间距直接用原子类 -->
<view class="mt-16rpx p-4">
  <wd-search v-model="keywords" placeholder="搜索" />
</view>

<!-- ❌ 同一元素混用过多原子类 + BEM -->
<view class="profile-card flex flex-col p-28rpx bg-white rounded-28rpx shadow-sm">
</view>

BEM 命名

格式

block__element--modifier
 │      │          │
 │      │          └── 状态/变体(双连字符)
 │      └── 组成部分(双下划线)
 └── 独立功能实体

Block 必须带页面前缀

text
首页(index)  → home-hero / home-nav / home-stat
我的(mine)   → mine-hero / mine-profile / mine-menu
登录(login)  → login-form / login-brand / login-nav

Element 通用词汇

语义标准词汇禁止
头部__headerhead / top
底部__footerbottom
标题__titlename / heading
副标题__subtitledesc(描述时用 desc)
描述__desctext / detail
图标__iconimg / pic
图片__imageimg / bg
头像__avatarphoto
标签__tagbadge(徽章时用 badge)
徽章__badgedot(圆点时用 dot)
操作按钮__actionaction-btn
操作区__actionsbtns
内容__bodycontent
输入框__inputfield(行容器时用 field)
表单行__fieldrow
列表__listitems
列表项__itemrow

SCSS 嵌套

scss
.login {
  background: linear-gradient(135deg, var(--color-bg-tertiary), var(--color-primary-light));

  &__field {
    display: flex;
    align-items: center;

    &:focus-within {
      box-shadow: 0 0 0 2px var(--color-primary);
    }
  }

  &__code-btn {
    height: 32px;
    border-radius: 8px;

    &--active { color: var(--color-primary); background: var(--color-primary-light); }
    &--disabled { color: var(--color-text-placeholder); background: var(--color-bg-tertiary); }
  }
}

主题变量

变量速查

主题色

语义LightDark变量
主色#4d80f0#3b82f6--color-primary
主色浅#e8f0fe#1e3a5f--color-primary-light
成功#34d19d#34d399--color-success
成功浅#e6f7f1#064e3b--color-success-light
警告#f0883a#fbbf24--color-warning
警告浅#fff4e6#78350f--color-warning-light
危险#ff4757#f87171--color-danger
危险浅#fff1f2#7f1d1d--color-danger-light

背景色

语义LightDark变量
主背景#ffffff#1f2937--color-bg
次背景#f5f5f5#111827--color-bg-secondary
三级背景#f1f5f9#1e293b--color-bg-tertiary

文字色

语义LightDark变量
主文字#1f2937#f9fafb--color-text
次文字#6b7280#9ca3af--color-text-secondary
占位文字#9ca3af#6b7280--color-text-placeholder

边框色

语义LightDark变量
默认#e5e7eb#374151--color-border
浅色#f3f4f6#1f2937--color-border-light

使用原则

scss
// ✅ 使用变量
.card { background: var(--color-bg); border: 1rpx solid var(--color-border); }

// ❌ 禁止硬编码
.card { background: #ffffff; border: 1rpx solid #e5e7eb; }

Wot Design 变量桥接

scss
--wot-color-theme:   var(--color-primary);
--wot-color-success: var(--color-success);
--wot-color-warning: var(--color-warning);
--wot-color-danger:  var(--color-danger);
--wot-color-bg:      var(--color-bg);
--wot-color-text:    var(--color-text);

z-index 层级

只有 position: fixed/sticky/absolute 且存在层叠竞争的元素才设 z-index,禁止魔法数字。

scss
--z-dropdown:  100;   // 下拉菜单、Popover
--z-sticky:    200;   // 吸顶栏、吸底栏
--z-overlay:   300;   // 遮罩层
--z-popup:     400;   // Popup
--z-dialog:    500;   // Dialog / MessageBox
--z-toast:     600;   // Toast
--z-navbar:    700;   // 固定导航栏
--z-fab:       800;   // 浮动按钮

间距与圆角

间距

语义场景
xxs4rpx极小间距
xs8rpx图标与文字
sm16rpx模块间分隔
md24rpx卡片内边距
lg32rpx页面左右边距
xl40rpx
xxl48rpx大区块分隔
scss
--spacing-xxs: 4rpx;  --spacing-xs: 8rpx;   --spacing-sm: 16rpx;
--spacing-md: 24rpx;  --spacing-lg: 32rpx;  --spacing-xl: 40rpx;
--spacing-xxl: 48rpx;

圆角

场景
小元素(按钮、标签)8rpx
中元素(输入框)16rpx
大卡片24rpx
圆形50%

阴影

级别场景
sm0 1px 2px rgba(0,0,0,0.05)卡片
md0 4px 6px rgba(0,0,0,0.1)弹窗
lg0 10px 15px rgba(0,0,0,0.1)模态框

字体

场景字号字重行高
辅助信息24rpx4001.4
次要文字26rpx4001.5
正文28rpx4001.6
小标题30rpx6001.4
标题32rpx6001.3
大标题36rpx7001.2

UnoCSS Shortcuts

快捷类展开用途
flex-centerflex justify-center items-center居中
flex-betweenflex justify-between items-center两端对齐
flex-startflex justify-start items-center起始对齐
flex-col-centerflex flex-col items-center纵向居中

新增 Shortcut 条件:全局出现 ≥ 5 次 + 有明确语义 + 不含业务色值。

WXSS 兼容性

特性状态替代
:deep()编译后残留,WXSS 报错组件 custom-class + 非 scoped style
[attr*="val"]不支持具体类名
:has() / :is()不支持具体选择器
vue
<!-- ✅ custom-class + 非 scoped 覆盖组件样式 -->
<wd-card custom-class="my-card">
  <template #title>标题</template>
</wd-card>

<style lang="scss">
.my-card { margin: 0 !important; }
.my-card .wd-card__body { padding: 24rpx !important; }
</style>

反模式

反模式正确做法
硬编码颜色值使用 CSS 变量
普通流内容设 z-index只有定位元素才设
::deep([attr*="val"])使用具体类名
Block 名过于通用使用页面/功能前缀
height: 100vh使用 min-height: 100vh
z-index 魔法数字使用 var(--z-*)
SCSS 大量 @apply原子类留在模板
AI 蓝紫渐变纯色或品牌色
Emoji 当图标SVG 图标
过度装饰(阴影+渐变+动画)最多一个装饰效果

自查清单

  • [ ] 页面根元素 class="page"
  • [ ] 颜色全部使用 CSS 变量
  • [ ] z-index 使用 var(--z-*),普通流内容未设 z-index
  • [ ] 页面容器 min-height: 100vh
  • [ ] BEM 类名带页面前缀
  • [ ] 模板中原子类 ≤ 3 个,超过则归入 BEM

基于 MIT 许可发布 · 由 ❤️ 和 ☕ 驱动 · 支持作者