class属性必须用双引号包裹且空格分隔类名,命名须用kebab-case,class应置于html属性首位,类名需语义化、避免样式与逻辑耦合。

class 属性必须写成 class="xxx",且多个类名之间**只用单个空格分隔**,其他任何写法(逗号、分号、换行、引号嵌套)都会导致部分或全部类名失效。
class 属性值必须用双引号包裹,且只接受空格分隔
浏览器解析 class 属性时,会把引号内的整个字符串按 ASCII 空格切分成独立类名。哪怕多打几个空格、Tab 或换行,也只算一个分隔符,不影响结果;但一旦混入逗号、分号、点号或中文顿号,就会变成非法类名的一部分。
- ✅ 正确:
class="btn primary is-loading"→ 三个独立类:btn、primary、is-loading - ❌ 错误:
class="btn, primary"→ 实际只有一个类:btn,(含英文逗号) - ❌ 错误:
class="btn;primary"→ 实际只有一个类:btn;(含分号) - ❌ 错误:
class=".active"→ 类名是.active(带点),CSS 中要写.\.active才能匹配,极难维护
类名必须用 kebab-case,禁用驼峰、下划线和数字开头
kebab-case(小写字母 + 连字符)是唯一被所有现代工具链(PostCSS、Tailwind、Webpack、Jest 测试选择器)默认支持的格式。其他写法会在构建、调试或 SSR hydration 阶段出问题。
- ✅ 推荐:
user-profile-card、form-input-error、nav-main - ❌ 避免:
userProfileCard(JS 变量风格,CSS 选择器需转义)、user_profile_card(旧版 IE 兼容风险)、3col-layout(数字开头,#3col-layout在 CSS 中无效) - ⚠️ 注意:BEM 中的
__和--是约定,不是语法要求,但必须统一使用连字符作为唯一分隔符,不可混用
class 必须放在 HTML 标签属性第一位
这不是规范强制,但它是实际协作中最有效的可读性约束。class 是结构标识的核心,排在最前能让开发者一眼识别组件类型,避免被 id、data-test 或动态 src 干扰判断。
- ✅ 推荐:
<div class="card user-card" id="card-123" data-id="123"> <li>❌ 不推荐:<code><div id="card-123" class="card user-card" data-id="123"> —— 扫一眼先看到实例 ID,掩盖了复用意图 <li>? 补充:服务端渲染或模板中动态拼接时,也要确保最终输出的 <code>class属性排第一,否则某些 SSR 框架的 hydration 可能因顺序不一致而失败 - ✅ 语义化命名:
search-submit(功能)、article-title(内容)、is-expanded(状态,无样式含义) - ❌ 样式耦合:
red-button、float-left、font-large-bold - ❌ JS 与 CSS 共用未约定类名:
btn-submit既被 CSS 用作样式钩子,又被 JS 用作事件委托目标 —— 某天 CSS 重构删掉它,JS 就静默失效 - ? 解法:JS 操作优先用
data-action="submit",CSS 用.btn+.btn--primary,职责分离
别让 class 名承担样式快照或 JS 控制逻辑
class 是语义锚点,不是“当前状态快照”。一旦把表现细节(颜色、尺寸、位置)或行为指令(submit-btn)硬编码进类名,后续改主题、加暗色模式、做组件抽离时,HTML 就得跟着大改。
最容易被忽略的是 class 的「语义生命周期」:它一旦写进 HTML,就可能被 CSS、JS、测试脚本、SEO 工具、无障碍引擎同时依赖。改一个类名,可能牵动五六个系统。所以别把它当临时标记,而要像定义 API 接口一样慎重。











