弹出框
为网站上的任何元素添加 Bootstrap 弹出框(如 iOS 中的弹出框)的文档和示例。
概述
使用弹出框插件时需要了解的事项
- 弹出框依赖第三方库 Popper 进行定位。您必须在
bootstrap.js
之前包含 popper.min.js,或使用包含 Popper 的bootstrap.bundle.min.js
。 - 弹出框需要 弹出框插件 作为依赖项。
- 出于性能原因,弹出框是可选择加入的,因此您必须自己初始化它们。
- 零长度的
title
和content
值永远不会显示弹出框。 - 指定
container: 'body'
以避免在更复杂的组件(如我们的输入组、按钮组等)中出现渲染问题。 - 对隐藏元素触发弹出框不起作用。
- 针对
.disabled
或disabled
元素的弹出框必须在包装元素上触发。 - 当从跨多行的锚点触发时,弹出框将居中于锚点的整体宽度之间。在
<a>
上使用.text-nowrap
以避免此行为。 - 必须在将相应的元素从 DOM 中删除之前隐藏弹出框。
- 可以触发弹出框,这要归功于阴影 DOM 中的元素。
prefers-reduced-motion
媒体查询。请参阅 无障碍文档中的减少运动部分。
继续阅读,了解如何通过一些示例使用弹出框。
示例
启用弹出框
如上所述,必须先初始化弹出框,然后才能使用它们。初始化页面上所有弹出框的一种方法是通过其 data-bs-toggle
属性选择它们,如下所示
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
实时演示
我们使用类似于上述代码段的 JavaScript 来呈现以下实时弹出框。标题通过 data-bs-title
设置,正文内容通过 data-bs-content
设置。
title
或 data-bs-title
。当使用 title
时,Popper 会在元素呈现时自动将其替换为 data-bs-title
。
<button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" data-bs-title="Popover title" data-bs-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>
四个方向
有四个选项可用:顶部、右侧、底部和左侧。在 RTL 中使用 Bootstrap 时,方向会镜像。设置 data-bs-placement
以更改方向。
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Top popover">
Popover on top
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="right" data-bs-content="Right popover">
Popover on right
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Bottom popover">
Popover on bottom
</button>
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="left" data-bs-content="Left popover">
Popover on left
</button>
自定义 container
当父元素上的一些样式会干扰弹出框时,需要指定一个自定义 container
,以便弹出框的 HTML 出现在该元素内。这在响应式表格、输入组等中很常见。
const popover = new bootstrap.Popover('.example-popover', {
container: 'body'
})
需要设置显式自定义 container
的另一种情况是 模态对话框 中的弹出框,以确保弹出框本身附加到模态。对于包含交互式元素的弹出框,这一点尤其重要——模态对话框会捕获焦点,因此除非弹出框是模态的子元素,否则用户将无法聚焦或激活这些交互式元素。
const popover = new bootstrap.Popover('.example-popover', {
container: '.modal-body'
})
自定义弹出框
在 v5.2.0 中添加你可以使用 CSS 变量 来自定义弹出框的外观。我们使用 data-bs-custom-class="custom-popover"
设置一个自定义类,以限定我们的自定义外观,并使用它来覆盖一些本地 CSS 变量。
.custom-popover {
--bs-popover-max-width: 200px;
--bs-popover-border-color: var(--bd-violet-bg);
--bs-popover-header-bg: var(--bd-violet-bg);
--bs-popover-header-color: var(--bs-white);
--bs-popover-body-padding-x: 1rem;
--bs-popover-body-padding-y: .5rem;
}
<button type="button" class="btn btn-secondary"
data-bs-toggle="popover" data-bs-placement="right"
data-bs-custom-class="custom-popover"
data-bs-title="Custom popover"
data-bs-content="This popover is themed via CSS variables.">
Custom popover
</button>
下次点击时消失
使用 focus
触发器在用户下次点击除切换元素之外的元素时关闭弹出框。
<a tabindex="0" class="btn btn-lg btn-danger" role="button" data-bs-toggle="popover" data-bs-trigger="focus" data-bs-title="Dismissible popover" data-bs-content="And here's some amazing content. It's very engaging. Right?">Dismissible popover</a>
const popover = new bootstrap.Popover('.popover-dismiss', {
trigger: 'focus'
})
禁用元素
具有 disabled
属性的元素不可交互,这意味着用户无法将鼠标悬停在它们上面或单击它们以触发弹出框(或工具提示)。作为一种解决方法,你希望从包装 <div>
或 <span>
触发弹出框,理想情况下使用 tabindex="0"
使其可通过键盘聚焦。
对于禁用的弹出框触发器,你可能还更喜欢 data-bs-trigger="hover focus"
,以便弹出框作为立即的视觉反馈显示给你的用户,因为他们可能不会期望在禁用的元素上点击。
<span class="d-inline-block" tabindex="0" data-bs-toggle="popover" data-bs-trigger="hover focus" data-bs-content="Disabled popover">
<button class="btn btn-primary" type="button" disabled>Disabled button</button>
</span>
CSS
变量
在 v5.2.0 中添加作为 Bootstrap 不断发展的 CSS 变量方法的一部分,弹出框现在在 .popover
上使用本地 CSS 变量,以增强实时自定义。CSS 变量的值通过 Sass 设置,因此 Sass 自定义仍然受支持。
--#{$prefix}popover-zindex: #{$zindex-popover};
--#{$prefix}popover-max-width: #{$popover-max-width};
@include rfs($popover-font-size, --#{$prefix}popover-font-size);
--#{$prefix}popover-bg: #{$popover-bg};
--#{$prefix}popover-border-width: #{$popover-border-width};
--#{$prefix}popover-border-color: #{$popover-border-color};
--#{$prefix}popover-border-radius: #{$popover-border-radius};
--#{$prefix}popover-inner-border-radius: #{$popover-inner-border-radius};
--#{$prefix}popover-box-shadow: #{$popover-box-shadow};
--#{$prefix}popover-header-padding-x: #{$popover-header-padding-x};
--#{$prefix}popover-header-padding-y: #{$popover-header-padding-y};
@include rfs($popover-header-font-size, --#{$prefix}popover-header-font-size);
--#{$prefix}popover-header-color: #{$popover-header-color};
--#{$prefix}popover-header-bg: #{$popover-header-bg};
--#{$prefix}popover-body-padding-x: #{$popover-body-padding-x};
--#{$prefix}popover-body-padding-y: #{$popover-body-padding-y};
--#{$prefix}popover-body-color: #{$popover-body-color};
--#{$prefix}popover-arrow-width: #{$popover-arrow-width};
--#{$prefix}popover-arrow-height: #{$popover-arrow-height};
--#{$prefix}popover-arrow-border: var(--#{$prefix}popover-border-color);
Sass 变量
$popover-font-size: $font-size-sm;
$popover-bg: var(--#{$prefix}body-bg);
$popover-max-width: 276px;
$popover-border-width: var(--#{$prefix}border-width);
$popover-border-color: var(--#{$prefix}border-color-translucent);
$popover-border-radius: var(--#{$prefix}border-radius-lg);
$popover-inner-border-radius: calc(#{$popover-border-radius} - #{$popover-border-width}); // stylelint-disable-line function-disallowed-list
$popover-box-shadow: var(--#{$prefix}box-shadow);
$popover-header-font-size: $font-size-base;
$popover-header-bg: var(--#{$prefix}secondary-bg);
$popover-header-color: $headings-color;
$popover-header-padding-y: .5rem;
$popover-header-padding-x: $spacer;
$popover-body-color: var(--#{$prefix}body-color);
$popover-body-padding-y: $spacer;
$popover-body-padding-x: $spacer;
$popover-arrow-width: 1rem;
$popover-arrow-height: .5rem;
用法
通过 JavaScript 启用弹出框
const exampleEl = document.getElementById('example')
const popover = new bootstrap.Popover(exampleEl, options)
确保弹出框对键盘和辅助技术用户可用,方法是仅将它们添加到传统上可通过键盘聚焦且可交互的 HTML 元素(例如链接或表单控件)。虽然可以通过添加 tabindex="0"
使其他 HTML 元素可聚焦,但这会在非交互元素上为键盘用户创建烦人且令人困惑的制表位,并且大多数辅助技术在这种情况目前不会播报弹出框。此外,不要仅依赖 hover
作为弹出框的触发器,因为这会让键盘用户无法触发它们。
避免在弹出框中添加过多的内容,方法是使用 html
选项。一旦显示弹出框,它们的内容就会通过 aria-describedby
属性与触发元素绑定,导致所有弹出框的内容都会作为一条长而连续的流向辅助技术用户播报。
弹出框不管理键盘焦点顺序,并且它们在 DOM 中的位置可能是随机的,因此在添加交互元素(如表单或链接)时要小心,因为它可能会导致不合逻辑的焦点顺序,或使弹出框内容本身对键盘用户完全不可达。在必须使用这些元素的情况下,请考虑改用模态对话框。
选项
由于可以通过数据属性或 JavaScript 传递选项,因此可以将选项名称附加到 data-bs-
,如 data-bs-animation="{value}"
。通过数据属性传递选项时,请务必将选项名称的类型从“camelCase”更改为“kebab-case”。例如,使用 data-bs-custom-class="beautifier"
而不是 data-bs-customClass="beautifier"
。
从 Bootstrap 5.2.0 开始,所有组件都支持一个实验性保留数据属性 data-bs-config
,它可以将简单的组件配置作为 JSON 字符串容纳起来。当一个元素具有 data-bs-config='{"delay":0, "title":123}'
和 data-bs-title="456"
属性时,最终的 title
值将为 456
,并且单独的数据属性将覆盖 data-bs-config
上给定的值。此外,现有数据属性能够容纳 JSON 值,例如 data-bs-delay='{"show":0,"hide":150}'
。
最终的配置对象是 data-bs-config
、data-bs-
和 js object
的合并结果,其中最新给定的键值会覆盖其他键值。
sanitize
、sanitizeFn
和 allowList
选项不能使用数据属性提供。
名称 | 类型 | 默认 | 说明 |
---|---|---|---|
allowList |
对象 | 默认值 | 包含允许的属性和标签的对象。 |
animation |
布尔值 | true |
对弹出框应用 CSS 淡入淡出过渡。 |
boundary |
字符串、元素 | 'clippingParents' |
弹出框的溢出约束边界(仅适用于 Popper 的 preventOverflow 修饰符)。默认情况下,它是 'clippingParents' ,并且可以接受一个 HTMLElement 引用(仅限 JavaScript)。有关更多信息,请参阅 Popper 的 detectOverflow 文档。 |
container |
字符串、元素、false | false |
将弹出框附加到特定元素。示例:container: 'body' 。此选项特别有用,因为它允许你将弹出框定位在触发元素附近的文档流中 - 这将防止弹出框在窗口调整大小时远离触发元素。 |
content |
字符串、元素、函数 | '' |
弹出框的文本内容。如果给定一个函数,它将被调用,其 this 引用设置为弹出框附加到的元素。 |
customClass |
字符串、函数 | '' |
在弹出框显示时向其添加类。请注意,这些类将添加到模板中指定的任何类中。要添加多个类,请用空格分隔它们:'class-1 class-2' 。你还可以传递一个函数,该函数应返回一个包含其他类名的字符串。 |
delay |
数字、对象 | 0 |
延迟显示和隐藏弹出框(毫秒) - 不适用于手动触发类型。如果提供一个数字,则延迟将应用于隐藏/显示。对象结构为:delay: { "show": 500, "hide": 100 } 。 |
fallbackPlacements |
字符串、数组 | ['top', 'right', 'bottom', 'left'] |
通过提供数组中的位置列表(按优先顺序)来定义备用位置。有关更多信息,请参阅 Popper 的 行为文档。 |
html |
布尔值 | false |
允许在弹出框中使用 HTML。如果为 true,则弹出框 title 中的 HTML 标签将在弹出框中呈现。如果为 false,则 innerText 属性将用于将内容插入到 DOM 中。如果你担心 XSS 攻击,请使用文本。 |
offset |
数字、字符串、函数 | [0, 0] |
弹出框相对于其目标的偏移量。你可以使用逗号分隔的值传递数据属性中的字符串,例如:data-bs-offset="10,20" 。当使用函数确定偏移量时,它将被调用,其对象包含弹出框位置、引用和弹出框矩形作为其第一个参数。触发元素 DOM 节点作为第二个参数传递。该函数必须返回一个包含两个数字的数组:skidding、distance。有关更多信息,请参阅 Popper 的 offset 文档。 |
placement |
字符串、函数 | '顶部' |
如何定位弹出框:自动、顶部、底部、左侧、右侧。当指定auto 时,它将动态重新定向弹出框。当使用函数来确定位置时,它将使用弹出框 DOM 节点作为其第一个参数,并将触发元素 DOM 节点作为其第二个参数。this 上下文被设置为弹出框实例。 |
popperConfig |
null、对象、函数 | null |
要更改 Bootstrap 的默认 Popper 配置,请参阅 Popper 的配置。当使用函数创建 Popper 配置时,它将使用包含 Bootstrap 的默认 Popper 配置的对象进行调用。它可以帮助你使用和合并默认配置与你自己的配置。该函数必须为 Popper 返回一个配置对象。 |
sanitize |
布尔值 | true |
启用或禁用清理。如果激活'template' 、'content' 和'title' 选项将被清理。 |
sanitizeFn |
null、函数 | null |
在这里,你可以提供你自己的清理函数。如果你更喜欢使用专门的库来执行清理,这会很有用。 |
selector |
字符串、false | false |
如果提供了选择器,弹出框对象将被委托给指定的 target。实际上,这用于将弹出框应用于动态添加的 DOM 元素(jQuery.on 支持)。请参阅 此问题 和 一个信息丰富的示例。注意:title 属性不得用作选择器。 |
template |
字符串 | '<div class="popover" role="tooltip"><div class="popover-arrow"></div><div class="popover-inner"></div></div>' |
创建弹出框时要使用的基本 HTML。弹出框的title 将被注入到.popover-inner 中。.popover-arrow 将成为弹出框的箭头。最外层的包装元素应具有.popover 类和role="tooltip" 。 |
title |
字符串、元素、函数 | '' |
弹出框标题。如果给定一个函数,它将被调用,其this 引用设置为弹出框附加到的元素。 |
trigger |
字符串 | 'hover focus' |
弹出框的触发方式:点击、悬停、聚焦、手动。你可以传递多个触发器;用空格分隔它们。'manual' 表示弹出框将通过 .popover('show') 、.popover('hide') 和 .popover('toggle') 方法以编程方式触发;此值不能与任何其他触发器结合使用。单独使用 'hover' 将导致无法通过键盘触发的弹出框,并且仅当存在向键盘用户传达相同信息的替代方法时才应使用。 |
使用带有 popperConfig
的函数
const popover = new bootstrap.Popover(element, {
popperConfig(defaultBsPopperConfig) {
// const newPopperConfig = {...}
// use defaultBsPopperConfig if needed...
// return newPopperConfig
}
})
方法
方法 | 说明 |
---|---|
disable |
移除元素的弹出框显示功能。只有在重新启用弹出框后,才能显示弹出框。 |
dispose |
隐藏并销毁元素的弹出框(移除 DOM 元素上存储的数据)。使用委托(使用 selector 选项 创建)的弹出框不能在后代触发器元素上单独销毁。 |
enable |
赋予元素的弹出框显示功能。弹出框默认启用。 |
getInstance |
静态 方法,允许你获取与 DOM 元素关联的弹出框实例。 |
getOrCreateInstance |
静态 方法,允许你获取与 DOM 元素关联的弹出框实例,或者在未初始化的情况下创建一个新的实例。 |
hide |
隐藏元素的弹出框。在弹出框实际隐藏之前(即在 hidden.bs.popover 事件发生之前)返回给调用者。这被认为是弹出框的“手动”触发。 |
setContent |
提供了一种在初始化后更改弹出框内容的方法。 |
show |
显示元素的弹出框。在弹出框实际显示之前返回给调用者(即在 shown.bs.popover 事件发生之前)。这被认为是对弹出框的“手动”触发。标题和内容都为零长度的弹出框永远不会显示。 |
toggle |
切换元素的弹出框。在弹出框实际显示或隐藏之前返回给调用者(即在 shown.bs.popover 或 hidden.bs.popover 事件发生之前)。这被认为是对弹出框的“手动”触发。 |
toggleEnabled |
切换元素弹出框的显示或隐藏功能。 |
update |
更新元素弹出框的位置。 |
// getOrCreateInstance example
const popover = bootstrap.Popover.getOrCreateInstance('#example') // Returns a Bootstrap popover instance
// setContent example
popover.setContent({
'.popover-header': 'another title',
'.popover-body': 'another content'
})
setContent
方法接受一个 object
参数,其中每个属性键都是弹出框模板中有效的 string
选择器,每个相关的属性值可以是 string
| element
| function
| null
事件
事件 | 说明 |
---|---|
hide.bs.popover |
当调用 hide 实例方法时,会立即触发此事件。 |
hidden.bs.popover |
当弹出框完成对用户隐藏后触发此事件(将等待 CSS 过渡完成)。 |
inserted.bs.popover |
当弹出框模板被添加到 DOM 时,在 show.bs.popover 事件后触发此事件。 |
show.bs.popover |
当调用 show 实例方法时,会立即触发此事件。 |
shown.bs.popover |
当弹出框对用户可见时触发此事件(将等待 CSS 过渡完成)。 |
const myPopoverTrigger = document.getElementById('myPopover')
myPopoverTrigger.addEventListener('hidden.bs.popover', () => {
// do something...
})