contenteditable必须配tabindex="0"才能真正可编辑,缺则键盘不可达、WCAG 2.1 2.1.1不通过;只认true/false/空字符串三值,“plaintext-only”等无效;子元素含user-select:none或pointer-events:none会阻断输入;spellcheck="false"可消除拼写下划线干扰。

contenteditable 必须配 tabindex="0" 才能真正可编辑
加了 contenteditable="true" 却点不进去、Tab 跳不过去、输不了中文——90% 是因为漏了 tabindex="0"。它不是可选装饰,而是 WCAG 2.1 2.1.1 强制要求的可访问性底线。
-
contenteditable只认三个值:true、false、空字符串(等价于true);"plaintext-only"或"on"都无效 - 子元素若带
user-select: none或pointer-events: none,会拦截光标定位,导致“能聚焦但无法选中/输入” - 拼写检查下划线干扰 UI?补上
spellcheck="false"就干净了 - 推荐最小可用写法:
<div contenteditable="true" tabindex="0" spellcheck="false">编辑内容</div>
tabindex 不是“让元素能 tab 进去”的开关
它的数值直接决定焦点流语义和屏幕阅读器顺序,不是简单排序工具。
-
tabindex="-1":只能用 JS 调el.focus()聚焦,不进自然 tab 流——适合弹窗打开后手动聚焦 -
tabindex="0":按 DOM 顺序加入 tab 流,95% 场景该用这个 -
tabindex="5"及正数:强制前置顺序,但会打乱屏幕阅读器逻辑,WCAG 明确不推荐 - 对
contenteditable元素,tabindex缺失 = 键盘不可达 = 可访问性失败
哪些属性真能用在任意 HTML 标签上?
MDN 当前(2026 年 4 月)明确列为全局属性的共 27 个,不是所有“看着通用”的都算数。
- 确定属于全局属性的:
accesskey、autocapitalize、class、contenteditable、dir、draggable、hidden、id、inert、lang、spellcheck、style、tabindex、title、translate等 -
on*类(如onclick)是 DOM 接口支持,不属于 HTML 规范定义的全局属性 -
xml:lang和xml:base已被弃用,仅因兼容性保留 -
inert在 Chrome 122+、Firefox 125+ 才稳定支持;popover和virtualkeyboardpolicySafari 目前不支持
data-* 属性命名和读取有硬性规则
它看似自由,但浏览器对格式和 JS 访问方式有明确限制。
立即学习“前端免费学习笔记(深入)”;
- 必须以
data-开头,后接合法 HTML 标识符(不能含大写字母、空格、特殊符号,建议用短横线分隔) -
data-user-id="123"✅,data-userId="123"❌(驼峰不被标准化识别) - JS 中必须用
dataset访问:el.dataset.userId→ 实际读的是data-user-id(自动转为驼峰) - 动态设置要用
el.dataset.foo = "bar",而不是el.setAttribute("data-foo", "bar")(后者不会同步到dataset)
复杂点不在数量,而在组合逻辑:比如 contenteditable 和 tabindex 是强绑定关系,inert 会覆盖 contenteditable 行为,hidden 会让元素彻底退出渲染流——这些不是叠加生效,而是互相覆盖或阻断。实际写的时候,得先想清楚行为优先级,而不是堆属性。



















