contenteditable="true" 元素必须添加 tabindex="0" 才能键盘聚焦,否则不参与 tab 流、违反 wcag 2.1;禁用 disabled 混用,hidden 不解除可访问性,lang/dir 缺失影响多语言渲染与语音合成。

contenteditable="true" 但元素无法键盘聚焦
这是最常被忽略的可访问性断点:设了 contenteditable="true",却没加 tabindex,结果鼠标能点、键盘 tab 不进去,WCAG 2.1 直接不通过。
根本原因不是“浏览器不支持”,而是浏览器默认把 contenteditable 元素视为非焦点元素——它不参与自然 tab 流,除非你明确告诉它“可以进”。
-
tabindex="0"是最安全选择:按 DOM 顺序加入 tab 流,屏幕阅读器也能正确识别 - 别用
tabindex="1"或更高正数:会打乱语义顺序,对辅助技术用户造成困惑 -
tabindex="-1"仅用于程序化聚焦(比如点击按钮后自动 focus 到编辑区),不能替代0 - 如果元素同时有
disabled,tabindex完全失效——disabled和contenteditable本质冲突,别混用
正确写法示例:
<div contenteditable="true" tabindex="0" spellcheck="false">可编辑文本</div>
data-* 属性当响应式状态用,值变了组件却不更新
React/Vue 里直接读 element.dataset.id 并绑定到视图,改了 el.setAttribute('data-id', '999') 却没重渲染?这不是框架 bug,是误用了 DOM 属性的语义。
dataset 只读取初始 HTML 中的值,且所有值都是字符串——data-count="42" 拿到的是 "42",不是数字;data-active="true" 是字符串 "true",不是布尔值。更关键的是:它不触发 MutationObserver,默认不被框架监听。
- 不要在 mount 后靠
setAttribute更新data-*来驱动 UI 变化 - 避免把 JSON 字符串塞进
data-config后直接JSON.parse(),没try/catch一报错就卡死 - SSR 渲染的
data-值若被客户端 JS 覆盖,而框架没同步状态,首屏和 JS 状态就会不一致 - 真要让自定义数据参与响应式,得用
customElements+attributeChangedCallback,且必须在observedAttributes里声明(不含data-前缀)
hidden 属性滥用导致隐藏元素仍可聚焦或影响布局
hidden 是布尔属性,存在即生效,但它不是 CSS 的 display: none 的完全等价物——它只控制可见性,不解除可访问性树中的节点关系。
常见错误是给一个 contenteditable 元素同时加 hidden 和 tabindex="0",结果元素不可见但仍能被键盘 tab 到,形成“看不见的焦点陷阱”,严重违反可访问性原则。
-
hidden元素仍保留在可访问性树中,屏幕阅读器可能读出其内容(取决于 UA 实现) - 旧版 Safari/IE 不支持
hidden,需 fallback 到style.display = 'none'或 class 控制 - 逻辑上该卸载的区域(比如已关闭的弹窗),别只用
hidden,应配合remove()或条件渲染真正移除 DOM - 用
class控制显隐比hidden更可控:el.classList.toggle('is-hidden')配合 CSS.is-hidden { display: none; }
lang/dir 缺失导致 RTL 文本错乱或语音合成异常
中文页面没写 lang="zh-CN",阿拉伯语段落没加 dir="rtl",看着好像没问题,但实际会影响拼写检查、语音朗读节奏、标点方向,甚至让某些输入法行为异常。
尤其当页面混排多语言时,浏览器依赖 lang 和 dir 决定字体回退、换行规则和光标移动方向。缺失时,它只能猜,一猜就错。
-
lang应设在根上作为默认,局部覆盖用在具体元素(如<span lang="ar">مرحبا</span>) -
dir必须与语言匹配:lang="ar"应配dir="rtl",lang="he"同样;lang="zh"或lang="en"默认dir="ltr",可省略但建议显式写出 - 别用 CSS 的
direction或text-align替代dir:前者只影响渲染,后者才影响底层文本引擎行为 - 服务端渲染时确保
lang值来自可信上下文(如用户语言偏好或路由 locale),别硬编码成固定值
真正难的不是记住哪些属性可用,而是理解每个属性在浏览器渲染管线、可访问性树、DOM 事件流里的真实作用点——写错一个 tabindex,可能让整页对屏幕阅读器用户不可用;漏掉一个 lang,会让语音助手把中文读成日语腔调。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











