HTML语义化标签(如header、nav、main等)本身已具明确结构含义,无需冗余添加class或id;仅当需JS操作、CSS精确控制或区分同类元素时才添加,且class须用kebab-case命名。

HTML标签命名要不要加class或id
绝大多数语义化标签(header、nav、main、article、section、footer)本身已携带明确结构含义,不需要额外加class或id——除非你有具体用途:
- 需要 JS 操作单个元素(如
document.getElementById("main-content")),才加id - 需要 CSS 精确覆盖样式(比如多个
section中只改其中一个),才加class - 页面内存在多个同类语义标签(如两个
aside),且需区分角色,才用class="aside--related"这类 BEM 变体
乱加 class="header" 或 id="nav" 是典型冗余:既没新增语义,又干扰可读性,还可能和框架默认选择器冲突。
class命名为什么必须用kebab-case
CSS 选择器不支持驼峰(userAvatar)和下划线(user_avatar),浏览器解析时会把点号(.)和冒号(:)当伪类处理,而下划线在旧版 IE 中曾有兼容问题。统一用连字符是唯一安全选择:
-
class="search-bar"✅ 可直接写成 CSS:.search-bar { ... } -
class="searchBar"❌ 写成.searchBar会被当成类名含大写字母,但 HTML 不区分大小写,JS 获取时容易出错 -
class="search_bar"❌.search_bar虽能生效,但和 BEM 规范冲突,也易与后端模板变量(如 Jinja2 的{{ user_name }})混淆
工具类如 u-hidden、u-text-center 也必须遵守该规则,前缀 u- 是为隔离无语义行为,不是为了“看起来高级”。
立即学习“前端免费学习笔记(深入)”;
id含点号或冒号时JS怎么取元素
如果服务端动态生成的 id 包含 .、:、[、] 等 CSS 选择器特殊字符(比如 id="user.email"),直接用 document.getElementById("user.email") 会失败——浏览器把它当成了 CSS 选择器语法(类似 document.querySelector("user.email"))。
- 正确写法:
document.getElementById("user\.email")(反斜杠转义点号) - 更稳妥的方式:改用
document.querySelector("[id='user.email']"),避免手动转义遗漏 - 根本规避方案:服务端生成
id时过滤掉这些字符,用user-email替代user.email
这个坑在 SSR 场景下尤其致命:React/Vue hydration 依赖 DOM id 与虚拟节点严格匹配,错一个就导致首屏渲染错乱,且控制台不报错,只静默 fallback。
BEM里双下划线和双短横分别表示什么
BEM 的 block__element 和 block--modifier 不是装饰符号,而是层级与状态的硬约束:
-
card__title表示它是card块的直属子元素,不能跳级(card__header__title是错的,应为card__header-title或拆出新 block) -
card--featured表示整个卡片的状态变体,影响所有子元素;而card__title--highlighted表示仅标题高亮,不影响其他部分 - 修饰符名必须是布尔值或枚举值(
--disabled、--large),不能是样式描述(--red-bg违反语义优先原则)
实际项目中,BEM 的价值不在“写得像不像”,而在强制你思考组件边界——menu__item--active 能立刻说明「这是菜单项的激活态」,而不是靠猜 active-item 或 current 到底属于哪一层。



















