contenteditable 元素必须配合 tabindex="0" 才能键盘聚焦和输入,否则不可访问;其值仅认 "true"、"false"、空字符串;还需注意 spellcheck、user-select、dataset 命名规则及 hidden 行为差异。

contenteditable 不是加了就能编辑,缺 tabindex="0" 就等于没加——键盘根本进不去,屏幕阅读器直接报错。
为什么 contenteditable 加了却点不进去、输不了字?
它只认三个值:"true"、"false"、空字符串(等价于 "true"),其他如 "on"、"plaintext-only" 全被浏览器忽略。
- 光标点不进去、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 缺失 = 键盘不可达 = 违反可访问性底线。
data-* 属性读写时的命名陷阱
HTML 中写 data-user-id="123",JS 里访问的是 dataset.userId(连字符变驼峰,首字母小写),不是 dataset.userid 或 dataset.Userid。大小写不匹配就拿不到值。
- 属性名含数字开头,比如
data-1st-place,JS 中无法通过dataset.1stPlace访问(变量名非法),得用dataset["1st-place"] -
data-后只能跟 ASCII 字母、数字、连字符(-)、点(.)、下划线(_),不能有冒号(:)或空格;data-user:name是无效的,会被浏览器静默忽略 - 值始终是字符串,哪怕写
data-count="0",取出来也是"0",需要手动转类型:Number(el.dataset.count)
hidden 不只是“看不见”,它分两种行为模式
默认 hidden 等价于 display: none,不占布局空间;但新值 hidden="until-found" 是例外:
-
hidden(无值或hidden="hidden")→ 完全移出渲染流,内外边距、宽高都不计算 -
hidden="until-found"→ 视觉隐藏但保留布局位置,等效于content-visibility: hidden,用于懒加载场景 -
hidden在<script></script>或<meta>上无效,浏览器直接忽略
真正容易被忽略的,是 contenteditable 和 tabindex 的绑定关系 —— 它们必须成对出现,否则功能形同虚设。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











