HTML 语义化与可访问性基础

共 81 题
📑 题目列表 81 题
#
★★★

1. 与 的协作模式及自动补全下的边界

与 如何协作实现"可输入的选择框"?在动态选项更新、键盘操作与无障碍方面各有哪些边界?

  • datalist 通过 list 属性与 input 关联,提供非强制性建议
  • 与 select 强制选择语义的本质区别
  • 动态更新选项的方式及键盘、无障碍边界

通过 input 的 list 属性关联,提供"建议"而非"约束",用户可自由输入任意值; 要求必须从预定义选项中选取,二者协作可形成"可输入的选择框"。动态更新时直接增删 datalist 内的 ,浏览器实时刷新建议。边界:datalist 无法自定义选项渲染,键盘交互依赖浏览器原生实现且各端差异大;其选项不进入 Tab 顺序,屏幕阅读器支持不统一,生产环境常需自定义下拉组件兜底并补充 role、aria-expanded 等属性。

本题考察对原生自动补全机制的理解:list 属性只是把 input 与 datalist 绑定,属于非强制性建议,与 select 的强制选择语义本质不同;同时需关注动态更新方式与键盘、无障碍边界,体现工程落地时对浏览器差异的认知。

<input list="city-list" name="city" placeholder="输入或选择城市">
<datalist id="city-list">
  <option value="北京"></option>
  <option value="上海"></option>
  <option value="深圳"></option>
</datalist>
#
★★★

2. / 在内容引用与媒体描述上的语义价值

与 在内容引用与媒体描述上有怎样的语义价值?使用时有哪些规范要点?
  • figure 表示自包含、可独立迁移的内容单元
  • figcaption 与 figure 的绑定关系及位置约束
  • 对 SEO 与可访问性树的实际影响
表示自包含的内容单元,如图表、插图、代码片段或媒体,与主文档相关但可独立移动; 作为其首或末子元素提供标题说明。语义价值:把内容与说明绑定为整体,屏幕阅读器可按组朗读;帮助搜索引擎理解媒体上下文;为样式提供稳定结构。规范要点:figcaption 必须是 figure 的第一个或最后一个子元素且最多一个;figure 不强制包含 figcaption;不要用 figure 包裹纯装饰内容或当作通用容器。

考察语义化标签的准确使用:figure 强调"自包含、可独立迁移",figcaption 提供标题说明,二者构成完整语义组,对 SEO 与可访问性树均有影响;还需掌握 figcaption 位置与数量的规范约束。

#
★★★

3. HTML inert 属性与对话框焦点管理的取舍(含 SPA 多对话框栈)

HTML inert 属性如何影响元素的可交互性与焦点管理?在 SPA 存在多对话框叠加时如何使用它治理焦点?

  • inert 对交互、焦点、Tab 顺序与可访问性树的系统影响
  • dialog.showModal 的原生惰性机制
  • 多对话框栈的焦点治理与归还策略

inert 使元素"惰性化":不可点击、不可聚焦、不响应键盘事件,并从 Tab 顺序与可访问性树中移除,但仍可见,常用于遮罩下使背景不可交互。多对话框场景中,dialog 通过 showModal() 打开时浏览器自动把其余页面设为惰性;多对话框叠加时手工维护对话框栈:只让栈顶对话框可交互,对其余对话框或背景设置 inert,避免焦点逃逸。关闭时移除 inert 并把焦点归还给触发元素或上一层对话框,保证键盘用户焦点不丢失。

考察 inert 对"可聚焦性"的系统性影响及其在复杂弹窗栈中的应用:与 dialog.showModal 的原生惰性机制配合,手工维护"栈顶可交互、其余 inert",并正确处理关闭后的焦点归还。

#
★★★

4. search/details[name]/selectlist 等新表单元素的可访问性差异

search、details[name]、selectlist 等新表单元素在可访问性上有哪些差异?工程中如何取舍?

  • search 容器的语义地标价值
  • details 原生的展开收起与 name 互斥
  • selectlist 的实验状态与降级策略

search 是语义化搜索容器(等效 role="search" 地标),不影响交互但改善辅助技术导航,可安全使用;details 提供原生展开/收起,带 name 属性后可实现互斥手风琴,其摘要对辅助技术有原生状态反馈,但键盘体验随浏览器而异;selectlist(Chromium 实验)把下拉按钮与 listbox 分离,可样式化,但 ARIA 映射仍在演进。取舍:search 与 details 已可用且渐进增强友好;selectlist 需特性检测并降级为原生 select 或自定义组件;自定义实现必须补充 role、aria-expanded、aria-controls 并保证键盘可达。

考察新一代表单控件可访问性成熟度的区分:search 已标准化且低风险,details[name] 可用但需验证状态反馈,selectlist 仍处实验期必须降级;回答体现"按成熟度分级采用"的工程判断。

#
★★★

5. 原生表单约束验证(required、pattern、type、:invalid)与自定义校验的协作

原生表单约束验证(required、pattern、type、:invalid)如何与自定义校验协作?协作的边界在哪里?

  • 声明式约束与 validityState 体系
  • setCustomValidity 融入原生验证
  • novalidate 关闭后的责任转移

原生验证由浏览器基于 HTML 约束(required、pattern、min/max、type 等)自动执行,提交时阻止非法数据并聚焦首个非法字段,:invalid/:valid 与 validityState 提供状态表达。自定义校验用 JS 计算业务规则,通过 setCustomValidity 写入消息并纳入原生体系。协作边界:原生验证只能表达声明式规则,跨字段、异步与服务端规则必须 JS 实现;使用 novalidate 关闭原生验证时需自行实现错误提示、焦点管理与表单状态。最佳实践是原生做基础约束、JS 做业务扩展,通过 validityState 与 :user-invalid 统一驱动渲染。

考察对约束验证 API 的分层理解:声明式规则交给浏览器,复杂业务规则用 setCustomValidity 融入原生体系;同时要讲清 novalidate 关闭后的责任转移,避免"原生或自定义二选一"的简单化回答。

<form id="f">
  <input id="pwd" required pattern=".{6,}" type="password">
</form>
<script>
  const pwd = document.getElementById('pwd');
  pwd.addEventListener('input', () => {
    if (pwd.value === '123456') {
      pwd.setCustomValidity('密码过于简单');
    } else {
      pwd.setCustomValidity('');
    }
  });
</script>
#
★★★

6. FormData、FormAssociated Custom Elements 与 submit 事件的关系

FormData、form-associated 自定义元素与 submit 事件之间存在怎样的关系?

  • 成功控件与 FormData 的构造规则
  • ElementInternals 让自定义元素参与表单
  • submit 事件作为拦截原生提交的钩子

表单提交时,浏览器收集成功控件构造 FormData:含 name 的控件值与文件等;form-associated 自定义元素通过 ElementInternals 提供 value 与表单状态,从而被 FormData 收集并参与提交与校验。submit 事件在用户触发提交且校验通过后触发,可被 preventDefault 拦截以改用 fetch 异步提交;处理器中可用 new FormData(form) 取最新数据,或用 submitter 判断触发来源。三者构成渐进增强的表单体系:FormData 承载数据、ElementInternals 让自定义元素参与、submit 是拦截原生提交的钩子。

考察对表单提交链路的整体认知:FormData 承载数据、ElementInternals 让自定义元素参与收集与校验、submit 事件提供拦截点;能说清三者协作即证明对现代表单机制有系统性理解。

#
★★★

7. 原生 requestSubmit() 与 form.submit() 的事件触发、可访问性边界差异

原生 requestSubmit() 与 form.submit() 在事件触发与可访问性边界上有哪些差异?如何选择?

  • submit() 绕过校验与事件的行为
  • requestSubmit() 模拟用户提交路径
  • submitter 参数与可访问性影响

form.submit() 直接执行提交,不触发 submit 事件、不做约束验证,相当于"强制提交",适合 JS 已自行完成校验后的编程提交;requestSubmit() 模拟用户点击提交按钮:触发 submit 事件、执行约束验证,失败时不提交并聚焦第一个非法字段,还支持传入 submitter 携带按钮的 name/value。可访问性上,requestSubmit 与真实用户提交路径一致,能被校验、监听器与无障碍机制正确处理;submit() 绕过验证与事件,易造成无效数据被提交或与监听器失联。工程上默认推荐 requestSubmit。

考察两个提交 API 的行为差异:submit() 绕过校验与 submit 事件,requestSubmit() 完整模拟用户提交路径并支持 submitter;选择正确 API 直接影响校验链与可访问性,是高频面试点。

#
★★★

8. enctype=multipart/form-data 与 FormData.entries 在文件+JSON 混合提交的工程价值

enctype=multipart/form-data 与 FormData.entries 在"文件+JSON"混合提交上有何工程价值?

  • multipart 是唯一能携带二进制的表单编码
  • FormData 混合字段与文件的构建方式
  • 与 base64 JSON 方案的体积与内存对比

multipart/form-data 是唯一能携带二进制文件的表单编码,浏览器把每个字段按 multipart 分块编码,服务端可流式解析,无需 base64 膨胀体积;FormData 提供 append 与 entries() 接口,天然支持同一请求中混合普通字段、JSON 文本与文件。工程价值:避免把文件转 base64 塞进 JSON 造成体积膨胀与内存压力;可 new FormData(form) 收集表单再 append JSON 字段;配合 fetch 发送时无需手动设置 Content-Type,浏览器自动附带 boundary。适合大文件、多文件与结构化字段混合场景。

考察对表单编码的深层理解:multipart 是文件传输的标准编码,FormData 让文件与 JSON 字段同请求混合且体积可控,无需手设 Content-Type;能讲清"为什么不用 base64 JSON"即抓住要点。

const fd = new FormData();
fd.append('meta', JSON.stringify({ title: '报表', tags: ['a'] }));
fd.append('file', fileInput.files[0]);
await fetch('/upload', { method: 'POST', body: fd });
#
★★★

9. novalidate 与 JS 校验回退方案的边界

novalidate 与 JS 校验回退方案的边界是什么?何时需要回退?

  • novalidate 关闭整表原生验证的语义
  • 关闭后的提示、焦点与阻断责任转移
  • 渐进增强的回退策略

novalidate 放在 form 上会关闭整表的原生约束验证(提交时不校验、不阻止),用于"完全由 JS 接管校验"或"存在原生无法表达的规则"的场景。边界:关闭原生验证后,错误提示 UI、焦点定位、aria-invalid/aria-describedby、表单状态与提交阻断都要自行实现;保留原生验证时浏览器提供免费的错误气泡与焦点管理,但样式与国际化受限。合理回退是渐进增强:默认依赖原生验证,需定制时读取 validityState 补充自定义 UI,必要时对个别输入用 setCustomValidity 或整表 novalidate 加 JS 校验。

考察 novalidate 的语义与责任转移:它只关掉原生验证,不提供替代 UI;回答需说明"何时回退、回退后谁负责提示、焦点与阻断",体现对表单验证完整链路的掌握。

#
★★★

10. HTML5 输入类型(email、url、tel、number、date)在不同浏览器下的体验差异

HTML5 输入类型(email、url、tel、number、date)在不同浏览器下的体验差异体现在哪些方面?如何降级?

  • 类型对移动端键盘与原生控件的影响
  • number、date 的跨端行为分裂
  • 特性检测与 text 兜底的降级策略

差异主要体现在键盘、校验与控件渲染:移动端 tel、email 唤起对应数字、邮箱键盘;number 的步进按钮与滚动行为在桌面端存在;date 在桌面 Chrome/Edge 有日历控件、Safari 桌面无原生日历,移动端各 WebView 差异更大;number 对千分位、科学计数法与 IME 支持不一致。降级策略:先声明 type 获得键盘与校验红利,再特性检测(input.type 是否回退为 text、showPicker 是否存在)决定是否引入自定义控件;对 date 类用只读加自定义选择器;始终保留 text 语义兜底并补充 pattern 与 JS 校验。

考察对"同一属性跨端行为分裂"的工程认知:类型决定键盘与原生控件,移动、桌面、WebView 差异大;降级关键是特性检测加 text 兜底加 JS 校验,而不是假设各端行为一致。

#
★★★

11. 语义化标签与文档大纲如何影响 SEO 与辅助技术

语义化标签与文档大纲如何影响 SEO 与辅助技术?实践中应遵循哪些准则?

  • 标题层级与文档大纲的关系
  • 地标元素对辅助技术导航的作用
  • 对 SEO 主题理解与富结果的影响

语义化标签为内容赋予机器可读含义:标题层级构成文档大纲,辅助技术用户可按标题导航;nav、main、article、section、aside 等地标帮助屏幕阅读器跳转区域,也帮助搜索引擎理解页面结构。对 SEO 而言,清晰大纲利于爬虫抽取主题,结构化语义配合 schema.org 可提升富结果机会;对辅助技术而言,正确的标题层级、地标与表单标签决定朗读顺序与操作效率。实践要点:避免跳级标题、用 div 冒充按钮、滥用 section;h1 应反映页面主题,保证大纲连续完整。

考察语义与"两大消费者"的关系:搜索引擎看重主题结构与富结果,辅助技术看重大纲导航与地标;回答应落到"结构即语义、大纲要连续、地标要准确"的实践准则,并强调用正确元素表达真实结构而非堆砌标签。

#
★★★

12. autocomplete 属性对密码管理器和自动填充的影响

autocomplete 属性如何影响密码管理器与自动填充?工程上应如何标注?

  • 常用令牌的语义(name、email、current-password、new-password 等)
  • 密码管理器对令牌的依赖
  • 自动填充对受控组件时序与样式的影响

autocomplete 告知浏览器字段语义,浏览器据此决定是否自动填充及填充哪类值:name 填姓名、email 填邮箱、current-password 与 new-password 管理密码、one-time-code 用于验证码、off 关闭自动填充。影响:密码管理器依赖令牌识别注册、登录与改密场景,错误标注会导致不弹保存提示或填错字段;自动填充会触发 change 事件与样式污染(:-webkit-autofill),需处理受控组件初始化时序;off 并不总是被遵守,敏感数据更应依赖服务端策略。规范做法是按真实语义标注字段,保持 name 与 id 稳定。

考察 autocomplete 令牌语义与浏览器行为:正确令牌让密码管理器与自动填充正常工作,错误标注会破坏保存与回填;同时要认清 off 的边界及自动填充对受控组件时序的影响。

#
★★★

13. 与移动端虚拟键盘的精细化控制

如何精细化控制移动端虚拟键盘?它与 type 属性有何区别?

  • inputmode 的取值与键盘布局映射
  • 与 type 的职责分离(语义校验 vs 键盘形态)
  • enterkeyhint 与 pattern 的配合

inputmode 提示浏览器为输入法显示哪种虚拟键盘布局,取值为 none、text、tel、url、email、numeric、decimal、search。与 type 不同,inputmode 只影响键盘布局,不改变语义与校验:type=text 加 inputmode=numeric 在移动端弹数字键盘但值仍可是任意文本;金额输入常用 decimal 获得带小数点的数字键盘。要点:按输入内容的"形态"而非字段类型选择 inputmode;配合 pattern 或 JS 限制非法字符;iOS 支持较好但部分第三方输入法可能忽略;搜索框用 search 显示"搜索"键,并配合 enterkeyhint 定制回车键文案。

考察 inputmode 与 type 的职责分离:type 管语义与校验,inputmode 只管键盘形态;能结合 decimal、search 与 enterkeyhint 说明移动端输入体验优化,即体现精细化控制的理解。

<input type="text" inputmode="decimal" pattern="[0-9]*[.]?[0-9]+" placeholder="请输入金额">
#
★★★

14. 表单字段聚焦时 preventScroll 的滚动行为治理

表单字段聚焦时,focus({ preventScroll: true }) 如何治理滚动行为?何时需要关闭自动滚动?

  • focus() 默认滚动到可视区的行为
  • preventScroll 的语义与适用场景
  • 旧浏览器兼容与 scroll-margin 配合

focus() 默认会把元素滚动到可视区域,在 SPA 中可能导致页面跳动或破坏既有滚动位置;focus({ preventScroll: true }) 可禁止这次聚焦引发的滚动,只移动焦点。适用场景:程序化恢复焦点(弹窗关闭后回到触发按钮、校验失败聚焦远处非法字段但不想跳页)、保持用户阅读位置、移动端避免软键盘唤起时页面被推挤。治理要点:优先用原生 preventScroll;兼容旧浏览器时聚焦前记录 scrollTop 并在聚焦后恢复;它只影响本次聚焦引发的滚动;配合 scroll-margin 可精细化锚点定位。

考察 focus 副作用的工程治理:默认聚焦会滚动到可视区,preventScroll 提供关闭通道;回答需覆盖适用场景、旧浏览器兼容与 scroll-margin 配合,体现对交互细节的把控。

#
★★★

15. patternMismatch/tooShort/rangeUnderflow 等校验状态在自定义错误 UI 的应用

patternMismatch、tooShort、rangeUnderflow 等校验状态在自定义错误 UI 中如何应用?

  • ValidityState 各布尔位的语义
  • 按错误类型生成差异化文案
  • 与 :user-invalid、aria-describedby 的配合

ValidityState 提供一组布尔属性精确描述字段为何非法:valueMissing(必填缺失)、typeMismatch(类型不符)、patternMismatch(不匹配 pattern)、tooShort/tooLong(长度越界)、rangeUnderflow/rangeOverflow(数值越界)、stepMismatch(步长不符)等。自定义错误 UI 的正确做法是按优先级读取这些标志生成差异化文案,并用 validity.valid 判断整体是否通过;配合 :user-invalid 仅在用户交互后展示错误;错误信息通过 aria-describedby 关联到字段,保证屏幕阅读器可感知。

考察 ValidityState 的细分诊断能力:不同布尔位对应不同错误类型,可用于生成精确文案与分级提示;结合 :user-invalid 与 aria-describedby 即构成完整的自定义错误 UI 方案。

const v = input.validity;
let msg = '';
if (v.valueMissing) msg = '该项必填';
else if (v.patternMismatch) msg = '格式不正确';
else if (v.rangeUnderflow) msg = '数值过小';
#
★★★

16. input[type=reset] 与受控组件冲突的边界与浏览器一致性

input[type=reset] 与受控组件(React/Vue)冲突的边界在哪里?浏览器行为一致性如何?

  • 原生 reset 恢复 HTML 默认值的语义
  • 与框架状态驱动模型的冲突点
  • reset 事件同步状态的工程方案

原生 reset 按钮触发 form.reset(),把表单控件恢复为 HTML 默认值(defaultValue/defaultChecked),且不触发 input/change 事件,也不触发 submit。与受控组件冲突的核心:受控组件用状态驱动 value,reset 后 DOM 值回到初始 HTML 属性但框架状态未同步,出现界面与数据模型的撕裂。处理方式:在表单 reset 事件中同步重置框架状态,或禁用原生 reset 按钮改用业务按钮手动清空;浏览器一致性上 reset 行为各端基本一致,但自定义元素的 reset 回调需 ElementInternals 配合。工程上更推荐状态驱动重置。

考察原生 reset 语义与受控组件状态模型的冲突:reset 只改 DOM 默认值且不发事件,框架状态不同步;回答需给出 reset 事件同步状态或禁用原生按钮的工程方案,并点明一致性边界。

#
★★★

17. 表单重置事件 reset 与字段默认值的关系

表单重置事件 reset 与字段默认值之间是什么关系?如何自定义重置行为?

  • 默认值来自 HTML 属性而非当前状态
  • reset 事件的可取消性
  • 自定义重置的监听与接管

form.reset() 把每个表单控件恢复为"默认值":text 类取 value 属性初始值,checkbox/radio 取 checked 属性,select 取选中项,textarea 取文本内容;重置过程不触发 input/change 事件,但会在表单上触发 reset 事件,且该事件可被 preventDefault 取消。自定义重置的常用做法:监听 reset 事件做状态清理或二次确认,需要完全接管时 preventDefault 后手动重置;注意 reset 不会清除 JS 动态设置的值,也不会重置浏览器自动填充内容;配合自定义组件时需在 ElementInternals 中处理表单重置回调。

考察 reset 事件与默认值机制的联动:默认值源自 HTML 属性,reset 事件可被拦截以自定义行为;能说清"reset 不发 input/change、默认值来自属性"即抓住本质。

#
★★★

18. 的 分组与原生搜索过滤(listbox popover 实验)

的 分组与原生搜索过滤(listbox popover 实验特性)如何提升长列表选择体验?

  • optgroup 的分组语义与无障碍影响
  • selectlist、listbox popover 等实验特性状态
  • 长列表场景的工程取舍

optgroup 通过 label 属性把选项分组,原生长列表下拉中显示分组标题,帮助用户快速定位,同时屏幕阅读器会朗读分组信息,改善可访问性;它不改变选项的提交值,只影响展示层级。原生搜索过滤方面,selectlist 与 listbox popover 等实验特性试图为 select 增加可搜索、可样式化的下拉面板,目前仅在 Chromium 部分版本可用。工程取舍:普通 select 加 optgroup 兼容性最好,适合静态分组;需要搜索、远程数据或自定义渲染时,通常自研组合框或使用组件库,并补充 aria-activedescendant、aria-selected 等属性。

考察对原生下拉能力层级的认知:optgroup 提供轻量分组且无障碍友好;搜索过滤仍依赖实验特性或自定义组件;回答体现"按需求选择原生或自研并补全 ARIA"的工程判断。

<select>
  <optgroup label="华东">
    <option>上海</option>
    <option>杭州</option>
  </optgroup>
  <optgroup label="华南">
    <option>深圳</option>
    <option>广州</option>
  </optgroup>
</select>
#
★★★

19. + method="dialog" 的表单提交与 close 返回值(returnValue)在关闭语义中的工程应用

+ method="dialog" 的表单提交与 close 返回值(returnValue)在关闭语义中有何工程应用?
  • method="dialog" 的提交即关闭机制
  • returnValue 作为关闭原因载体
  • 与校验、submit 事件的边界

dialog 内表单若声明 method="dialog",提交时不走网络,而是关闭对话框并把提交按钮的 value(无 value 则空串)写入 dialog.returnValue,随后触发 close 事件。工程价值:实现"确定/取消"语义的轻量关闭,无需 JS 监听 submit;returnValue 成为关闭原因的载体,可在 close 事件中读取以区分结果;与原生焦点管理配合(showModal 后焦点进入对话框,关闭后归还)。注意 method="dialog" 不触发约束验证与 submit 事件,需要校验时改用普通 method 配合 requestSubmit 或 JS 处理。

考察 dialog 的关闭数据通道:method="dialog" 让表单提交即关闭并回传 returnValue,close 事件读取结果;同时需点明其绕过校验与 submit 事件的边界,避免误用。

<dialog id="d">
  <form method="dialog">
    <button value="ok">确定</button>
    <button value="cancel">取消</button>
  </form>
</dialog>
<script>
  d.addEventListener('close', () => console.log(d.returnValue));
</script>
#
★★★

20. 的 wrap 属性与 IME 中文输入下的换行行为

的 wrap 属性与 IME 中文输入下的换行行为如何理解?
  • soft/hard/off 对提交值的影响
  • IME 组合状态与 composition 事件
  • 中文输入场景的工程处理

textarea 的 wrap 属性控制软换行:wrap="soft"(默认)只在视觉上折行,提交值中不含软换行;wrap="hard" 在折行处插入换行符(需配合 cols 生效),提交值包含硬换行;wrap="off" 不折行,出现横向滚动。IME 中文输入下,输入法组词过程中的候选状态不应触发 value 变化,浏览器在 compositionend 前不提交最终值;回车键在 IME 组词时用于确认候选而非换行。工程要点:按提交需求选择 wrap 模式,统计行数与字数以实际 value 为准;自定义换行或按键逻辑需监听 composition 事件。

考察 soft/hard/off 对提交值的影响与 IME 组合态下的事件特殊性:软换行不进值、硬换行进值,IME 组词期不产生最终 value;回答体现对中文输入场景的细腻认知。

#
★★★

21. 事件捕获、目标和冒泡阶段的执行顺序

事件捕获、目标和冒泡阶段的执行顺序是怎样的?addEventListener 的 capture 参数如何影响?

  • 三阶段传播模型
  • capture 参数与注册阶段
  • stopPropagation 与 preventDefault 的区别

DOM 事件传播分三阶段:捕获(capture)从 window 沿树向下到目标,目标(target)阶段在目标节点触发,冒泡(bubble)从目标沿树向上回到 window。默认 addEventListener 注册在冒泡阶段(capture=false);capture=true 注册在捕获阶段,目标节点上的监听器不论 capture 与否都在目标阶段按注册顺序触发。stopPropagation 阻止后续传播,stopImmediatePropagation 额外阻止同节点剩余监听器;preventDefault 不阻止传播,只取消默认动作。理解顺序的价值在于事件委托、捕获拦截与第三方库事件冲突排查。

考察事件传播三阶段模型这一高频考点:捕获自上而下、冒泡自下而上、目标阶段居中;capture 参数决定注册阶段,stopPropagation 与 preventDefault 职责不同,需清晰区分。

<div id="outer"><button id="inner">点我</button></div>
<script>
  const log = (s) => console.log(s);
  document.getElementById('outer').addEventListener('click', () => log('outer capture'), true);
  document.getElementById('outer').addEventListener('click', () => log('outer bubble'), false);
  document.getElementById('inner').addEventListener('click', () => log('inner'), false);
</script>
#
★★★

22. 标题层级、地标元素与可访问性树的关系

标题层级、地标元素与可访问性树之间是什么关系?如何构建健康的可访问性树?

  • 可访问性树的派生来源
  • 标题 level 与 landmark 角色映射
  • 隐藏方式对可访问性树的影响

可访问性树由浏览器从 DOM 树派生,为辅助技术提供语义化视图;标题(h1-h6)在树中体现为 heading 角色并携带 level 属性,构成大纲导航基础;地标元素(nav、main、header、footer、aside、form、search)映射为 landmark 角色,支持按区域跳转。可访问性树忠实反映语义而非视觉:display:none 与 hidden 不在树中,aria-hidden 显式移除,而视觉隐藏但可读的文本仍保留;CSS 类不会改变角色。构建健康可访问性树需保证标题层级连续、地标清晰且 main 唯一、交互元素有正确角色与名称、表单控件与 label 关联。

考察语义如何在可访问性树中落地:标题带 level、地标映射 landmark、隐藏方式决定是否入树;回答需连接"写对 HTML"与"生成健康可访问性树"的因果链,并说明 display:none、hidden 与 aria-hidden 对可访问性树的差异化影响。

#
★★★

23. 事件委托的实现原理与性能边界

事件委托的实现原理是什么?其性能边界在哪里?

  • 冒泡机制与单一监听器分发
  • 不冒泡事件的特殊处理
  • target 归一化与高频事件代价

事件委托利用事件冒泡:在公共祖先上注册一次监听器,通过 e.target(或 composedPath)判断实际触发元素并分发逻辑,避免为大量同类子元素逐个绑定监听器。收益:减少监听器数量,降低内存与初始化开销,动态新增子元素无需重新绑定。边界与代价:只有冒泡事件可委托,focus、blur、scroll、resize 等需用捕获阶段或 focusin/focusout 处理;每次事件都要做 target 判断,高频事件下分发成本放大;e.target 可能是深层子元素,需 closest 归一化;与 Shadow DOM 组合时需考虑 composedPath。它适合列表、表格、菜单等同类节点多的场景。

考察对事件委托机制与代价的双向理解:收益在减少监听器与支持动态节点,边界在不冒泡事件、target 归一化与高频分发成本;能列举适用场景并说明 closest 归一化等细节,即体现工程判断力。

document.querySelector('#list').addEventListener('click', (e) => {
  const item = e.target.closest('li');
  if (item) console.log(item.dataset.id);
});
#
★★★

24. DOM 操作的批量更新与回流/重绘成本控制

DOM 操作的批量更新如何控制回流(reflow)与重绘(repaint)成本?

  • 回流与重绘的触发关系
  • 合并读写避免 layout thrashing
  • 批量插入与合成器属性

回流指浏览器重新计算元素几何(布局),重绘指重新绘制像素;回流必然伴随重绘,且一个节点变化可能影响整棵布局树,是性能主要瓶颈。批量更新策略:合并读写,先集中读取布局属性(offsetWidth、getBoundingClientRect 等)再统一写入,避免"读-写交替"强制多次同步布局(layout thrashing);用 DocumentFragment 或一次性 innerHTML 批量插入节点;用 CSS 类切换代替多次修改;用 transform、opacity 等合成器属性减少布局影响;必要时用 display:none 隐藏后再批量操作。现代框架的虚拟 DOM 批量 diff 也遵循同一思想。

考察对渲染管线中回流/重绘成本的系统认知:合并读写、批量插入、减少布局依赖是三大抓手;能解释 layout thrashing 与合成器属性(transform/opacity)即体现深度。

#
★★★

25. Element.animate()(Web Animations API)与 CSS 动画的并行与冲突解决

Element.animate()(Web Animations API)与 CSS 动画如何并行运行?冲突时如何解决?

  • WAAPI 与 CSS 动画的统一合成体系
  • 同属性冲突的优先级规则
  • getAnimations/cancel 与 composite 治理

Element.animate() 创建的 Animation 与 CSS 动画共用同一动画合成体系(WAAPI 是底层标准),可并行叠加:多个动画可同时作用于不同属性,或同一属性由多个动画分层控制。优先级上,同一属性被多个来源命中时按特定性排序:CSS 过渡低于 CSS 动画,内联 style 的动画(Element.animate 返回的动画)通常覆盖 CSS 动画与样式表规则;动画完成后若无 fill 模式,效果被移除。冲突解决:用 getAnimations() 检查已有动画,用 cancel() 取消旧动画再创建;动画间叠加可用 composite 操作控制。工程上常用"JS 接管过渡态、CSS 负责常态"的分工。

考察 WAAPI 与 CSS 动画的统一合成模型:并行叠加可行,同属性冲突按优先级与 composite 决定;回答需给出 getAnimations/cancel 与 composite 的冲突治理手段。

#
★★★

26. scrollIntoView({ behavior, block, inline }) 与 scroll-behavior: smooth 的协作

scrollIntoView({ behavior, block, inline }) 与 scroll-behavior: smooth 如何协作?有哪些注意点?

  • block/inline 的对齐控制
  • JS behavior 与 CSS 默认值的优先级
  • smooth 的异步性与 reduced-motion

scrollIntoView 把元素滚动到可视区,block 控制垂直对齐(start/center/end/nearest),inline 控制水平对齐;behavior 可为 auto(跟随 CSS 的 scroll-behavior 设置,默认为瞬间)或 smooth(平滑)。scroll-behavior: smooth 是 CSS 级默认,影响所有未显式指定 behavior 的滚动操作,JS 显式传 behavior: 'instant' 可强制瞬间滚动、覆盖 CSS 平滑设置(传 'auto' 则仍遵循 CSS 值)。协作要点:长页面用平滑滚动改善体验,但用户偏好 reduced-motion 时应回退为 auto;block: 'nearest' 适合列表焦点跟随;smooth 滚动是异步的,紧跟其后的位置读取会拿到旧值,需监听 scrollend 处理。

考察滚动 API 与 CSS 的优先级协作:JS 显式 behavior 覆盖 CSS 默认,block/inline 控制对齐,smooth 的异步性与 reduced-motion 是工程陷阱;回答体现对滚动细节的完整把握。

#
★★★

27. MutationObserver 与 IntersectionObserver 联动实现无限滚动与虚拟列表的取舍

MutationObserver 与 IntersectionObserver 如何联动实现无限滚动与虚拟列表?各有哪些取舍?

  • IO 的可见性判断与哨兵元素
  • MO 对动态 DOM 变更的感知
  • 异步回调、观察器数量与节流边界

IntersectionObserver 观察目标与视口(或容器)的交叉状态,适合实现"滚动到底部加载"的无限滚动(观察底部哨兵元素)与虚拟列表的可见项渲染;MutationObserver 观察 DOM 树变化,可监测列表项增删以重新校正哨兵与观察目标。联动典型做法:IO 驱动按需渲染,MO 监听渲染结果的插入与移除,维持观察器与占位元素同步。取舍:IO 回调异步且基于帧,滚动极快时可能延迟;MO 在频繁变更时回调密集,需节流合并;虚拟列表还可结合 ResizeObserver 测量项尺寸。合理分工是"可见性交给 IO、DOM 变更感知交给 MO、尺寸变化交给 RO"。

考察两个观察器 API 的分工与协作:IO 管可见性与按需加载,MO 管 DOM 变更后的校正;回答需点明异步回调、观察器数量与节流等性能边界,并延伸到虚拟列表的完整方案。

const sentinel = document.querySelector('#sentinel');
const io = new IntersectionObserver((entries) => {
  if (entries[0].isIntersecting) loadMore();
});
io.observe(sentinel);
#
★★★

28. Speculation Rules API 与现有 HTML5 语义的协同

Speculation Rules API 与现有 HTML5 语义如何协同?它解决什么问题?

  • prefetch/prerender 规则声明
  • 依赖真实链接结构与语义导航
  • 预渲染副作用与服务端配合

Speculation Rules API 通过

考察新导航性能 API 与传统语义的关系:speculationrules 依赖真实链接结构(语义化导航),与 prefetch/prerender 互补;回答体现对预渲染副作用与服务端配合的理解。

<script type="speculationrules">
{
  "prefetch": [{ "source": "list", "urls": ["/a", "/b"] }]
}
</script>
#
★★★

29. MutationObserver、IntersectionObserver、ResizeObserver 的能力与场景

MutationObserver、IntersectionObserver、ResizeObserver 各自的能力与典型场景是什么?

  • MO 观察 DOM 结构变化
  • IO 观察可见性交叉
  • RO 观察元素尺寸变化

三者都是基于回调的观察 API,避免轮询。MutationObserver 观察 DOM 树变化(节点增删、属性、字符数据),用于监听动态内容、同步框架状态;IntersectionObserver 观察元素与视口/容器的交叉比例,用于懒加载、无限滚动、曝光埋点;ResizeObserver 观察元素盒尺寸变化,用于自适应布局、图表重绘。共同特点:回调异步批量触发、可配置观察目标与阈值、需要 disconnect 释放。工程上常组合:虚拟列表用 IO 判断可见性、MO 校正节点、RO 测量尺寸。

考察三大 Observer 的分工边界:MO 管 DOM 结构、IO 管可见性、RO 管尺寸;能各举典型场景并说明批量异步回调、disconnect 释放与组合用法,即证明对观察者模型的系统掌握。

#
★★★

30. ResizeObserver 的 box 选项 与现代框架(React/Vue)的协作边界

ResizeObserver 的 box 选项(content-box/border-box/device-pixel-content-box)如何理解?与现代框架协作的边界是什么?

  • 三种盒模型的测量差异
  • device-pixel-content-box 的亚像素精度
  • 框架内更新循环与生命周期管理

ResizeObserver 的 box 选项决定观察哪种盒:content-box(默认,内容盒,不含 padding/border)、border-box(边框盒)、device-pixel-content-box(设备像素级内容盒,适合精确到物理像素的测量,避免亚像素误差)。现代框架协作边界:框架响应式渲染会改变 DOM 并触发 RO 回调,若在回调中再改状态可能造成"测量-更新"循环;解决方式是合并多次回调、用 rAF 节流,或在回调里只记录尺寸由框架统一更新;RO 回调发生在布局之后、绘制之前;组件卸载时必须 disconnect 观察器防止泄漏。

考察 box 选项的精度语义与框架协作的坑:不同盒影响测量结果,框架内更新要防循环并管理生命周期;能讲清 device-pixel-content-box 与卸载清理即体现工程深度。

#
★★★

31. 语义化结构与原生表单校验如何协同构建可访问表单

语义化结构与原生表单校验如何协同构建可访问表单?

  • label、fieldset 的结构语义
  • 原生校验的无障碍红利
  • aria-describedby 与 aria-invalid 的状态联动

可访问表单的核心是"语义完整、键盘可达、状态可感知"。语义结构上:每个控件用 label 显式关联,fieldset+legend 分组相关字段,用 aria-describedby 关联帮助与错误文本;原生校验提供免费的无障碍红利:提交时浏览器聚焦非法字段并弹出可朗读的错误提示。协同要点:用原生约束承载基础规则,复杂规则用 setCustomValidity 融入同一体系,保证 aria-invalid 与 validityState 一致;错误信息必须关联 aria-describedby;提供多种输入途径(键盘 Tab、回车提交、inputmode 键盘优化);不依赖颜色单独传达错误。

考察语义、校验与无障碍三者的集成:label/fieldset 建立结构语义,原生校验提供聚焦与提示红利,aria 属性让状态可感知;回答需覆盖错误关联、状态同步与多通道传达。

<label for="email">邮箱</label>
<input id="email" type="email" required aria-describedby="e-hint e-err">
<span id="e-hint">用于登录</span>
<span id="e-err" role="alert"></span>
#
★★★

32.

无障碍地标(

、 、 、 )与 ARIA landmark 在 SPA 单页应用中的回退方案

无障碍地标与 ARIA landmark 在 SPA 单页应用中有哪些回退方案?

  • 路由切换后焦点与标题不更新的问题
  • 主内容聚焦与 aria-live 播报
  • landmark 兜底与动态区域标注

SPA 中多个路由共享同一外壳,地标元素常驻,切换路由时内容区更新。主要问题:路由切换后屏幕阅读器焦点与标题不更新;多个异步组件可能产生重复 main 或缺失地标。回退方案:每个路由维护唯一 h1 与 document.title,切换后聚焦到主内容容器(tabindex="-1")并配合 aria-live 播报"页面已切换";用 role="main" 兜底;对动态注入区域显式标注 landmark 并加 aria-label;组件卸载时清理 aria-hidden 与 live region。核心是让 SPA 的"虚拟导航"在可访问性上等价于 MPA 的真实导航。

考察 SPA 无障碍的关键痛点:内容更新但焦点、标题、大纲不随之更新;回答需给出标题同步、主内容聚焦、aria-live 播报与 landmark 兜底的具体回退方案,并说明组件卸载时的清理义务。

#
★★★

33. 、、 三种状态元素的语义与无障碍朗读差异

、、 三种状态元素的语义与无障碍朗读差异是什么?

  • output 表达计算结果
  • progress 表达任务进度
  • meter 表达区间度量

output 表示计算结果,可配合 for 属性引用参与计算的控件,语义角色为 status(部分浏览器映射),结果变化时适合用 aria-live 播报;progress 表示任务进度,max 与 value 决定百分比,角色为 progressbar,辅助技术朗读"百分比",适合加载、上传进度;meter 表示已知范围内的度量值,如电量、评分,角色为 meter,带 min/max/low/high/optimum 表达好坏区间。朗读差异:progress 强调"完成比例",meter 强调"数值是否处于优/良/差区间",output 强调"结果值";三者都不应被用于纯装饰,且都需要文本标签或 aria-label 补充上下文。

考察三个状态元素语义分工:output 表达结果、progress 表达进度、meter 表达区间度量;能区分其 ARIA 角色与朗读侧重,并说明与 aria-live 的配合,即体现对语义精确性的把握。

<progress max="100" value="60">60%</progress>
<meter min="0" max="100" low="30" high="80" value="65">中</meter>
#
★★★

34. 在国际化与日历系统下的解析策略与微格式(microformats)联动

在国际化与日历系统下的解析策略是什么?如何与微格式联动?

  • datetime 的规范时间语法
  • 公历基准与国际化的关系
  • 与微格式、结构化数据的联动

time 元素把人类可读时间与机器可读 datetime 绑定,datetime 须符合 HTML 规范的时间语法(完整日期、本地时间、时区偏移、时长、周/月等),浏览器不解析展示值,只把 datetime 暴露给程序;这解决了同一时间在不同语言写法下语义一致的国际化问题。日历系统方面,HTML 规范主要基于公历;农历、佛历等需要额外扩展或使用 Intl.DateTimeFormat 的 calendar 选项在展示层实现,datetime 仍建议用公历。与微格式联动:hCalendar、h-event 等常配合 datetime 为事件提供机器可读数据,便于日历应用导入;schema.org Event 也常读取该属性。

考察 time 的机器可读价值:datetime 语法规范化解决多语言同一时刻的表示,与微格式/schema 联动服务日历导入与 SEO;回答需点明公历基准与 Intl 展示层扩展。

#
★★★

35. 、 、 的语义差异与误用场景

、 、 的语义差异是什么?常见误用场景有哪些?
  • article 的独立分发语义
  • section 的主题分组语义
  • aside 的补充关联语义

article 表示可独立分发或复用的完整内容单元(博文、新闻、评论、组件卡片),离开页面上下文仍自洽;section 表示文档中一个主题分组,通常带标题;aside 表示与主内容松散相关的内容(侧边栏、相关链接、引用说明)。常见误用:用 section 包裹纯样式容器(应选 div)、用 article 包裹没有独立语义的碎片、在 section 中省略标题、把整页塞进 aside、用 div 冒充三者。规范要点:article 可嵌套(评论在文章内)、section 需要主题标题、aside 用于补充性内容;选择顺序是"先语义后样式",无法归入三者时用 div。

考察三大语义容器的边界:article 强调独立分发、section 强调主题分组、aside 强调补充关联;能识别常见误用并给出选型依据,即体现对内容模型的准确理解。

#
★★★

36. role 属性补充语义时,如何避免与原生语义冲突

role 属性补充语义时,如何避免与原生语义冲突?

  • role 覆盖原生语义但不改行为
  • 原生优先与 ARIA 第一规则
  • 角色、行为、属性三位一体

role 会覆盖元素的原生语义角色,但不会改变其行为与外观;冲突的根源在于"声明了角色却没有对应行为"或"覆盖了不该覆盖的原生语义"。避免冲突的原则:优先使用原生语义元素(button、nav、main),仅在无法满足时用 role 补充;遵循 ARIA 第一规则:不要给原生有语义的元素随意加角色,如给 button 加 role="link" 会让屏幕阅读器按链接朗读但键盘行为仍是按钮;角色必须搭配完整属性(role="combobox" 需 aria-expanded、aria-controls 等);不用 role 给 div 冒充交互元素却无键盘事件与焦点管理;避免冗余声明。核心是"角色、行为、属性"三位一体。

考察 ARIA 使用的核心准则:role 只改语义不改行为,滥用会造成"说的和做的不一致";回答需落到原生优先、角色行为属性一致、避免冗余声明三条实践,并说明与键盘事件的配套义务。

#
★★★

37. HTML 实体与 Unicode 字符在源码与展示中的转义边界

HTML 实体与 Unicode 字符在源码与展示中的转义边界是什么?

  • 实体用于结构字符的转义
  • Unicode 字符在 UTF-8 源码中直接书写
  • 不同上下文(文本、属性、脚本)的规则差异

HTML 实体(如 <、&、©)用于在源码中表示特殊字符:小于号、大于号、引号、& 等会被解析器视为标记结构,必须转义才能作为文本展示;而普通 Unicode 字符(如中文、©、→)可直接写入 UTF-8 源码,无需转义。转义边界:元素文本中 < 与 & 必须转义;属性值中引号与 & 需转义;script 与 style 中 HTML 实体不解析,转义反而无意义。工程建议:保持文件 UTF-8,普通字符直接书写,仅对结构字符转义;用模板或框架的自动转义防止 XSS,而不是手工拼实体。

考察转义的分层边界:HTML 解析层对结构字符转义,Unicode 直接书写;不同上下文(文本、属性、脚本)规则不同;回答需强调框架自动转义与源码 UTF-8 的现代实践。

#
★★

38. HTML 解析器在容错时的隐式标签闭合规则

HTML 解析器在容错时遵循哪些隐式标签闭合规则?为什么浏览器能容忍不规范 HTML?

  • 隐式闭合的典型场景(li、p、表格补齐)
  • 容错设计源于历史兼容
  • 显式闭合的工程必要性

HTML 解析器基于 WHATWG 规范的状态机算法,遇到不规范标签时按"隐式闭合"规则容错:例如 li、p、td 等列表或表格项遇到下一个同类标签时自动闭合前一个;p 遇到块级元素(div、ul)时自动闭合;tr 会自动补齐 tbody;br 等空元素不闭合;解析错误还会触发 foster parenting。容忍设计源于历史兼容:浏览器必须能渲染遗留网页,所以解析器以"不崩溃、尽力恢复"为目标,且规则被标准化以保证各浏览器行为一致。工程影响:依赖隐式闭合会让 DOM 结构与预期不符,应显式闭合标签;解析差异仍是 XSS 与布局问题的重要来源。

考察对解析器容错模型的认知:隐式闭合是标准化状态机的一部分,源于历史兼容设计;回答需举例说明 li、p、表格补齐等隐式闭合规则,并说明显式闭合标签、防范解析差异风险的工程必要性。

#
★★

39. 与动态模板字符串在 XSS 防护上的差异

与动态模板字符串在 XSS 防护上有何差异?

  • template 的惰性解析与不执行脚本
  • 字符串拼接注入的 XSS 风险
  • 转义、净化与 CSP 的配合

是 HTML 元素,其内容被解析为独立的 DocumentFragment,默认不渲染、不执行脚本与资源加载,适合声明静态结构并在运行时克隆;由于内容由浏览器解析,插入模板内的数据若未转义仍可能构成 XSS。动态模板字符串只是字符串拼接,最终经 innerHTML 注入时浏览器按 HTML 解析,用户可控内容一旦包含 script、事件属性、javascript: URL 即触发 XSS。差异核心:template 提供"文档片段加惰性解析"的隔离,但仍需转义;字符串模板无防护,必须配合转义与净化(如 DOMPurify)或框架的自动转义。

考察两种模板机制的 XSS 边界:template 惰性解析且不执行脚本,但插入数据仍需转义;字符串模板无防护,需转义、净化加 CSP;回答需强调"转义是义务,机制不是保险"。

<template id="row">
  <li class="item"></li>
</template>
#
★★

40.

标签的现代语义权重与视觉表现差异

标签的现代语义权重与视觉表现有何差异?

  • em 语气强调与 strong 重要性强调的区分
  • small 的附属细则语义
  • 语义与视觉表现的可分离性

em 表示语气强调(stress emphasis),在句中改变语调用意,屏幕阅读器会调整朗读重音;strong 表示重要性强(strong importance),如警告、关键步骤,语义权重比 em 更高;small 表示"附属细则",如免责声明、版权、法律文本,语义上不是"小号字"而是次要内容。现代语义权重排序 strong 高于 em;视觉上默认 strong 加粗、em 斜体、small 小字号,但可用 CSS 覆盖,且不应为了视觉加粗或斜体而滥用。工程上根据"强调程度、重要性、附属性质"选择对应标签,配合 CSS 定制视觉。

考察对强调类标签的现代语义认知:em 语气强调、strong 重要性强调、small 附属细则,权重与视觉表现可分离;回答需纠正"small 只是小字、strong 只是加粗"的旧认知。

#
★★

41. / 在 CJK 注音排版的浏览器支持矩阵

/ 在 CJK 注音排版的浏览器支持矩阵如何?工程上如何处理?

  • ruby/rt/rp 的结构语义
  • ruby-position、ruby-align 的支持差异
  • rp 回退与特性检测策略

ruby 用于 CJK 注音(拼音、假名、谚文)排版:ruby 包裹基础文本,rt 提供注音,rp 为不支持 ruby 的浏览器提供括号回退。支持矩阵:现代 Chrome、Edge、Firefox、Safari 均支持 ruby 基础语法与 rp 回退;差异在于 ruby-position(注音位于上方还是右侧)、ruby-align(对齐方式)等 CSS 属性的实现程度,复杂 ruby(rtc、双行注音)在部分浏览器支持不全。工程处理:始终提供 rp 括号回退;用特性检测决定是否应用 ruby-position 等进阶样式;注音文本用 lang 标注语言;动态生成时保持 rp/rt 结构完整。

考察 ruby 语义结构与其 CSS 支持差异:rp 回退是兼容关键,ruby-position/align 等属性跨浏览器不一致;回答体现"基础可用、进阶需检测"的兼容策略。

<ruby>汉<rp>(</rp><rt>hàn</rt><rp>)</rp></ruby>
#
★★

42. Content-Security-Policy 报告的 securitypolicyviolation 事件在前端埋点的应用

Content-Security-Policy 报告的 securitypolicyviolation 事件在前端埋点中有哪些应用?

  • CSP 违规事件的对象字段
  • 在线统计与策略调优
  • 埋点代码自身符合 CSP

CSP 通过策略指令限制资源加载与执行;当页面违反策略时,浏览器除了可向 report-uri/report-to 上报外,还会在 document 上派发 securitypolicyviolation 事件,事件对象携带 blockedURI、violatedDirective、sourceFile 与 lineNumber 等字段。前端埋点应用:实时统计 CSP 违规,发现线上策略误伤(第三方脚本被拦、内联样式被禁)并据此调整策略;把违规与用户行为、版本关联,定位问题发布;检测潜在攻击迹象。注意事件只在违反策略的文档触发;埋点代码本身要符合 CSP。

考察对 CSP 违规观测链路的理解:securitypolicyviolation 事件携带违规详情,可做实时埋点与策略调优;回答需强调上报代码自身符合策略,体现安全工程的闭环思维。

document.addEventListener('securitypolicyviolation', (e) => {
  sendReport({ blocked: e.blockedURI, directive: e.violatedDirective });
});
#
★★

43. output 与 progress 元素在异步结果可视化的语义价值

与 元素在异步结果可视化中有何语义价值?

  • progress 表达进行中进度
  • output 表达完成结果
  • 与 aria-live、aria-busy 的反馈闭环

异步操作(上传、搜索、计算)中,output 与 progress 提供"有语义的反馈容器":progress 表达过程状态——max/value 描述完成度,适合加载条、上传进度、批量任务;output 表达结果值——把计算或异步返回的结果展示出来,并用 for 关联产生该结果的控件。相比普通 div/span,其价值在于:辅助技术能识别 progressbar 角色并朗读进度,output 的变化可配合 aria-live 播报结果,无需手工维护复杂的 aria 状态。实践上把 progress 用于"进行中",把 output 用于"已完成的结果",配合 aria-busy 标记容器繁忙状态,形成完整的异步反馈闭环。

考察两个元素在异步场景的分工:progress 表达进行中进度,output 表达完成结果;能结合 aria-live、aria-busy 说明无障碍反馈闭环,即体现语义价值的落地。

#
★★

44. 表单字段 form-associated 自定义元素的可观察性与 React 受控组件协作

表单字段 form-associated 自定义元素的可观察性如何与 React 受控组件协作?

  • attachInternals 与 ElementInternals
  • 事件向外发、属性向内收的同步契约
  • setFormValue 与原生表单收集

form-associated 自定义元素通过 attachInternals() 获得 ElementInternals,可设置 value、表单状态、校验消息与表单所有者,从而被原生表单收集;"可观察性"指其内部状态变化能通过 MutationObserver 或 FormData 收集时机被外部感知,但默认不触发 React 的受控更新。协作要点:自定义元素需在内部状态变化时派发可冒泡的 input/change 事件并携带 value,React 受控组件才能感知;受控模式下自定义元素要实现 attributeChangedCallback 同步内部状态,避免竞态;配合 setFormValue 让原生表单拿到最新值。

考察自定义表单元素与框架受控模型的对接:内部状态需通过事件暴露给 React,受控属性需通过 attributeChangedCallback 回流;能讲清双向同步契约即抓住协作本质。

#
★★

45. 表单的 autocomplete Token(section-、billing street-address)

表单 autocomplete Token(section-、billing、street-address)的语义与作用是什么?

  • billing/shipping 的场景分组
  • section- 前缀区分同名分组
  • 地址字段令牌体系

autocomplete 令牌分为结构化令牌与分组令牌:billing、shipping 表示同一字段在不同地址场景(账单地址、收货地址)中的语义,配合 section- 前缀可把多个同名分组区分开;street-address、address-line1、postal-code、country 等构成地址字段的完整语义体系,浏览器据此跨字段自动填充。作用:让浏览器把表单与用户资料正确映射,实现整表自动填充;密码管理器与地址簿插件依赖这些令牌识别字段;减少重复输入,提升转化率。实践要点:按字段真实语义标注完整令牌链(前缀加字段名),保持同一表单内令牌一致,避免语义漂移导致填充错位。

考察 autocomplete 令牌体系的层次:billing/shipping 区分场景,section- 区分分组,street-address 等描述字段语义;能说明令牌如何驱动整表自动填充即抓住要点。

#
★★

46. inputmode 与 autocomplete 属性如何协同提升移动端输入效率

inputmode 与 autocomplete 属性如何协同提升移动端输入效率?

  • inputmode 控制键盘形态
  • autocomplete 控制自动填充
  • 协同场景与降级兜底

inputmode 决定移动端虚拟键盘的形态(numeric、decimal、email、search 等),autocomplete 决定浏览器是否及如何自动填充字段值,二者从不同维度优化输入:inputmode 减少击键(数字字段直接弹数字键盘),autocomplete 减少重复输入。协同要点:按字段的数据形态选择 inputmode(金额用 decimal、验证码用 numeric),同时用 autocomplete 标注语义(one-time-code、name、email);注意 iOS 对 one-time-code 有短信提取优化,而 inputmode 会被部分第三方输入法忽略,仍需 JS 校验兜底。

考察两个属性从"键盘形态"与"自动填充"两条路径优化移动端输入:inputmode 减击键、autocomplete 减重复输入;能举例说明协同与降级即体现工程细节。

#
★★

47. pattern 属性使用正则约束输入格式时,如何处理中文、Unicode 与跨浏览器的兼容差异

pattern 属性使用正则约束输入格式时,如何处理中文、Unicode 与跨浏览器的兼容差异?

  • ASCII 字符类与 Unicode 范围的差异
  • v/u 标志与隐式锚定
  • 特性检测与 JS 兜底

pattern 的正则由浏览器以 v(或旧 u)标志编译,处理 Unicode 时注意:字符类 [a-z] 只匹配 ASCII,中文等需用 \u4E00-\u9FFF 或 \p{Script=Han}(需 v 标志支持,部分浏览器受限);默认正则对输入值整体匹配(隐式锚定),点号不匹配换行。跨浏览器差异:不同浏览器对 Unicode 属性转义的支持不同,旧浏览器可能把非法模式当作"无 pattern";pattern 校验只触发 patternMismatch,不阻止输入本身。工程建议:优先用 \uXXXX 显式范围保证兼容;复杂规则配合 JS 侧校验并统一错误文案;先做特性检测,避免依赖未支持的特性。

考察 pattern 正则的 Unicode 语义与兼容性:ASCII 字符类不匹配中文、v/u 标志支持不均、隐式锚定与换行规则;回答体现"显式范围加 JS 兜底"的兼容策略。

#
★★

48. formaction 与 formmethod 属性在多提交按钮场景下如何实现同一表单不同行为

formaction 与 formmethod 属性在多提交按钮场景下如何实现同一表单不同行为?

  • 按钮级表单覆盖属性
  • submitter 区分触发源
  • 草稿/发布与校验差异的工程场景

formaction 与 formmethod 可覆盖表单级 action/method,用于同一表单内不同按钮走不同提交目标与方式:如"保存草稿"走 /draft 而"正式发布"走 /publish;它们也支持 formenctype、formnovalidate、formtarget 等覆盖属性。提交时,被点击按钮的覆盖属性优先生效,提交事件中可用 event.submitter 拿到触发按钮及其属性。工程要点:给每个按钮命名便于服务端区分;JS 拦截提交时读取 submitter 的 formAction/formMethod 属性;formnovalidate 可让"草稿"按钮跳过校验。

考察表单覆盖属性的按钮级语义:formaction/formmethod 按触发按钮覆盖表单默认值,配合 submitter 区分来源;回答需覆盖草稿/发布、搜索跳转等典型场景与 JS 读取方式。

<form action="/save" method="post">
  <button formaction="/draft" formnovalidate>存草稿</button>
  <button formaction="/publish">发布</button>
</form>
#
★★

49. 使用 fieldset 与 legend 嵌套结构对辅助技术与屏幕阅读器朗读体验的提升

使用 fieldset 与 legend 嵌套结构如何提升辅助技术与屏幕阅读器的朗读体验?

  • legend 作为朗读上下文前缀
  • 嵌套分组与单 legend 规范
  • 整组禁用/重置的联动

fieldset 把相关表单控件分组,legend 提供分组标题;屏幕阅读器在朗读组内每个控件时,会把 legend 文本作为组前缀一并读出(如"收货地址:省 编辑框"),让用户理解字段所属上下文,这在多组相似字段(账单/收货地址、多个联系人)时尤其重要。规范要点:一组字段只用一个 legend,且 legend 应是 fieldset 的第一个子元素;不要用 fieldset 包裹无关联字段,也不要为单一字段滥用;可嵌套表达层级,但过深分组会增加朗读负担。除提升朗读外,fieldset 还能统一禁用或重置一组控件,并支持键盘导航分组。

考察 fieldset/legend 的朗读机制:legend 作为组前缀伴随组内每个控件朗读;回答需说明嵌套、禁用联动与"避免滥用"的边界,体现对无障碍细节的把握。

<fieldset>
  <legend>收货地址</legend>
  <label>省 <input name="province"></label>
  <label>市 <input name="city"></label>
</fieldset>
#
★★

50. autofocus 属性在 SPA 路由切换时与无障碍焦点管理的冲突如何处理

autofocus 属性在 SPA 路由切换时与无障碍焦点管理有何冲突?如何处理?

  • autofocus 只在初始加载生效
  • 路由切换后的 JS 焦点管理
  • 模态框强制聚焦与页面内容聚焦的区分

autofocus 只在页面初次加载时对元素聚焦一次,SPA 路由切换是 JS 动态渲染新视图,autofocus 不会再次生效,导致模态框或新页面没有焦点;此外自动聚焦可能"抢走"用户正在阅读的位置,对辅助技术用户造成跳转干扰。处理方案:路由切换后由 JS 显式管理焦点——模态框调用 focus()(并配合焦点陷阱),普通页面聚焦到主内容容器(tabindex="-1")或首个交互元素;避免无条件 autofocus,按"用户意图"决定是否聚焦;聚焦时用 preventScroll 或恢复滚动位置;在 React/Vue 中用 ref 加 useEffect 实现声明式聚焦。核心是"导航即焦点迁移"的思维。

考察 autofocus 的一次性语义与 SPA 焦点断层:autofocus 不随路由重触发,需 JS 接管聚焦策略;回答需区分模态框强制聚焦与页面内容聚焦的场景,并考虑滚动位置。

#
★★

51. showPicker() 程序化打开原生日期/颜色/文件选择器的浏览器兼容性与无障碍回退

showPicker() 程序化打开原生日期/颜色/文件选择器有哪些浏览器兼容性与无障碍回退?

  • 用户手势触发的安全约束
  • 跨浏览器支持差异
  • 特性检测与原生控件兜底

showPicker() 可编程打开日期、颜色、文件等原生选择器,但要求由用户手势触发(浏览器安全策略),否则报 AbortError 或 SecurityError;兼容性上 Chrome/Edge 支持较好,Safari 与 Firefox 部分类型长期不支持。无障碍回退:不能假设 showPicker 可用或生效,应先特性检测;调用失败时降级为聚焦输入框并提示用户按 Enter 或点击打开;对自定义"打开按钮"必须用真实 button 元素并保留键盘可达;保持原生控件可见可聚焦作为兜底。核心是"增强而非替代"。

考察 showPicker 的手势约束与兼容性:必须用户手势触发、Safari/Firefox 支持不全;回答需给出特性检测与"保留原生控件可聚焦"的回退策略,并强调自定义按钮的键盘可达性。

#
★★

52. setCustomValidity/reportValidity 与 validity 状态对象(validityState)在自定义校验 UI 的细节集成

setCustomValidity/reportValidity 与 validity 状态对象在自定义校验 UI 中如何细节集成?

  • setCustomValidity 的注入与清除
  • reportValidity 与 checkValidity 的分工
  • 与 aria-invalid、aria-describedby 的联动

setCustomValidity(msg) 设置自定义错误消息,非空时该控件 validity.customError 为 true 且 valid 为 false,传空字符串清除。reportValidity() 在元素或表单上运行约束验证,非法时聚焦第一个错误字段并显示原生错误气泡;checkValidity() 只返回布尔值不提示。细节集成:自定义 UI 监听 input/change,读取 validityState 生成文案并维护错误节点;用 aria-invalid 与 aria-describedby 关联错误;提交时调用 checkValidity() 或 requestSubmit 触发校验,非法则聚焦错误。

考察校验 API 的职责分工:setCustomValidity 注入业务错误、validityState 提供诊断、reportValidity/checkValidity 驱动提示与聚焦;能说明与自定义 UI、aria 状态的集成即体现细节。

form.addEventListener('submit', (e) => {
  e.preventDefault();
  if (!form.checkValidity()) {
    form.querySelector(':invalid').focus();
    return;
  }
  submit();
});
#
★★

53. HTML 表单 :invalid、:valid、:in-range、:out-of-range 伪类在 UX 设计的取舍

HTML 表单的 :invalid、:valid、:in-range、:out-of-range 伪类在 UX 设计中有哪些取舍?

  • :invalid 初始即匹配的问题
  • 范围伪类的适用控件限制
  • 与 aria-invalid、多通道传达的配合

:invalid/:valid 匹配约束验证后的字段状态,:in-range/:out-of-range 匹配数值或日期字段是否在 min/max 范围内。UX 取舍:一是时机问题——:invalid 在页面加载时即匹配空必填字段,直接应用红色样式会让初始表单一片红,应结合 :user-invalid(用户交互后才触发)或 JS 状态延迟展示;二是范围伪类只针对数值/日期类控件,文本字段无 in-range 概念;三是伪类反映"当前值"而非"用户是否看过",配合 aria-invalid 保持语义一致;四是错误展示不只靠颜色,需图标与文本并用。工程上建议默认隐藏错误,交互后或提交时再呈现。

考察校验伪类与 UX 的耦合::invalid 初始即匹配导致"一进来就红"的问题,:user-invalid 是更优选择;范围伪类有适用控件限制;回答体现"状态时机与多通道传达"的设计思维。

#
★★

54.

新版表单元素如 、 在复杂表单编排的取舍

新版表单元素如 、 在复杂表单编排中有哪些取舍?

  • selectlist 与 command 的声明式能力
  • 实验特性的成熟度与降级
  • 可访问性兜底与渐进增强

selectlist(实验)把下拉按钮与 listbox 分离,可自定义样式与选项渲染,目标是替代"自研下拉加 ARIA"的高成本方案;button 的 command 属性可声明式触发 popover 的显示、隐藏与切换,无需 JS。取舍:selectlist 仅 Chromium 部分版本可用,必须特性检测并降级到原生 select;command/toggle-popover 支持较好但仍需验证降级路径;实验特性的 ARIA 映射与键盘行为未完全稳定,高风险场景建议用成熟组件库并补全 aria-expanded、aria-controls;声明式方案减少代码量,但灵活度不如 JS 完全控制,应渐进增强采用。

考察对实验性表单特性的工程判断:selectlist 与 command 提供声明式能力但成熟度不一;回答需体现特性检测、降级到原生控件与可访问性兜底三位一体的取舍框架。

#
★★

55. type="color" 与 type="date" 等新输入类型在桌面与移动端 WebView 的渲染差异与降级

type="color" 与 type="date" 等新输入类型在桌面与移动端 WebView 的渲染差异与降级策略是什么?

  • 桌面/移动/WebView 三档渲染差异
  • 特性检测与自研控件兜底
  • value 格式(YYYY-MM-DD、hex)的双向同步

type=color 在桌面 Chrome/Edge/Firefox 有原生取色器,Safari 桌面为普通文本框加色值校验;type=date 在桌面 Chrome/Edge 有日历控件、Safari 桌面无原生日历,移动端 iOS/Android 分别调用系统日期选择器,而 WebView 可能退化为纯文本框或样式走样。降级策略:先声明正确 type 获得键盘与校验收益;用特性检测判断原生控件是否可用;对必须统一体验的业务自研选择器或引入组件库,但保留原生输入作为无 JS 兜底;注意 date 的 value 格式为 YYYY-MM-DD,自定义 UI 需与原生 value 双向同步;color 同理维护 hex 值。

考察新输入类型跨端渲染差异:桌面、移动、WebView 三档行为不同;降级关键是特性检测加自研控件兜底加 value 格式同步,避免"声明即所得"的错觉,并保留原生输入作为无 JS 回退。

#
★★

56. HTML 表单提交时 submitter 属性在区分多按钮触发源与埋点上报的应用

HTML 表单提交时 submitter 属性在区分多按钮触发源与埋点上报中有哪些应用?

  • SubmitEvent.submitter 的指向
  • 按钮 name/value 与 dataset 的读取
  • submitter 为 null 的兜底

SubmitEvent.submitter 指向实际触发提交的按钮(或图片输入),可读取其 name/value、formAction/formMethod 等覆盖属性与 dataset,用于区分同一表单内不同提交按钮的业务意图。应用场景:多按钮表单在统一提交处理器中按 submitter 分流;埋点上报把 submitter 的标识随事件带上;结合 formaction 判断请求目标;自定义校验可按按钮区分(草稿跳过校验、发布严格校验)。注意 submitter 可能为 null(如 form.submit() 触发时),需兜底;requestSubmit(button) 可显式指定 submitter。

考察 SubmitEvent.submitter 的工程价值:它把"哪个按钮触发"显式暴露给提交处理器,支撑分流与埋点;回答需覆盖 name/value、dataset、覆盖属性读取及 submitter 为 null 的兜底。

form.addEventListener('submit', (e) => {
  e.preventDefault();
  const btn = e.submitter;
  report({ source: btn?.dataset.source || 'unknown' });
  if (btn?.dataset.action === 'draft') saveDraft();
  else publish();
});
#
★★

57. accept 属性在 文件类型限制与 MIME 嗅探攻击的边界

accept 属性在 文件类型限制与 MIME 嗅探攻击的边界是什么?

  • accept 的过滤语义与可绕过性
  • 前端二次校验(file.type/size)
  • 服务端内容检测与响应治理

accept 接受扩展名(.png)、MIME 类型(image/png)或通配(image/*),用于在文件选择器中过滤可选项;但它只是"建议性过滤",不是安全机制:用户可切换到"所有文件",或通过拖拽、JS 赋值等方式绕过,服务端必须重新校验。边界与风险:不同平台对 accept 实现不一致(iOS 支持有限);MIME 嗅探攻击——文件扩展名与实际内容不符时,若服务端按扩展名信任并原样输出,可能被用于 XSS 或任意代码执行;前端应读取 file.type 与 file.size 做二次校验,服务端应基于内容检测(magic bytes)并设置正确的响应头。结论:accept 只提升体验,安全边界在服务端。

考察 accept 的"体验过滤"本质:它不是安全边界,可被绕过;回答需延伸到服务端内容校验、MIME 嗅探与响应头治理,体现安全纵深与"安全边界在服务端"的结论,并说明前端二次校验手段。

#
★★

58. ElementInternals.setValidity 在表单关联自定义元素(form-associated custom elements)中的校验集成

ElementInternals.setValidity 在表单关联自定义元素中如何集成校验?

  • attachInternals 与 ElementInternals
  • setValidity 的 flags/message/anchor 参数
  • 与原生校验链(伪类、报告、提交拦截)的集成

form-associated 自定义元素通过 attachInternals() 得到 ElementInternals,调用 setValidity(flags, message, anchor) 把校验状态注册进原生表单校验体系:flags 描述错误类型,message 为文案,anchor 指定错误锚点。集成效果:错误会参与 form.checkValidity/reportValidity、:invalid 伪类与提交拦截。工程要点:内部状态变化时重新调用 setValidity 保持同步;提供可聚焦的错误锚点;与受控属性配合时在 attributeChangedCallback 中同步校验状态。

考察 ElementInternals.setValidity 的接入点:它让自定义元素错误进入原生校验链(伪类、报告、提交拦截);回答需说明 flags/message/anchor 参数与状态同步时机。

class MyInput extends HTMLElement {
  connectedCallback() {
    this._internals = this.attachInternals();
  }
  set value(v) {
    this._internals.setFormValue(v);
    const ok = /^[a-z]+$/.test(v);
    this._internals.setValidity(
      ok ? {} : { patternMismatch: true },
      ok ? '' : '仅支持小写字母',
      this
    );
  }
}
#
★★

59. 自定义事件(CustomEvent)的创建与冒泡控制

自定义事件(CustomEvent)如何创建?冒泡与穿透如何控制?

  • CustomEvent 的 detail/bubbles/composed/cancelable
  • 事件委托与 Shadow DOM 穿透
  • 命名规范与清理

CustomEvent 通过 new CustomEvent(type, { detail, bubbles, cancelable, composed }) 创建,detail 携带任意数据。bubbles: true 允许事件向上冒泡,配合事件委托在祖先统一处理;composed: true 且 bubbles: true 时事件可穿透 Shadow DOM 冒泡到外部文档,适合自定义元素向宿主通知内部交互;仅 composed 而 bubbles=false 时外部仍可在捕获阶段感知;cancelable 决定 preventDefault 是否有效。实践要点:命名避免与原生事件冲突、detail 保持可序列化、监听后及时移除。

考察 CustomEvent 的构造选项与传播语义:bubbles 管常规冒泡、composed 管 Shadow DOM 穿透、cancelable 管可取消性;能结合自定义元素通信场景说明即体现理解。

el.dispatchEvent(new CustomEvent('app:change', {
  detail: { id: 1 },
  bubbles: true,
  composed: true,
  cancelable: false
}));
#
★★

60. Selection 与 Range API 在富文本编辑器中的选区操作

Selection 与 Range API 在富文本编辑器中如何操作选区?

  • Selection 与 Range 的职责分工
  • 选区的保存、恢复、包裹与替换
  • 富文本模型中的 DOM 层定位

Selection 表示文档中当前选中的区域(通常一个 Range),通过 getSelection() 获取;Range 表示连续区域(startContainer/startOffset/endContainer/endOffset)。富文本编辑器应用:保存与恢复选区(失焦、插入图片前后记录 range,操作后 restore);用 surroundContents 包裹选中文本加 strong/em;用 toString 读取选中文本同步工具栏。现代编辑器常用 contenteditable 加自定义数据模型(Lexical、ProseMirror),Range 作为 DOM 层桥梁。

考察 Range/Selection 的职责分工:Selection 是用户选区集合,Range 是精确的容器偏移描述;回答需覆盖保存恢复、包裹、替换三大操作及其在富文本模型中的位置。

#
★★

61. Event 的 composed 属性与跨 Shadow DOM 边界的可冒泡性

Event 的 composed 属性与跨 Shadow DOM 边界的可冒泡性如何理解?

  • composed 与 bubbles 的独立维度
  • 事件穿透 shadow root 的条件
  • composedPath 与事件溯源

composed 决定事件能否从 Shadow DOM 内部穿透到宿主文档:composed: true 时事件可跨越 shadow root 边界继续传播(配合 bubbles 才能冒泡到外部祖先;仅 composed 而 bubbles=false 时外部只能在捕获阶段感知);composed: false(默认)时事件被限制在 shadow 树内。典型场景:自定义元素内部按钮的 click 事件默认 composed=true,宿主可监听;自定义事件需显式设置。工程价值:composedPath() 可查看事件完整传播路径(含 shadow root 与 slot 边界),用于事件溯源与委托;用 composed 控制内外可见性的平衡。

考察 composed 与 bubbles 的独立维度:composed 管 Shadow DOM 穿透、bubbles 管常规冒泡,两者配合决定外部可见性;能结合自定义元素通信与 composedPath 说明即体现深度。

#
★★

62. adoptedStyleSheets 在多组件共享样式表时的性能与缓存

adoptedStyleSheets 在多组件共享样式表时如何带来性能与缓存收益?

  • CSSStyleSheet 对象级共享
  • 构造表与 replaceSync 的运行时更新
  • 与 Shadow DOM 隔离的组合及兼容回退

adoptedStyleSheets 允许把 CSSStyleSheet 对象(构造表或 link/style 的 sheet)adopt 到 Document 或 ShadowRoot,同一样式表可被多个根共享。收益:解析一次、多树复用——样式表内部只解析一次,多组件共享避免重复解析与内存占用;构造表可用 replaceSync 同步更新,修改一处所有采用者即时生效,便于设计令牌与主题切换;与 Shadow DOM 组合时样式天然隔离且无需复制文本;配合统一管理可实现运行时主题热更新。注意兼容性(旧 Safari 需要 polyfill 或回退到 style),且构造表不参与 document.styleSheets 列表。

考察 adoptedStyleSheets 的共享机制:样式表对象级复用实现"解析一次、多处生效",配合构造表支持运行时更新;回答需点明与内联 style 的差异及兼容回退。

#
★★

63. AbortController/AbortSignal 在事件监听与 fetch 链路的统一取消协议

AbortController/AbortSignal 如何在事件监听与 fetch 链路实现统一取消协议?

  • signal 选项驱动事件监听移除
  • fetch 与流、定时器的统一取消
  • AbortError 区分与超时组合

AbortController 提供 signal 与 abort(),AbortSignal 作为"取消令牌"被 fetch、事件监听(addEventListener 的 signal 选项)、流等 API 统一消费,实现"一次取消、全链路停止"。事件监听用法:addEventListener(type, fn, { signal }),abort() 后监听器自动移除,利于组件卸载清理。fetch 链路:把同一 signal 传给请求,abort() 会中断请求(AbortError),可配合 AbortSignal.timeout 与并发竞态控制。注意被取消的 fetch 需捕获 AbortError 区分于业务错误。

考察 AbortSignal 作为统一取消协议的核心:同一信号可同时驱动 fetch 与事件监听,实现组件卸载时一站式清理;回答需覆盖 signal 选项、AbortError 处理与超时组合。

const ac = new AbortController();
window.addEventListener('resize', onResize, { signal: ac.signal });
fetch('/api', { signal: ac.signal });
ac.abort();
#
★★

64. Element.animate 与 Animation.commitStyles 在过渡与动画衔接的工程价值

Element.animate 与 Animation.commitStyles 在过渡与动画衔接中有何工程价值?

  • 无 fill 动画结束回跳问题
  • commitStyles 固化终态
  • 与 CSS 过渡接管的编排及内联样式代价

Element.animate() 创建的动画结束时若无 fill 模式会回到原样式,可能产生"动画后回跳";commitStyles() 把动画当前的计算样式写入元素内联样式,作为动画与后续状态的衔接快照。工程价值:在 finish 回调中调用 commitStyles() 再 cancel(),样式平滑落到终值;用于"从动画态过渡到常态"的编排——先 WAAPI 播放,合适时机 commitStyles 后改用 CSS transition 接管;配合 getAnimations() 做状态持久化。注意 commitStyles 会膨胀 style 属性,更适合终态属性少的场景。

考察 WAAPI 动画的终态衔接问题:无 fill 动画结束回跳,commitStyles 固化终态并让 CSS 过渡接管;回答需点明内联样式膨胀的代价与"终态属性少"的适用边界。

#
★★

65. Element.checkVisibility() 与可见性判断的场景

Element.checkVisibility() 与可见性判断的适用场景是什么?

  • 渲染可见性的判断维度
  • options 参数(opacity、content-visibility)
  • 与 IntersectionObserver 的分工

checkVisibility(options) 返回元素是否"可见":默认要求元素有布局盒、非 display:none、非 visibility:hidden、非 content-visibility:hidden,options 可追加条件(opacityProperty 检查 opacity:0 等)。适用场景:判断组件是否真正展示(埋点、懒渲染前检查)、确定元素是否被 content-visibility 跳过、避免用 getComputedStyle 组合判断。边界:它检查"渲染可见性"而非"视口内可见",屏幕内判断仍需 IntersectionObserver;旧浏览器需 polyfill 或回退。

考察 checkVisibility 的语义边界:它判断渲染可见性(display、visibility、content-visibility),不含视口内判断;能说明与 IntersectionObserver 的分工及 options 参数即体现理解。

#
★★

66. Pointer Events 与 Mouse Events 的统一与差异

Pointer Events 与 Mouse Events 的统一与差异是什么?工程上如何选择?

  • 指针事件对鼠标/触摸/触控笔的统一
  • pointerType、touch-action 的作用
  • hover 语义与旧浏览器回退

Pointer Events 统一鼠标、触摸、触控笔为同一事件体系,事件对象携带 pointerType(mouse/touch/pen)、压力、倾斜角等;Mouse Events 只针对鼠标。差异:触摸设备不产生真正的 mousemove/mousedown(兼容性 mouse 事件由浏览器模拟派发);pointer 事件可区分 pointerType 与 pointerId,支持多指与笔压;需显式设置 touch-action 以禁用默认滚动与缩放。工程选择:新交互优先用 Pointer Events 加 touch-action;兼容老浏览器时回退到 Mouse/Touch 事件;桌面悬停语义仍常用 CSS。

考察输入事件体系的演进:Pointer Events 统一三类输入并携带 pointerType,Mouse Events 仅鼠标;回答需覆盖 touch-action、hover 语义与旧浏览器回退,体现选择依据。

#
★★

67. scrollend 事件替代 scroll 防抖的精度提升

scrollend 事件如何替代 scroll 防抖提升精度?

  • scrollend 的原生触发时机
  • 与防抖方案的对比
  • Safari 兼容回退

scroll 事件在滚动过程中高频触发,传统做法是手动防抖或节流判断"滚动停止";scrollend 由浏览器在滚动真正结束时一次性派发(含惯性滚动、滚动捕捉、缩放后的滚动),无需 JS 猜测时机,精度更高且代码更简洁。工程价值:滚动结束后的回调(吸顶状态计算、懒加载触发、位置埋点)可直接监听 scrollend,避免防抖窗口与真实停止时刻的偏差;程序化滚动(scrollTo、scrollIntoView)同样触发 scrollend。注意兼容性:Safari 曾长期缺失,需特性检测并回退到 scroll 加防抖;scrollend 只表示滚动结束,不代表布局稳定。

考察 scrollend 的语义价值:浏览器原生判定滚动结束,替代手写防抖并消除时机偏差;回答需点明触发时机(惯性、捕捉)、Safari 兼容回退与"结束后布局未必稳定"的边界。

#
★★

68. Document Picture-in-Picture API 在浏览器内画中画窗口的 DOM 树创建

Document Picture-in-Picture API 如何在浏览器内创建画中画窗口的 DOM 树?

  • requestWindow 创建独立窗口
  • 向独立 document 注入 DOM 与样式
  • 与旧视频 PiP 的差异及关闭同步

Document Picture-in-Picture API 允许把任意 DOM 内容放入独立的画中画窗口:调用 documentPictureInPicture.requestWindow() 返回新 Window,可向该窗口的 document 注入样式与节点,形成与主页面隔离的渲染树;画中画窗口始终置顶,主页面失焦仍可见。使用要点:requestWindow 需用户手势;可传 width/height 与 aspectRatio 控制窗口大小;注入内容应自包含(内联样式或 adoptedStyleSheets),因为独立窗口不共享主文档 CSS;通过 pagehide 监听其关闭并同步状态。

考察 Document PiP 的核心能力:requestWindow 创建独立窗口并注入 DOM,样式需自包含;回答需对比旧视频 PiP、说明手势要求与关闭同步,体现对新 API 的掌握。

const pipWin = await documentPictureInPicture.requestWindow({ width: 400, height: 300 });
pipWin.document.body.append(pipWin.document.adoptNode(playerEl));
#
★★

69. Document.pictureInPictureElement 与窗口模式控制的前端取舍

Document.pictureInPictureElement 与窗口模式控制在前端有哪些取舍?

  • 当前 PiP 元素的状态查询
  • enter/leave 事件的状态同步
  • 原生窗口与自定义窗口的取舍

document.pictureInPictureElement 返回当前处于画中画模式的元素(无则 null),是判断"是否在 PiP"的主要途径;配套 exitPictureInPicture() 退出。前端取舍:能力检测——判断 documentPictureInPicture 与 requestPictureInPicture 是否存在;状态同步——进入/退出 PiP 触发 enter/leavepictureinpicture 事件,页面需同步播放状态与 UI;窗口控制——Document PiP 可设置尺寸与比例,视频 PiP 由浏览器接管窗口;权衡——PiP 增加实现复杂度,非核心场景可降级为普通浮动组件。

考察 PiP 状态模型与工程取舍:pictureInPictureElement 提供状态查询,事件驱动同步;回答需覆盖能力检测、状态同步与自定义窗口 vs 原生窗口的选择。

#
★★

70. input 事件的 InputEvent.getTargetRanges 在富文本撤销栈的工程价值

input 事件的 InputEvent.getTargetRanges 在富文本撤销栈中有何工程价值?

  • inputType 与 targetRanges 的组合
  • 细粒度撤销栈与协作同步
  • IME 组合与兼容回退

InputEvent.getTargetRanges() 返回 input 事件影响的 Range 列表,配合 inputType(insertText、deleteContentBackward、insertFromPaste 等)可还原"用户做了什么"。工程价值:构建撤销/重做栈——记录 inputType、targetRanges 与前后快照,回退时精确恢复受影响区间,而非整段 DOM 快照;实现协作编辑的变更同步(OT/CRDT 需要细粒度操作);按输入类型分流(粘贴需清理格式、IME 组合需合并)。注意兼容性:部分浏览器返回空数组,需回退到选区快照;组合输入期间需与 compositionend 协同。

考察 InputEvent 的细粒度输入描述:inputType 加 targetRanges 构成"可回放的操作记录",是高质量撤销栈与协同编辑的基础;回答需点明兼容回退与 IME 合并边界。

#
★★

71. Shadow Root composedPath() 在团队规范与代码组织

Shadow Root composedPath() 在团队规范与代码组织中有何应用?

  • 完整传播路径的构成
  • 事件溯源与委托边界
  • 组件事件命名与测试契约

composedPath() 返回事件从触发点到 window 的完整传播路径,包含 shadow root、slot 与宿主元素等边界节点,可回答"这个事件到底来自组件内部哪个节点"。团队规范应用:一是事件溯源与调试——在公共事件总线或埋点中记录 composedPath,快速定位深层自定义元素内部的事件来源;二是统一的事件委托规范——在组件库入口用 composedPath 判断事件是否穿越组件边界,决定对外派发还是内部消化;三是命名与契约设计——要求自定义元素内部事件统一命名空间,并规范 composed 的显式设置。它让"事件从哪来"成为可测试的契约。

考察 composedPath 在工程治理中的价值:它提供事件完整路径,支撑事件溯源、委托边界与组件契约;回答需结合事件命名规范与测试断言,体现对组件边界治理的理解。

document.addEventListener('click', (e) => {
  const path = e.composedPath();
  const widget = path.find((n) => n && n.dataset && n.dataset.widget);
  if (widget) handleWidgetClick(widget, e);
});
#

72. min/max/step 属性在数字与日期输入控件的边界精度与跨时区策略

min/max/step 属性在数字与日期输入控件的边界精度与跨时区策略如何理解?

  • 数值与日期控件的范围语义
  • 浮点 step 判定的精度问题
  • 时区存储与展示分离

min/max/step 作用于 number、range、date、time、month 等控件:数值控件按数字比较,日期控件按"日历日/时刻"比较;step 定义合法值步长(number 为数值增量,date 为天数),值为 min 加 step 的整数倍才合法,否则触发 stepMismatch。边界精度:浮点数值(0.1 步长)存在二进制精度问题,步长判定可能产生意外 mismatch,应选用合适精度或容忍误差;日期 value 是字符串(YYYY-MM-DD),比较按日历日语义,展示受本地时区影响——跨时区场景应存 UTC 时间戳,仅展示层转换。工程要点:用 validity 的相关状态反馈,并配合服务端二次校验。

考察约束属性的精度与时区陷阱:浮点 step 判定与日期字符串比较、时区展示与存储分离;回答需给出"存储 UTC、展示本地"与误差处理的工程策略,体现对边界情况的认知。

#

73. Web 组件与 HTML 表单元素(如 ElementInternals)

Web 组件如何与 HTML 表单元素集成(如 ElementInternals)?

  • attachInternals 与表单关联自定义元素
  • setFormValue/setValidity 与生命周期回调
  • 兼容降级

Web 组件默认不参与表单;通过 attachInternals() 获得 ElementInternals 后,自定义元素可成为"表单关联自定义元素":setFormValue() 设置提交值(可含文件),setValidity() 注册校验状态,form 属性获得表单所有者,配合四个生命周期回调(关联、重置、禁用、状态恢复)处理表单集成。工程价值:自研控件可被 form 收集、参与 checkValidity 与提交,享受原生表单与无障碍基础设施;注意 ElementInternals 需现代浏览器,要有降级方案。

考察表单关联自定义元素的集成面:ElementInternals 打通值、校验、生命周期四回调;回答需覆盖 setFormValue/setValidity 与各回调时机,并点明兼容降级。

#

74. 表单跨域提交时 formaction 与 CORS 策略对凭证 Cookie 与 token 传递的影响

表单跨域提交时 formaction 与 CORS 策略对凭证 Cookie 与 token 传递有何影响?

  • 原生导航提交与 CORS 的关系
  • fetch 跨域的凭证配置
  • SameSite 与 CSRF token 的可用性

表单原生提交是"导航式"请求,不受 CORS 同源限制,但响应会整页导航、无法读取,且第三方 Cookie 是否携带取决于 SameSite 策略(跨站提交默认不带 SameSite=Lax/Strict 的 Cookie);若用 fetch 跨域提交则受 CORS 约束,需服务端返回 Access-Control-Allow-Origin 与 allow-credentials,且 fetch 需 credentials:'include' 才携带凭证。formaction 只是把提交目标指向跨域地址,不影响 CORS 判定,但影响凭证与 token 可用性:CSRF token 跨域时可能不带,需改用显式 token 头或双提交策略。

考察表单跨域与 CORS 的本质区别:原生提交导航式、不受 CORS 但无法读响应,fetch 受 CORS 且凭证需显式配置;回答需延伸到 SameSite 与 CSRF token 的可用性。

#

75. type="search" 输入控件在 Safari 与 Chrome 中取消按钮与样式覆盖的边界

type="search" 输入控件在 Safari 与 Chrome 中取消按钮与样式覆盖的边界是什么?

  • 原生取消按钮的跨内核差异
  • 伪元素定制的边界
  • 自建按钮的无障碍与 search 事件

type=search 语义上表示搜索框,浏览器会附加"清除"按钮:Chrome 在输入非空时显示 ✕(点击清空并聚焦),Safari 显示圆叉且常伴随圆角样式与内边距差异;这些 UI 由浏览器内部实现,不同内核样式覆盖能力不同。边界:Chrome 可用 ::-webkit-search-cancel-button 伪元素定制或隐藏;Safari 的取消按钮也支持部分定制,但版本间行为不一致。工程实践:需要统一视觉时,可隐藏原生取消按钮并自建清除按钮,注意保留键盘可达与无障碍标签;search 输入回车触发 search 事件,配合 input 事件区分;保留 type=search 的移动端"搜索"键语义。

考察搜索控件样式的跨内核差异:取消按钮由浏览器内部实现、伪元素定制能力不一;回答需给出"隐藏原生取消按钮并自建清除按钮、保留键盘可达与无障碍标签"的实践,并说明 search 事件与 input 事件的配合时机与移动端搜索键语义。

#

76. HTML5 校验伪类 :user-invalid 与 :user-valid 在用户已交互后才触发校验的设计意图

HTML5 校验伪类 :user-invalid 与 :user-valid 在用户已交互后才触发校验的设计意图是什么?

  • 与 :invalid/:valid 的触发差异
  • 避免初始红屏的 UX 设计
  • 兼容兜底与展示层定位

:user-invalid 与 :user-valid 只在"用户已与该字段交互"后匹配:用户修改过值并离开(或尝试提交)后,字段的非法/合法状态才反映在伪类上;而 :invalid/:valid 在页面加载时即按当前值匹配。设计意图:避免"表单一打开就满屏红"的挫败体验——用户还没输入就被惩罚;校验反馈应发生在"用户有机会修正之后",:user-invalid 让错误提示只在用户真正犯错时出现。工程价值:用它替代"JS 记录 touched 状态"的样板代码,配合 CSS 控制错误样式时机;注意浏览器支持差异,仍需以 JS 的 touched 逻辑兜底;它不改变 validityState,只是展示层的时机选择器。

考察 :user-* 伪类的交互时机设计:把"校验状态展示"从"值是否非法"解耦为"用户是否已交互",避免初始红屏;回答需说明与 :invalid 的差异及 JS touched 兜底。

#

77. 使用 pattern="[0-9]" 验证数字时如何考虑 Unicode 数字字符与本地化写法

使用 pattern="[0-9]" 验证数字时如何考虑 Unicode 数字字符与本地化写法?

  • ASCII 与 Unicode 数字字符的差异
  • 全角数字与本地化格式
  • NFKC 归一化与错误提示

[0-9] 只匹配 ASCII 数字,而 Unicode 包含大量数字字符:全角数字、阿拉伯-印度数字、上标/下标数字、罗马数字、带圈数字等,不同语言的用户可能输入这些字符;本地化写法还包括千分位逗号、小数点(逗号或点)、货币符号等。若业务只接受 ASCII 数字,pattern="[0-9]*" 配合 type=number 即可,但全角数字会被判非法,应提供清晰错误文案;若需宽容处理,可在 JS 中用 Unicode 属性转义(\p{N},需 u/v 标志)匹配任意数字,或先把全角与本地化数字归一化(NFKC 折叠全角)再校验。工程建议:明确输入域的语言边界,pattern 做精确约束,JS 做归一化与提示。

考察 pattern 与国际化输入的冲突:ASCII 字符类不覆盖全角与非拉丁数字,本地化写法(千分位、小数点)需归一化;回答体现"明确边界加 NFKC 归一化"的策略。

#

78. autocomplete="one-time-code" 在短信验证码场景的安全考量与浏览器实现差异

autocomplete="one-time-code" 在短信验证码场景有哪些安全考量与浏览器实现差异?

  • iOS 短信提取与 Android WebOTP
  • 验证码的会话绑定与防泄漏
  • 特性检测与手动输入兜底

autocomplete="one-time-code" 声明字段为一次性验证码,iOS/iPadOS 会从短信自动提取验证码并提示填入,Android 上常配合 SMS Retriever 或 WebOTP API 实现自动填。安全考量:验证码是敏感凭证,自动填充只应发生在用户主动触发短信验证的会话中;短信内容应包含域名或品牌标识,且字段应结合一次性使用、短时效与服务端绑定(会话、手机号);不要在前端日志、URL 或埋点中记录验证码。实现差异:iOS 对 one-time-code 支持好但要求短信发送方符合 Apple 特定格式;Chrome Android 依赖 WebOTP 或自动填充服务;需做特性检测并保留手动输入兜底。

考察验证码自动填充的安全与兼容两面:one-time-code 触发 iOS 短信提取,Android 需 WebOTP;回答需强调会话绑定、防泄漏与特性检测兜底的安全工程。

#

79. tabindex 属性在表单元素焦点顺序与无障碍键盘导航的工程取舍

tabindex 属性在表单元素焦点顺序与无障碍键盘导航中有哪些工程取舍?

  • tabindex 三种取值的语义
  • 焦点顺序与文档顺序一致原则
  • 自定义控件的键盘契约与 SPA 焦点管理

tabindex 决定元素是否可聚焦及 Tab 顺序:默认表单控件与链接可聚焦;tabindex="0" 使元素按文档顺序可聚焦(适合自定义交互元素,需同时加 role 与键盘事件);tabindex="-1" 使元素可编程聚焦但不进 Tab 顺序(适合路由切换时内容容器聚焦、焦点恢复);正整数值会打乱文档顺序,WCAG 建议避免。工程取舍:焦点顺序应遵循"视觉与文档顺序一致";自定义控件必须补 role、键盘事件与可见焦点样式,否则只是"伪可聚焦";SPA 焦点管理常用 tabindex="-1" 目标容器配合 JS 聚焦;模态框内用焦点循环实现键盘导航。

考察 tabindex 的三个取值语义:0 进入 Tab 顺序、-1 仅可编程聚焦、正整数打乱文档顺序应避免;回答需覆盖自定义控件需补齐 role 与键盘事件的契约,以及 SPA 路由切换焦点管理的取舍,体现无障碍的工程判断。

#

80. input 事件与 change 事件在实时表单校验场景的触发时机与性能取舍

input 事件与 change 事件在实时表单校验场景的触发时机与性能取舍如何?

  • input 高频触发与 change 提交时触发
  • 防抖、节流与远程校验取消
  • IME 组合输入的处理

input 事件在值每次变化时触发(键入、粘贴、拖拽、IME 确认后),适合实时校验、字数统计;change 事件在"值已提交"时触发:文本类控件在失焦时(若值有变化)、select/radio/checkbox 在选择改变后立即触发。取舍:input 高频触发,校验逻辑重时需防抖或节流;change 低频但滞后,适合"离开字段再校验"的场景。工程实践:轻量校验用 input 加防抖,远程校验用 input 防抖加 AbortController 取消旧请求;IME 组合输入时需结合 composition 事件。

考察两个事件的时机差异:input 随每次变化触发适合实时但需防抖,change 在提交/失焦触发适合事后校验;回答需覆盖 IME 组合态与远程校验取消,体现性能取舍。

#

81. 通过 传递 CSRF token 在 SSR 与客户端表单的工程实现边界

通过 传递 CSRF token 在 SSR 与客户端表单的工程实现边界是什么?

  • 同步令牌模式与 SSR 预填
  • CSR/fetch 场景的请求头方案
  • XSS 读取风险与双提交

隐藏字段传 CSRF token 是同步令牌模式:SSR 时把会话绑定的 token 输出到隐藏 input,提交时随表单发送,服务端比对会话中的值。边界与问题:CSR 表单无法服务端预填,需异步获取后写入,存在时序与缓存问题;SPA 用 fetch 提交时 token 更适合放请求头(X-CSRF-Token),并配合 SameSite Cookie 双提交;隐藏字段会出现在 DOM 中,存在 XSS 注入时攻击者可读取,必须与 Cookie 双因子或会话绑定共同使用;SSR 下要防止 token 被 CDN 缓存共享;GET 请求不应携带敏感 token。核心边界:隐藏字段适合同步导航提交,异步场景用请求头加双提交。

考察 CSRF 防护的表单实现边界:SSR 可预填隐藏字段,CSR 与 fetch 场景更适合请求头 token;回答需点明隐藏字段在 DOM 中可被 XSS 读取的风险、Double Submit 双提交与 CDN 缓存问题,体现安全工程的完整思维。