跳转到内容

样式规范

CSS 命名、主题、变量、避免深度选择器


  • Standard:项目统一使用 BEM(Block Element Modifier)命名法,或 CSS Modules(类名哈希化)。二选一,项目内保持一致。
  • Requirement:类名使用小写字母 + 连字符(kebab-case),禁止使用驼峰或下划线(CSS Modules 除外)。
/* Block:组件名 */
.user-card { }
 
/* Element:组件内元素,用双下划线连接 */
.user-card__header { }
.user-card__avatar { }
.user-card__name { }
 
/* Modifier:状态或变体,用双连字符连接 */
.user-card--active { }
.user-card__name--highlight { }
  • Requirement:Block 名必须具有语义,禁止使用 .box、.item、.content 等无意义名称。
  • Standard:Modifier 表示状态时,使用 is- 前缀作为辅助类,如 .is-active、.is-disabled。
  • Default:React 项目优先使用 CSS Modules,类名使用 camelCase,编译后自动哈希避免冲突。
/* UserCard.module.css */
.userCard { }
.userCardHeader { }
.userCardAvatar { }
.isActive { }
import styles from './UserCard.module.css';
 
<div className={`${styles.userCard} ${isActive ? styles.isActive : ''}`}>
  <div className={styles.userCardHeader}>...</div>
</div>
反模式问题建议
类名 .a、.b、.c完全无意义使用语义化名称
混用 kebab-case 和 camelCase风格不统一项目内统一一种风格
.item .content .text 嵌套命名无法独立使用使用 BEM 扁平化命名

  • Standard:使用 CSS 自定义属性(CSS Variables)实现主题切换,支持运行时动态切换。
  • Requirement:颜色、字号、间距、圆角等设计 Token 必须使用 CSS 变量,禁止硬编码。
:root {
  /* 颜色 */
  --color-primary: #1677ff;
  --color-success: #52c41a;
  --color-warning: #faad14;
  --color-danger: #ff4d4f;
  --color-text-primary: rgba(0, 0, 0, 0.88);
  --color-text-secondary: rgba(0, 0, 0, 0.65);
  --color-bg: #ffffff;
  --color-border: #d9d9d9;
 
  /* 字号 */
  --font-size-xs: 12px;
  --font-size-sm: 13px;
  --font-size-base: 14px;
  --font-size-lg: 16px;
  --font-size-xl: 20px;
 
  /* 间距 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
 
  /* 圆角 */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
}
 
/* 暗色主题 */
[data-theme='dark'] {
  --color-primary: #4096ff;
  --color-text-primary: rgba(255, 255, 255, 0.88);
  --color-bg: #141414;
  --color-border: #434343;
}
// 切换主题
function setTheme(theme: 'light' | 'dark') {
  document.documentElement.setAttribute('data-theme', theme);
  localStorage.setItem('theme', theme);
}
  • Standard:组件样式中只引用 CSS 变量,不直接写颜色值,确保主题切换生效。
  • Caution:新增颜色 Token 必须同步更新浅色和暗色两套主题值。
反模式问题建议
组件内硬编码颜色 #1677ff主题切换不生效使用 var(--color-primary)
颜色值散落各处难以统一修改集中定义在 styles/variables.css
暗色主题只改背景不改文字对比度不足完整定义暗色变量

  • Standard:样式变量分为三类:
    • 全局变量:src/styles/variables.css,定义设计 Token(颜色、字号、间距等)
    • 组件变量:组件级 CSS 变量,允许外部覆盖
    • 临时变量:@apply 或 SCSS 变量,仅在当前文件内使用
  • Standard:需要运行时动态修改的用 CSS 变量,仅编译时使用的用 SCSS 变量。
  • Caution:禁止在组件内重复定义已存在的全局变量,统一引用全局变量。
  • Standard:组件允许通过 CSS 变量实现外部定制,变量名以组件名为前缀。
.user-card {
  --user-card-padding: var(--spacing-md);
  --user-card-radius: var(--radius-md);
 
  padding: var(--user-card-padding);
  border-radius: var(--user-card-radius);
}
 
/* 外部覆盖 */
.user-card--large {
  --user-card-padding: var(--spacing-lg);
}
反模式问题建议
全局变量重复定义值不一致统一定义在 variables.css
用 SCSS 变量存主题色无法运行时切换用 CSS 变量
变量命名无前缀命名冲突全局变量 --color-*,组件变量 --组件名-*

  • Requirement:禁止使用深度选择器(::v-deep、/deep/、>>>)覆盖第三方组件样式,除非无法通过官方 API 定制。
  • Caution:如必须使用深度选择器,必须加注释说明原因,并限制在组件根类作用域内。
/* ❌ 反模式:无限制深度覆盖 */
::v-deep .ant-btn {
  color: red;
}
 
/* ✅ 正确:限定作用域并注释 */
.user-form {
  /* antd 表单按钮无法通过 props 定制,需深度覆盖 */
  :deep(.ant-btn-primary) {
    background: var(--color-primary);
  }
}
  • Standard:选择器嵌套层级不超过 3 层,超过时考虑使用类名直接选择。
  • Requirement:禁止使用 !important,除非覆盖内联样式或第三方无法移除的样式。
/* ❌ 反模式:层级过深 */
.page .content .list .item .title { color: red; }
 
/* ✅ 正确:扁平化 */
.list-item__title { color: red; }
  • Caution:避免使用标签选择器(div、span),优先使用类名选择器,避免样式污染。
/* ❌ 反模式 */
.user-card div { margin-top: 8px; }
 
/* ✅ 正确 */
.user-card__body { margin-top: 8px; }
反模式问题建议
::v-deep 无限制使用样式污染、难以维护限定作用域并注释
嵌套超过 4 层权重过高、难以覆盖扁平化类名
滥用 !important破坏样式优先级用更高权重的选择器
标签选择器影响范围不可控改用类名选择器

  • Standard:避免使用触发重排(reflow)的属性作为动画属性(width、height、top、left),优先使用 transform 和 opacity。
  • Standard:动画使用 will-change 提示浏览器提前优化,但禁止滥用,仅在确实有动画的元素上使用。
/* ❌ 反模式:用 top 做动画,触发重排 */
.modal {
  transition: top 0.3s;
  top: -100%;
}
.modal.active { top: 0; }
 
/* ✅ 正确:用 transform 做动画,只触发重绘 */
.modal {
  transition: transform 0.3s;
  transform: translateY(-100%);
}
.modal.active { transform: translateY(0); }
  • Standard:避免使用通配符选择器 * 和属性选择器 [type="text"],优先使用类名选择器。
  • Standard:后代选择器比子代选择器慢,优先使用子代选择器 > 或直接类名。
  • Standard:图片使用 background-image 时,大图片提供多倍图适配 Retina 屏幕。
  • Suggestion:使用 contain: layout paint 或 content-visibility: auto 优化长列表渲染性能。
反模式问题建议
用 width/top 做动画频繁重排,卡顿用 transform/opacity
全局 * { box-sizing: border-box }选择器性能差用 *, *::before, *::after 且仅在 reset 中用
无意义的 will-change: all占用内存只声明需要的属性