AI 在 Web 开发中容易出错的 10 大问题

发布时间:2026 年 11 月 11 日

本周,我们发布了 Modern Web Guidance 1.0 版,这是一套技能,可将 Web 平台专业知识、最佳实践和浏览器兼容性数据直接嵌入到您的编码智能体中。我们推出 Modern Web Guidance 的目标是帮助使用 AI 编码智能体的开发者充分利用现代 Web 平台的强大功能,最终提升用户的 Web 体验。

自我们于 5 月首次推出早期预览版 Modern Web Guidance 以来,编码智能体变得越来越强大,许多令人惊叹的新前沿模型也相继发布。我们最常听到的一个问题是:这些新的前沿模型不就已经遵循 Web 开发最佳实践了吗?

遗憾的是,答案是“不会”,我们之所以知道答案是“不会”,是因为我们对此进行了测试。

Modern Web Guidance 中的每个指南都定义了一组预期,如果指南中的最佳实践得到了正确遵循,这些预期就必须实现。然后,我们的评估套件会测试这些指南,方法是向安装了 Modern Web Guidance 的智能体(引导式智能体)和未安装 Modern Web Guidance 的智能体(非引导式智能体)提供相同的提示。系统会根据指南中定义的预期结果检查这两次运行的输出。

对比引导式和非引导式通过率,您会发现 AI 模型(即使是最新的前沿模型)也无法自行可靠地遵循现代 Web 开发最佳实践。

平均而言,无引导的编码智能体只能通过我们评估套件中大约 50% 的检查,而使用 Modern Web Guidance 时,通过率约为 90%。

水平条形图,比较了前沿编码智能体的平均评估检查通过率(截至 2026 年 11 月 9 日):不使用 Modern Web Guidance 时为 52%,使用 Modern Web Guidance 时为 91%。

您可以查看我们的评估信息中心,了解我们针对每个指南运行的具体检查的完整列表,以及每个模型在这些检查中的得分。

不过,为了让大家有一个宏观的认识,本文将介绍 AI 模型经常出错的 10 个最棘手领域,涵盖 Web 开发者在日常工作中极有可能遇到的关键学科,例如无障碍、用户体验、性能和安全性。

1. 无障碍功能:键盘焦点和 inert 管理

对于使用键盘或屏幕阅读器进行导航的用户,可预测的焦点顺序是互动式界面可用的关键。如果没有它,焦点可能会游移到隐藏的背景内容中,或者卡在数十个额外的 Tab 键停靠位中。

焦点和inert管理是我们评估中最大的无障碍差距之一,也是 Modern Web Guidance 改进最显著的领域之一。最常见的错误包括:

  • 未能将焦点移至新打开的视图,并且在返回时忘记将焦点恢复到触发元素。
  • 在自定义模态窗口中依赖手动 JavaScript 标签页陷阱和 aria-modal="true",而不是使用模态 <dialog> 或标记背景内容 inert。
  • 将工具栏或方向网格中的每个项公开为单独的 Tab 键停靠位,而不是使用具有漫游 tabindex 的单个 Tab 键停靠位。
  • 创建与相邻背景的对比度低于 3:1 的自定义 :focus-visible 轮廓。

2. 无障碍:减少动画效果支持

意外的页面移动和大规模动画不仅会分散注意力,对于患有前庭障碍或对运动敏感的用户,还可能引发头晕、恶心或头痛。

在添加标准 CSS 过渡或关键帧动画时,AI 模型通常会记得检查 prefers-reduced-motion。不过,在使用流畅滚动、视图过渡或滚动驱动动画等较新功能时,他们往往会忘记减少动画,或者在实现时出错:

  • 在根元素上全局且无条件地设置 scroll-behavior:smooth。
  • 使用滚动驱动的 CSS 动画,不进行减少动画检查。
  • 移除了轮播项上的 transition 时长,以便在滚动期间减少动画效果,但忘记了同时移除转换属性,导致轮播项在滚动时大小发生跳变。
  • 在启用“减少动画”时,对 *、*::before 和 *::after 应用一刀切的 0.01ms 持续时间重置,这也会清除所有必要的非动画过渡(这些过渡是传达界面状态变化所必需的)。
  • 无条件启用跨文档视图过渡,并在启用“减少动画”时替换 ::view-transition-* 动画,而不仅仅是在“减少动画”检查后限制 @view-transition 规则。

3. 无障碍功能:表单验证、格式提示和自动填充状态

表单是大多数关键用户历程的基石。结账表单中的一个小问题可能会对商家的利润产生重大影响。

在构建表单时,AI 模型可以正确处理许多基本问题。不过,它们往往会在一些微小但关键的细节上出错,例如验证错误、占位符和格式提示的位置不当,以及未能正确集成密码管理工具和自动填充功能:

  • 使用自定义 JavaScript blur 验证重新实现 CSS :user-invalid,这通常会在用户通过 Tab 键跳过未触及的 required 字段时立即将其标记。
  • 让 aria-invalid 与可见错误不同步,要么在 blur 上过早设置 aria-invalid="true",要么在 CSS 中设置 :user-invalid 样式,而不在 JavaScript 中同步 aria-invalid。
  • 依赖于消失的 placeholder 文本来显示所需格式(例如卡片到期日输入框中的 MM/YY),而不是呈现与 aria-describedby 关联的永久性提示。
  • 将格式提示和密码规则放在 <input> 下方(而不是上方),导致用户需要阅读这些内容时,它们可能会被移动键盘和自动填充弹出式窗口遮挡。
  • 仅通过更改边框颜色来突出显示 :autofill 输入,而不是将颜色与不会改变布局的非颜色提示(例如嵌入式 box-shadow)搭配使用。

4. 用户体验:滑动和轻触手势

智能体擅长使用命令式 JavaScript 实现轻触手势,并编写自己的自定义物理逻辑。这些实现方式虽然可行,但由 JavaScript 驱动的轻触互动很少能像用户期望的原生应用那样流畅。

其中许多互动都可以通过 CSS 和原生滚动 API 实现,从而让浏览器在主线程之外运行手势物理效果。但在我们的评估中,AI 模型往往会忽略这些特征:

  • 使用 pointermove 或 touchmove 监听器实现滑动关闭或滑动显示手势,而不是使用 CSS 滚动贴靠。
  • 在标签页滑动界面上省略 overscroll-behavior-x:none,这可能会在过度滑动时意外触发浏览器后退或前进导航。
  • 在 JavaScript 回调中驱动主线程上的滑动进度效果,而不是使用滚动驱动的动画。
  • 无法在基于滚动的滑动操作面板上正确支持键盘焦点。

5. 用户体验:对话框、弹出式窗口和顶层过渡

在我们的评估中,模型在为模态对话框和弹出式窗口添加动画效果、关闭或包含滚动效果时,通常会回退到命令式 JavaScript 解决方法。

代理通常不会依赖专为顶层叠加层构建的现代 HTML 和 CSS 功能,而是会手动编写进入和退出状态机、历史记录钩子和正文滚动锁定,这些功能更难维护,并且容易出现细微的界面 bug。

如果这些互动处理得当,就能将原本感觉脆弱的体验转变为用户信任的精致体验。以下是我们发现的最常见错误:

  • 构建自定义 position:fixed 叠加层,并使用手动点击外部处理程序进行轻度关闭,而不是仅使用 popover。
  • 通过切换 CSS 过渡类并与 requestAnimationFrame() 和 transitionend 监听器(具有 setTimeout() 回退)协调来创建进入和退出动画,而不是使用 @starting-style 和 transition-behavior 在纯 CSS 中执行此操作。
  • 通过在 <html> 上设置 overflow:hidden,而不是使用 <dialog> 元素来包含滚动回弹,从而在打开的模态窗口后锁定页面滚动。
  • 添加 popstate 监听器以检测 Android 返回手势并关闭打开的模态窗口,而不是使用模态 <dialog> 元素的原生返回按钮关闭功能。

6. 用户体验:深色模式和自适应主题控件

用户启用深色模式是为了减轻眼部疲劳和眩光,因此,如果网页加载时出现明亮的白色闪烁、表单控件未应用主题,或切换开关与操作系统偏好设置不同步,都会立即破坏用户体验。

深色模式切换开关看似简单,但在我们的评估中,未经引导的模型总是会遗漏一些关键的平台细节,而这些细节对于正确实现主题切换和原生表单控件至关重要:

  • <head> 中缺少 <meta name="color-scheme" content="light dark">,导致深色模式用户在加载外部样式表时会看到白色画布闪烁。
  • 使用自定义颜色设置深色主题或深色表面组件的样式,而不设置 color-scheme,导致原生滚动条和表单控件停留在浅色模式。
  • 在定义自动遵循活跃 color-scheme 的主题自适应颜色令牌时,忽略了 CSS light-dark() 函数。
  • 仅提供一个二元浅色或深色切换开关,用于在 localStorage 中设置明确的替换值,而没有返回到操作系统默认设置的选项。
  • 忘记添加 storage 事件监听器,导致用户更改主题时其他打开的标签页无法同步。

7. 性能:运行时响应能力和流畅度

网页加载完成后,用户会在网页上停留大部分时间,因此,互动迟缓和过渡不顺畅对用户体验造成的损害不亚于初始加载缓慢。

在我们的评估中,模型通常会遵循 Lighthouse 等工具多年来推广的经典加载时最佳实践,并且通常知道将明显繁重的循环分流到 Web Worker。它们始终难以解决的问题是主线程响应能力,这对于优化 INP 至关重要:隔离布局工作、按优先级安排任务,以及利用在主线程之外执行渲染工作的新 HTML 和 CSS 功能。

例如,我们经常看到代理:

  • 为后台或低优先级工作滚动自定义 setTimeout() 队列,而不是使用 scheduler.postTask() 优先处理用户可见的任务,或在浏览器支持时利用 scheduler.yield() 进行任务延续。
  • 在不应用 content-visibility:auto 和 contain-intrinsic-size 的情况下构建复杂布局(例如密集数据网格),这意味着用户互动后的更新会触发全页重排。
  • 使用 display:none 隐藏非活跃 SPA 视图(或将其销毁),而不是使用 content-visibility:hidden(与 inert 配对)。前者会销毁缓存的渲染状态,因此切换回来会触发完整布局和绘制。
  • 使用 Intersection Observer 回调暂停屏幕外 <canvas> 动画和后台循环,而不是将 content-visibility:auto 与 contentvisibilityautostatechange 事件配对(如果可用),从而错过了元素滚动到视图中之前浏览器的预渲染边距。
  • 使用 scroll 事件监听器构建滚动提示界面提示,这会强制进行持续的布局计算,而不是在可用时使用 CSS 滚动状态查询(使用 Intersection Observer 回退)。

8. 性能:布局偏移和视觉闪烁

意外的布局偏移会分散读者的注意力,并可能导致用户点击意外的按钮,有时会造成不可逆转的后果!

模型确实能够可靠地向标准 <img> 元素添加 width 和 height 属性,以防范布局偏移,但它们总是会忽略其他常见的布局偏移和预绘制闪烁来源,例如 <video> 元素、网页字体切换、移动浏览器工具栏和客户端实验,而这些都会影响 CLS。

  • 省略 <video> 元素上的显式 width 和 height 属性(这样,未加载的播放器会默认采用 300×150,并在元数据加载后发生布局偏移),或者为媒体封装容器元素设置样式,而不是直接在媒体元素上设置 aspect-ratio 和 object-fit。
  • 将网页字体与系统后备字体配对时未使用 font-size-adjust,导致网页字体换入时段落和标题明显重排。
  • 使用静态 vh 单位(而非动态或小视口单位 [dvh、svh])调整主打版块和全屏布局的大小,导致内容在移动浏览器工具栏展开和收起时发生跳动。
  • 在客户端 A/B 测试中,使用旧版 opacity:0 或 visibility:hidden 防闪烁代码段和多秒超时来隐藏内容(延迟 LCP 并使不可见元素可点击),而不是在可用时使用带有 blocking="render" 的脚本。
  • 在关键的首屏标记解析之前触发跨文档视图过渡,而不是使用 rel="expect" 和 blocking="render" 保持首次渲染,导致解析了一半的元素在过渡过程中突然出现。

9. 安全性:DOM XSS 防御和 HTML 清理

单个跨站脚本攻击 (XSS) 漏洞可让攻击者在用户浏览器中运行任意代码,窃取会话数据或代表用户采取行动。这就是为什么浏览器强制执行的防御措施(例如安全的 HTML 清理、可信类型和严格的 CSP)如此重要的原因。

模型很少会主动解决这些安全问题。例如,在完整评估套件的所有任务中,模型均未在没有明确提示的情况下添加内容安全政策 (CSP) 或跨域隔离标头。

即使提示直接要求安全性,未经引导的模型仍有超过一半的安全检查失败,从而导致脆弱的自定义回退或不完整的政策。在防范 DOM XSS 时,这一点尤为明显:

  • 在无法使用原生清理功能时,编写手动 DOMParser 许可清单清理工具(作为 setHTML() 回退或在可信类型政策中),而不是使用经过审核的库(例如 DOMPurify)。
  • 在每次网页加载时都急切地捆绑 DOMPurify,而不是在受支持时使用原生 setHTML(),并且仅在后备情况下延迟加载 DOMPurify。
  • 注册了会破坏接收器强制执行的宽松 (input) => input 直通式可信类型政策。
  • 在静态网页上将可信类型与主机许可清单 script-src 'self' CSP 配对,而不是使用 SHA-256 哈希锁定内嵌脚本。
  • 在配置基于 Nonce 的 script-src 内容安全政策时,省略了 'strict-dynamic' 和 'report-sample'。

10. 安全:通行密钥登录、重新身份验证和凭证生命周期

通行密钥可提高用户安全性,并提升企业的登录转化率,但实现起来(即使有智能体协助)也颇具挑战性。

WebAuthn 具有特定的序列化、功能检测和信号 API,在我们的评估中,无引导模型几乎完全忽略了这些 API。如果您要求 AI 模型添加通行密钥登录、管理或升级重新身份验证功能,它通常会编写手动字节编码辅助程序、跳过管理界面上的功能检查,或使凭据与密码管理工具不同步:

  • 手动编写 atob() 和 btoa() Base64URL 转换辅助函数(作为主要路径或冗余后备样板),而不是依赖 parseCreationOptionsFromJSON()、parseRequestOptionsFromJSON() 和 credential.toJSON() 等内置序列化方法。
  • 当服务器报告未知凭据 ID 时,在登录期间省略 PublicKeyCredential.signalUnknownCredential(),从而在用户的密码管理工具中保留已删除或已撤销的通行密钥。
  • 在呈现通行密钥创建和管理界面之前,跳过 PublicKeyCredential.getClientCapabilities()。
  • 在启动升级通行密钥重新身份验证请求时省略 AbortController 和 AbortSignal。
  • 传递源试用 mediation:"immediate" 选项(而非 uiMode:"immediate"),以显示简化的登录提示。

弥补这些差距

这 10 个领域远非详尽无遗,我们预计具体的知识差距会随着时间的推移而发生变化。模型会迎头赶上,Web 平台也会继续发展。

好消息是,Modern Web Guidance 填补了所有这些空白,并且会随着平台的发展而不断演进。

如需开始使用 Modern Web Guidance,请运行以下命令,或在智能体的插件市场中搜索该插件:

npx modern-web-guidance@latest install

您是否发现模型在其他 Web 开发任务中出错?我们希望收到关于此问题的反馈。在 Modern Web Guidance GitHub 代码库中提交问题,或通过贡献项目来帮助我们为其他开发者弥补这些差距。