B04 全局属性与交互元素
摘要:
id、class、hidden、data-*这类属性可以写在任何标签上,因此最容易被滥用:id重复、class承担语义、hidden代替删除。HTML 还内置了三类交互元素——折叠、弹层、进度条,用原生元素可以省掉一大段脚本与无障碍处理。本文给出全局属性的使用边界与三类原生交互元素的写法。
关键词:全局属性,data 属性,details,dialog,原生化
所属:frontend/html / B-进阶 | 上一篇:B03-内嵌内容与安全 | 下一篇:B05-结构化数据
1 引言
同一份页面里,class 常被同时当作样式钩子与语义标记,id 常被复制粘贴出重复值。这类问题不会立刻报错,却会让脚本选择器与无障碍关联失效。
本文按「标识类 → 状态类 → 数据类」整理全局属性,再给出三类可替代脚本的原生交互元素。范围见表 1-1。
| 项 | 本文覆盖 | 本文不覆盖 |
|---|---|---|
| 全局属性 | id、class、hidden、lang、dir、data-*、tabindex、contenteditable | ARIA 属性(C 阶段) |
| 交互元素 | details/summary、dialog、progress/meter |
复杂组件与状态管理 |
| 脚本 | 仅在必需处用少量脚本控制弹层 | 框架与组件库 |
2 预备知识
| 项 | 要求 | 核对方式 |
|---|---|---|
| 环境 | A02 的本地服务器 | 能访问 localhost |
| 文件 | html-practice/attrs.html |
编码 UTF-8 |
| 浏览器 | Chrome 130+,开发者工具 Console 可用 | 能执行选择器表达式 |
| 前置 | A08 | 语义骨架已掌握 |
3 原理与实现
3.1 全局属性的三类职责
全局属性按职责分三类,混用是多数问题的来源,如图 3-1 所示。
flowchart LR
G["全局属性"] --> I["标识类<br/>id / class"]
G --> S["状态类<br/>hidden / dir / lang"]
G --> D["数据类<br/>data-* / title"]
I --> I1["id 唯一,供锚点与关联"]
I --> I2["class 供样式与脚本钩子"]
S --> S1["hidden 隐藏但保留在树中"]
D --> D1["data-* 供脚本读取,不参与样式"]
图 3-1 全局属性的三类职责
图上可见:
id与class都不承担语义,语义由标签本身决定;把内容含义写进class名里,朗读软件读不到。
3.2 三类原生交互元素
<!-- 运行环境:Chrome 130+;body 内内容 -->
<section>
<h2>常见问题</h2>
<details>
<summary>为什么 id 不能重复?</summary>
<p>id 用于锚点跳转与 label 关联,重复后浏览器只认第一个,关联全部失效。</p>
</details>
<details open>
<summary>hidden 与不写元素有什么区别?</summary>
<p>hidden 的元素仍在文档树中,可被脚本恢复;不写元素则不存在。</p>
</details>
</section>
<p>
上传进度:
<progress value="42" max="100">42%</progress>
磁盘占用:
<meter value="0.72" min="0" max="1" low="0.5" high="0.85">72%</meter>
</p>
<button id="open">查看说明</button>
<dialog id="tip">
<p>这是一段说明文字,按 Esc 可关闭。</p>
<form method="dialog">
<button>关闭</button>
</form>
</dialog>
<script>
const dialog = document.getElementById('tip');
document.getElementById('open').addEventListener('click', () => dialog.showModal());
</script>
全局属性的使用边界见表 3-1。
| 属性 | 允许值 / 说明 | 常见误用 |
|---|---|---|
id |
全文档唯一,字母开头 | 同一 id 用于多个元素 |
class |
空格分隔的多个类名 | 用类名表达内容含义 |
hidden |
布尔属性,隐藏但保留 | 用 hidden 代替条件不渲染 |
lang |
语言码,如 zh-CN |
只在 html 上写,混排外语不标注 |
dir |
ltr / rtl / auto |
阿拉伯语等右排文字不标注 |
data-* |
自定义数据,脚本读取 | 把大量业务数据塞进属性 |
tabindex |
0 或 -1,正数会打乱顺序 |
使用 tabindex="3" 自定义顺序 |
title |
补充说明,悬停显示 | 当作必读信息,移动端无法悬停 |
contenteditable |
可编辑区域 | 需要富文本时未做输入校验 |
原生交互元素与脚本实现的对比见表 3-2。
| 需求 | 原生写法 | 脚本实现的代价 |
|---|---|---|
| 折叠面板 | details + summary |
需维护展开状态、键盘操作与朗读语义 |
| 弹层 | dialog.showModal() |
需自行处理焦点陷阱、Esc 与遮罩 |
| 进度 | progress / meter |
需额外绘制与无障碍标注 |
4 验证与讨论
- 保存文件,刷新页面,确认折叠面板默认收起、第二个面板默认展开。
- 只用键盘操作:
Tab聚焦到summary,按Enter或空格展开;聚焦到按钮并打开弹层,按Esc关闭。 - 执行
document.querySelectorAll('#tip').length,预期为1;把某处id改成重复值后再次执行,观察选择器仍只返回一个元素。 - 对照表 4-1 检查四项状态表现。
| 检查项 | 预期结果 | 说明 |
|---|---|---|
| 折叠键盘操作 | Enter 可展开/收起 |
原生行为 |
| 弹层焦点 | 打开后焦点进入弹层,Esc 可关 |
showModal 行为 |
| 进度语义 | 朗读软件读出百分比 | 元素自带角色 |
| id 唯一性 | 重复时选择器只命中第一个 | 违反唯一性后的表现 |
讨论与局限。 dialog 的 showModal 在旧浏览器不可用,需要回退方案;details 的动画无法只用 HTML 控制。另 data-* 只适合少量、与元素强相关的数据,列表类数据仍应走接口。
5 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| label 点击不聚焦输入框 | 关联的 id 重复,浏览器取第一个 | 保证 id 全文档唯一 |
| 折叠面板无法用键盘打开 | 用 div 加脚本模拟,未用 details | 改用 details + summary |
| 弹层打开后仍能操作背景 | 用了 show() 而非 showModal() |
改 showModal() |
| 键盘 Tab 顺序错乱 | 使用了正数 tabindex |
改为 0 或 -1,靠文档顺序排列 |
| 外语段落朗读错误 | 未标注 lang |
在对应元素上写 lang="en" |
6 结论
| 序号 | 结论 | 依据 |
|---|---|---|
| 1 | id 唯一、class 只作钩子,语义交给标签 | 图 3-1 |
| 2 | hidden 隐藏但保留,删元素才是删除 |
表 3-1 |
| 3 | 折叠、弹层、进度优先用原生元素 | 表 3-2 |
| 4 | tabindex 只用 0 与 -1 |
表 3-1 |
- 上一篇:B03-内嵌内容与安全
- 下一篇:B05-结构化数据
- 返回:B00-总结 | 科目 README
参考文献
[1] MDN Web Docs · 全局属性,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes(访问于 2026-10-29)
[2] MDN Web Docs · dialog 元素,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/dialog(访问于 2026-10-29)

评论 0
还没有评论,快来抢沙发吧~