bootstrap轮播需显式关闭自动播放:data-bs-interval="false",保留data-bs-ride="carousel"初始化组件,同时为指示器按钮添加aria-label、图片设置有效alt,并补全键盘可访问的手动控制逻辑。

nav 必须带 aria-label="主导航",否则读屏器会跳过
很多开发者把 nav 当成普通容器用,只加 class 或 id,结果在无障碍测试中直接失败。浏览器和 NVDA、VoiceOver 等读屏工具依赖 aria-label 识别导航意图。不写这个属性,移动端用户可能根本不知道顶部有一组可操作的菜单。
常见错误现象:
– 移动端 VoiceOver 滑动时直接从 logo 跳到轮播图,中间导航“消失”
– 自动化检测工具(如 axe)报错 ARIA11: Missing aria-label on navigation
-
nav必须是header的直接子元素,不能套在div里 - 不要用
aria-labelledby替代aria-label,除非你真有一个 visible、id 匹配的标题元素 - 如果页面有多个
nav(比如页脚也有链接区),每个都得有不同aria-label,例如aria-label="页脚导航"
轮播图禁用 data-bs-interval 是 B2B 官网的合理默认
自动轮播看似“高级”,但实测会显著降低转化率:用户刚点进产品介绍,图片突然切走,文案没读完就中断。Bootstrap 5 的 carousel 默认开启自动播放,必须显式关闭。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
正确写法是:<div class="carousel slide" data-bs-ride="carousel" data-bs-interval="false">
<ul>
<li>保留 <code>data-bs-ride="carousel" 启用组件初始化,仅关掉自动切换
<button></button> 必须带 aria-label="切换到第 2 张图片",不能只靠视觉圆点<img> 的 alt 属性不可为空;若为装饰图,用 alt="" + role="presentation"
Enter 和 Space 触发产品区用 Bootstrap row/col 比 CSS Grid 更适合 CMS 接入场景
Grid 写起来确实简洁,display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) 一行搞定三栏,但一旦后续要接入 WordPress 或 Contentful 这类 CMS,就得重写结构:CMS 输出的卡片通常包裹在 <div class="product-item"> 里,不是原生 <code>article,Grid 对 class 无感,而 Bootstrap 的 col-lg-4 可直接挂载在任意容器上。
- 每个产品卡片必须用
<article></article>或带role="region"的<div>,否则屏幕阅读器无法划分内容区块 <li>图片建议统一设 <code>aspect-ratio: 4/3+object-fit: cover,避免拉伸或留白不一致 - IE11 完全不支持
aspect-ratio,如需兼容,改用 padding-bottom 百分比 hack 或放弃 IE 支持(2026 年多数企业官网已明确不保) - 按钮必须用
<button></button>,不能用<div> 或 <code><span></span>模拟,否则键盘Tab无法聚焦 -
aria-controls的值要和目标菜单的id严格一致,大小写、连字符都不能错 - 别用
setTimeout做延时切换——页面切后台再回来,容易触发多次 toggle 导致状态错乱;改用requestAnimationFrame或事件委托更稳
真正卡住上线的,往往不是布局错位,而是这些细节点:读屏器读不出导航、轮播图切走用户正在看的文案、CMS 插入后三栏崩成一列、折叠菜单按钮按了没反馈。它们不报红错,但一测无障碍就挂,一跑 Lighthouse 就扣分,一上线就被客户指着说“怎么手机上点不开菜单”。
移动端折叠菜单的 aria-expanded 必须与 display 同步更新
只靠 CSS 切换 display: none/block 不够。读屏器不会监听样式变化,它只看 ARIA 属性。如果菜单展开时 aria-expanded="false" 还挂着,用户听到的是“导航菜单,已折叠”,实际却是展开状态——这是典型的逻辑断裂。
正确做法是:JS 控制菜单显隐时,同步操作两个属性:dropdownButton.setAttribute('aria-expanded', 'true')dropdownMenu.setAttribute('aria-controls', 'nav-menu-id')










