contenteditable必须配tabindex="0"才能键盘聚焦,否则无法输入;它只认true/false/空字符串,不支持"plaintext-only"等非标值,且缺失tabindex直接违反WCAG 2.1 2.1.1。

contenteditable 必须配 tabindex="0" 才能键盘聚焦,否则只是“看起来可编辑”,实际无法输入——这是最常被忽略的硬性组合。
为什么 contenteditable 加了却不能打字?
它不是开关式属性,而是行为触发器:浏览器只认三个值——true、false、空字符串(等价于 true),不支持 "plaintext-only" 或 "on" 等写法。
常见错误现象:
- 光标点不进去,按 Tab 也跳不过去 → 缺
tabindex="0" - 点了能聚焦,但输不了中文/符号 → 子元素有
user-select: none或pointer-events: none - 拼写检查下划线干扰 UI → 忘加
spellcheck="false"
推荐写法:
<div contenteditable="true" tabindex="0" spellcheck="false">编辑内容</div>
tabindex 的数值不是“越大越靠前”
它直接影响焦点流语义和屏幕阅读器顺序,不是简单排序工具。
立即学习“前端免费学习笔记(深入)”;
使用场景与风险:
-
tabindex="-1":只能用 JS 调el.focus()聚焦,不进自然 tab 流 —— 适合弹窗打开后手动聚焦 -
tabindex="0":按 DOM 顺序加入 tab 流,95% 场景该用这个 -
tabindex="5"及正数:强制前置顺序,但会打乱屏幕阅读器逻辑,WCAG 不推荐
对 contenteditable 元素,tabindex 缺失 = 键盘不可达 = 直接违反 WCAG 2.1 2.1.1。
哪些属性真能用在任意标签上?
MDN 当前(2026 年 4 月)明确列为全局属性的共 27 个,包括:accesskey、autocapitalize、class、contenteditable、dir、draggable、hidden、id、inert、lang、spellcheck、style、tabindex、title 等。
注意排除项:
-
on*类(如onclick)是 DOM 事件处理器,不属于 HTML 全局属性规范 -
xml:lang和xml:base已弃用,仅兼容保留 -
popover和virtualkeyboardpolicy属实验性属性,Safari 当前不支持后者 -
inert在 Chrome 122+、Firefox 125+ 才稳定,旧版需降级逻辑
data-* 和 id 的边界在哪?
两者都用于标识,但语义和用途完全不同。
data-* 是运行时数据容器:
- 命名必须以
data-开头,后续只能是字母、数字、连字符(如data-user-id) - 值纯字符串,JS 中需用
dataset.userId访问(驼峰转换) - 不参与样式、无障碍或 SEO,只服务脚本逻辑
id 是文档级唯一锚点:
- 必须全局唯一,且首字符只能是字母或下划线
- 被 CSS 选择器、
document.getElementById()、页面内跳转(#header)直接消费 - 影响可访问性:ARIA 属性(如
aria-labelledby)常依赖它
别用 data-id 替代 id 做锚点或样式绑定——那是语义错位。
contenteditable 和 tabindex 的耦合刚性,以及 inert、popover 这类新属性的兼容性断层。写的时候查一眼当前目标浏览器版本,比事后 debug 更省时间。



















