Bootstrap 5 中按钮文字应使用 visually-hidden 与响应式类组合实现可访问性显隐,而非 d-none;如用 visually-hidden-sm d-md-inline 保证小屏隐藏文字但屏幕阅读器仍可读,图标需加 aria-hidden="true"。
Bootstrap 5 中用 visually-hidden + 响应式类控制按钮文字显隐
直接结论:别用 hidden 或 d-none 粗暴隐藏,而是组合 visually-hidden 和响应式显示类(如 d-md-inline),兼顾可访问性与视觉效果。
常见错误是写成 <button><span class="d-md-inline">保存</span><i class="bi bi-floppy"></i></button> —— 小屏下文字虽不可见,但仍在 DOM 中占据空间,图标可能错位;更糟的是,屏幕阅读器仍会读出“保存”,造成语义混乱。
-
visually-hidden是 Bootstrap 5 内置的辅助类,它让元素对视觉用户隐藏,但保留在可访问树中(适合仅需图标、但需保留语义的场景) - 真正控制“大屏显示文字、小屏只留图标”的关键是:文字用
visually-hidden visually-hidden-sm d-md-inline,图标保持始终可见 - 注意顺序:
visually-hidden-sm在 Bootstrap 5.3+ 才支持;若用旧版,改用visually-hidden d-sm-inline(即默认隐藏,仅在 sm 及以上显示)
<button type="button" class="btn btn-primary"> <i class="bi bi-floppy me-1"></i> <span class="visually-hidden visually-hidden-sm d-md-inline">保存</span> </button>
为什么不用 d-none d-md-block 切换文字?
因为 d-none 会让元素完全脱离渲染流和可访问树——屏幕阅读器根本读不到“保存”,按钮变成无意义的图标,违反 WCAG 2.1。尤其表单提交按钮、操作按钮,必须有明确的可访问名称。
实操中容易忽略的一点:如果图标本身没 aria-hidden="true",而文字又被 d-none 掉,读屏软件可能只读图标 Unicode 名(比如“U+F0C7”),用户完全不知其意。
- 正确做法:图标加
aria-hidden="true",文字用visually-hidden保证可访问性 - 错误示例:
<span class="d-none d-md-inline">删除</span>→ 小屏下无障碍支持失效 - 兼容性注意:
visually-hidden-sm需 Bootstrap 5.3+;5.2 及以下只能靠visually-hidden d-sm-inline
自定义响应断点时如何适配?
如果你改过 Bootstrap 的断点(比如把 md 改成 lg),所有 d-md- 类都会失效。此时不能硬编码类名,得用 Sass 重编译或 JS 动态处理。
更轻量的做法:用原生媒体查询 + 自定义类,避免依赖框架断点命名:
.btn-icon-text .text-label {
clip: rect(1px, 1px, 1px, 1px);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
@media (min-width: 768px) {
.btn-icon-text .text-label {
clip: auto;
height: auto;
overflow: visible;
position: static;
white-space: normal;
width: auto;
}
}
然后按钮里写:<span class="text-label">编辑</span>。这样不耦合 Bootstrap 版本,也方便后续维护。
React/Vue 项目里怎么避免重复写响应逻辑?
不要每个按钮都手写一堆类。封装一个 IconTextButton 组件,接收 label 和 icon,内部自动注入 visually-hidden 和响应类。
Vue 示例(选项 API):
<template>
<button :class="btnClass">
<i v-bind="iconProps" class="me-1"></i>
<span class="visually-hidden visually-hidden-sm d-md-inline">{{ label }}</span>
</button>
</template>
<script>
export default {
props: {
label: { type: String, required: true },
icon: { type: String, required: true },
btnClass: { type: String, default: 'btn btn-outline-secondary' }
},
computed: {
iconProps() {
return { class: this.icon };
}
}
};
</script>
关键点:组件内固定用 visually-hidden-sm,而不是让用户传类名——否则极易漏掉可访问性保障。
复杂点在于,不同项目断点配置不同,且部分团队用 Tailwind 替代 Bootstrap;这时候最稳妥的仍是 CSS 自定义 + 语义化 HTML,而不是强依赖某套框架的类名体系。


















