HTML全局属性是页面结构、可访问性和维护性的基础设施:lang须按BCP 47规范精确设置并支持嵌套多语言;hidden为布尔属性,语义上移除元素,不同于display: none;data-*命名受限且dataset自动转小写;contenteditable需同步管控tabIndex与spellcheck。

HTML全局属性不是“可选加分项”,而是页面结构、可访问性和维护性的底层基础设施——漏掉lang或误用hidden,轻则影响SEO和屏幕阅读器,重则导致JS逻辑失效或安全策略拦截。
为什么lang必须写对,且不能只写在<html>上
浏览器和屏幕阅读器依赖lang判断文本方向、断词规则、语音合成音调。只在<html lang="zh-CN">设一次,无法覆盖多语言混排内容(比如英文术语嵌在中文段落里)。
- 中英混排时,在英文片段外层加
<span lang="en">API</span>,避免读错发音 - 用户生成内容(如评论)若含日文/阿拉伯文,需动态补
lang,否则NVDA等读屏器会沿用父级中文规则,把「こんにちは」读成中文音 -
lang值必须是BCP 47标准格式(如zh-Hans、en-GB),zh-CN虽常见但非强制;用document.documentElement.lang读取时,返回值与实际属性值严格一致,大小写敏感
hidden vs display: none:视觉隐藏≠语义移除
hidden是布尔属性,设了就生效,不写值;它让元素**不渲染、不可聚焦、不被AT(辅助技术)感知**,但DOM节点仍在。而display: none只是CSS隐藏,元素仍可被querySelector选中、仍占用tab顺序(若没设tabindex="-1")。
- 错误写法:
hidden="false"——布尔属性不接受字符串值,浏览器会当作true处理 - 正确开关方式:
el.hidden = true或el.removeAttribute('hidden'),别用setAttribute('hidden', 'false') - 表单场景慎用:
<input hidden name="token" value="xxx">能提交,但<input style="display:none" name="token">也能——两者行为在此一致;区别在可访问性:前者完全从AT流中剔除,后者仍可能被读出(尤其当未设aria-hidden)
data-*命名和读取的硬性限制
data-属性是前端传参最常用通道,但命名不合规会导致dataset API读不到。
立即学习“前端免费学习笔记(深入)”;
- 合法命名:只能含字母、数字、连字符(
-)、下划线(_)、冒号(:)、点号(.),且必须以data-开头,如data-user-id、data-config-json - 驼峰名会被自动转为短横线:定义
data-userId,JS中el.dataset.userId读不到,得写el.dataset.userid(全小写+去横线) - 值始终是字符串:
data-count="42"→el.dataset.count === "42",需手动parseInt,别直接用于数值比较 - 大量
data-会拖慢渲染:Chrome中单个元素超过50个data-属性,dataset访问延迟明显上升,高频交互区域建议改用WeakMap缓存结构化数据
contenteditable启用前必须同步控制tabIndex
contenteditable不是“加个属性就能编辑”,它默认让元素可聚焦、可键盘操作,但若没显式设tabIndex,焦点管理会失控。
- 未设
tabIndex时,contenteditable元素默认tabIndex=0,会进入自然tab顺序,可能打断表单流 - 禁用编辑时,仅设
contenteditable="false"不够:元素仍可聚焦(尤其当原tabIndex为0),应同步el.tabIndex = -1 - 富文本场景注意
spellcheck:Chrome对contenteditable默认开启拼写检查,中文输入法下常误标红,需显式关掉spellcheck="false"
真正难的不是记住哪些属性可用,而是理解每个属性背后绑定的浏览器行为链:一个lang错位,可能让整页语音导航失效;一个hidden误用,会让自动化测试脚本找不到本该存在的节点。它们不是装饰,是契约。



















