概述
<b-overlay>
可用于遮挡几乎所有内容。示例用例包括表单、表格、删除确认对话框,或任何需要发出应用程序正在执行后台任务、发出特定组件不可用或向最终用户提供额外上下文的信号的地方。
<b-overlay>
可用于覆盖(包裹)元素或组件(默认行为),或可作为 position: relative
元素的后代放置(非包裹模式)。
覆盖层可见性通过 show
属性控制。默认情况下,不显示覆盖层。
请注意,此组件仅在视觉上遮盖其内容(或页面)。有关其他辅助功能详细信息和注意事项,请参阅下面的 辅助功能部分。
默认包装模式示例
<template>
<div>
<b-overlay :show="show" rounded="sm">
<b-card title="Card with overlay" :aria-hidden="show ? 'true' : null">
<b-card-text>Laborum consequat non elit enim exercitation cillum.</b-card-text>
<b-card-text>Click the button to toggle the overlay:</b-card-text>
<b-button :disabled="show" variant="primary" @click="show = true">
Show overlay
</b-button>
</b-card>
</b-overlay>
<b-button class="mt-3" @click="show = !show">Toggle overlay</b-button>
</div>
</template>
<script>
export default {
data() {
return {
show: false
}
}
}
</script>
选项
有许多选项可用于设置覆盖层的样式,并在覆盖层中提供自定义内容。
覆盖层背景颜色
您可以通过 variant
属性控制背景背景颜色。该变体将转换为 Bootstrap 的 背景变体实用程序类 之一。通过 opacity
属性控制背景的不透明度(不透明度值范围为 0
到 1
)。背景模糊可以通过 blur
属性控制。
<template>
<div>
<b-row>
<b-col lg="6" aria-controls="overlay-background">
<b-form-group label="Variant" label-for="bg-variant" label-cols-sm="4" label-cols-lg="12">
<b-form-select id="bg-variant" v-model="variant" :options="variants"></b-form-select>
</b-form-group>
<b-form-group label="Opacity" label-for="bg-opacity" label-cols-sm="4" label-cols-lg="12">
<b-input-group>
<b-form-input
id="bg-opacity"
v-model="opacity"
type="range"
number
min="0"
max="1"
step="0.01"
></b-form-input>
<b-input-group-append is-text class="text-monospace">
{{ opacity.toFixed(2) }}
</b-input-group-append>
</b-input-group>
</b-form-group>
<b-form-group label="Blur" label-for="bg-blur" label-cols-sm="4" label-cols-lg="12">
<b-form-select id="bg-blur" v-model="blur" :options="blurs"></b-form-select>
</b-form-group>
</b-col>
<b-col lg="6">
<b-overlay
id="overlay-background"
show
:variant="variant"
:opacity="opacity"
:blur="blur"
rounded="sm"
>
<b-card title="Card with overlay" aria-hidden="true">
<b-card-text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</b-card-text>
<b-button disabled variant="primary">Button</b-button>
</b-card>
</b-overlay>
</b-col>
</b-row>
</div>
</template>
<script>
export default {
data() {
return {
variant: 'light',
opacity: 0.85,
blur: '2px',
variants: [
'transparent',
'white',
'light',
'dark',
'primary',
'secondary',
'success',
'danger',
'warning',
'info',
],
blurs: [
{ text: 'None', value: '' },
'1px',
'2px',
'5px',
'0.5em',
'1rem'
]
}
}
}
</script>
作为 variant
属性的替代方案,您可以通过 bg-color
属性指定 CSS 颜色字符串值。当为 bg-color
提供值时,将忽略 variant
属性值。
备注
- 某些浏览器(例如 IE 11)不支持背景模糊。
- 模糊要求不透明度级别相对较高才能使效果可见。
淡入淡出过渡
默认情况下,覆盖层在显示或隐藏时使用 Bootstrap 的淡入淡出过渡。您可以通过将 no-fade
属性添加到 <b-overlay>
来禁用淡入淡出过渡。
默认的微调样式
默认覆盖内容是 <b-spinner>
,类型为 'border'
。你可以通过以下属性控制 spinner 的外观
spinner-type
:当前支持的值是 'border'
(默认值)或 'grow'
。 spinner-variant
:spinner 的变体主题颜色。默认值为 null
,它继承当前字体颜色。 spinner-small
:设置为 true
以呈现一个小型 spinner。
<template>
<div>
<b-overlay
show
spinner-variant="primary"
spinner-type="grow"
spinner-small
rounded="sm"
style="max-width: 320px;"
>
<b-card title="Card with spinner style" aria-hidden="true">
<b-card-text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</b-card-text>
<b-button disabled variant="primary">Button</b-button>
</b-card>
</b-overlay>
</div>
</template>
覆盖角部圆角
默认情况下,覆盖背景是直角的。如果你要包装的内容是圆角的,则可以使用 rounded
属性将圆角应用到覆盖的角部,以匹配被遮挡内容的圆角。
可能的值是
true
(或空字符串 ''
)应用默认(中等)圆角 false
(默认值)不将圆角应用到背景覆盖 'sm'
表示小圆角 'lg'
表示大圆角 'pill'
表示药丸样式圆角 'circle'
表示圆形(或椭圆形)圆角 'top'
表示仅对前两个角进行圆角 'bottom'
表示仅对后两个角进行圆角 'left'
表示仅对左两个角进行圆角 'right'
表示仅对右两个角进行圆角
<template>
<div>
<b-button @click="show = !show">Toggle overlay</b-button>
<b-row class="text-center mt-3">
<b-col md="6">
<p>With rounding</p>
<b-overlay :show="show" class="d-inline-block" rounded="circle">
<b-img thumbnail rounded="circle" fluid src="https://picsum.photos/200/200/?image=54" alt="Image 1"></b-img>
</b-overlay>
</b-col>
<b-col md="6">
<p>Without rounding</p>
<b-overlay :show="show" class="d-inline-block">
<b-img thumbnail rounded="circle" fluid src="https://picsum.photos/200/200/?image=54" alt="Image 1"></b-img>
</b-overlay>
</b-col>
</b-row>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
自定义覆盖内容
通过可选范围槽 overlay
将自定义内容放置在覆盖中(替换默认 spinner)。
<template>
<div>
<b-overlay :show="show" rounded="sm" @shown="onShown" @hidden="onHidden">
<b-card title="Card with custom overlay content" :aria-hidden="show ? 'true' : null">
<b-card-text>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</b-card-text>
<b-card-text>Click the button to toggle the overlay:</b-card-text>
<b-button ref="show" :disabled="show" variant="primary" @click="show = true">
Show overlay
</b-button>
</b-card>
<template #overlay>
<div class="text-center">
<b-icon icon="stopwatch" font-scale="3" animation="cylon"></b-icon>
<p id="cancel-label">Please wait...</p>
<b-button
ref="cancel"
variant="outline-danger"
size="sm"
aria-describedby="cancel-label"
@click="show = false"
>
Cancel
</b-button>
</div>
</template>
</b-overlay>
</div>
</template>
<script>
export default {
data() {
return {
show: false
}
},
methods: {
onShown() {
this.$refs.cancel.focus()
},
onHidden() {
this.$refs.show.focus()
}
}
}
</script>
以下范围属性可用于 overlay
槽
属性 | 说明 |
spinnerVariant | 属性 spinner-variant 的值 |
spinnerType | 属性 spinner-type 的值 |
spinnerSmall | 属性 spinner-small 的值 |
出于可访问性原因,在覆盖层中放置交互式内容时,应当关注自定义内容的容器或覆盖层内容中的某个可聚焦控件。你可以监听 <b-overlay>
'shown'
事件,以了解何时可以在文档中使用覆盖层内容。
覆盖层内容居中
默认情况下,覆盖层内容将在覆盖层区域内水平和垂直居中。要禁用居中,将 no-center
属性设置为 true
。
在以下示例中,我们设置了 no-center
属性,并将自定义覆盖层插槽内容绝对定位在右上角。
<template>
<div>
<b-overlay no-center show rounded="sm">
<template #overlay>
<b-icon
icon="stopwatch"
variant="info"
scale="2"
shift-v="8"
shift-h="8"
class="position-absolute"
style="top: 0; right: 0"
></b-icon>
</template>
<b-card title="Card with no-center overlay" aria-hidden="true">
<b-card-text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</b-card-text>
<b-button disabled variant="primary">Button</b-button>
</b-card>
</b-overlay>
</div>
</template>
宽度
<b-overlay>
的默认宽度为 100%
。当包装内联或内联块元素时,你需要添加类 d-inline-block
(例如 <b-overlay class="d-inline-block">
)。
你还可以使用宽度 实用程序类 或 CSS 样式来控制覆盖层包装容器元素的宽度。
非包装模式
默认情况下,<b-overlay>
包装默认插槽的内容。在某些情况下,你可能希望模糊父容器。使用 no-wrap
属性来禁用包装的渲染(并忽略默认插槽)。请注意,这要求要模糊的祖先元素具有相对定位(通过实用程序类 'position-relative'
或 CSS 样式 'position: relative;'
)。
<template>
<div>
<div class="position-relative p-4 bg-info">
<p class="text-light font-weight-bold">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<b-card title="Card with parent overlay">
<b-card-text>Laborum consequat non elit enim exercitation cillum.</b-card-text>
<b-card-text>Click the button to toggle the overlay:</b-card-text>
<b-button :disabled="show" variant="primary" @click="show = true">
Show overlay
</b-button>
</b-card>
<p class="text-light font-weight-bold mb-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<b-overlay :show="show" no-wrap>
</b-overlay>
</div>
<b-button class="mt-3" @click="show = !show">Toggle overlay</b-button>
</div>
</template>
<script>
export default {
data() {
return {
show: false
}
}
}
</script>
请注意,Bootstrap v4 的某些组件样式定义了相对定位(例如卡片、列等)。你可能需要调整 <b-overlay>
在标记中的位置。
例如,<b-card>
具有相对定位,因此你可以将 <b-overlay no-wrap>
作为 <b-card>
的后代
<template>
<div>
<b-card header="Card header" footer="Card footer">
<b-media>
<template #aside>
<b-img
thumbnail
rounded="circle"
src="https://picsum.photos/72/72/?image=58"
alt="Image"
></b-img>
</template>
<p class="mb-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</b-media>
<b-overlay :show="show" no-wrap></b-overlay>
</b-card>
<b-button @click="show = !show" class="mt-3">Toggle overlay</b-button>
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
}
</script>
在 no-wrap
模式下,<b-overlay>
不会在被遮挡的元素上设置 aria-busy
属性。你可能还想在你的应用中使用 aria-live
区域,向屏幕阅读器用户宣布页面正在繁忙。
有关其他详细信息和注意事项,请参阅下面的 辅助功能部分。
用于 no-wrap
的绝对定位与固定定位
在使用 no-wrap
属性时,如果你想遮挡整个应用或页面,你可以通过在 <b-overlay>
上设置 fixed
属性来切换到视口固定定位。请注意,这不会禁用页面的滚动,并且请注意,页面上的任何交互元素仍将在文档选项卡序列中。
你可能还需要调整 遮罩层的 z 索引,以确保背景出现在所有其他页面元素之上。使用 z-index
属性来覆盖默认 z-index
值。
有关其他详细信息和注意事项,请参阅下面的 辅助功能部分。
遮罩层 z 索引
在某些情况下,你可能需要调整遮罩层使用的 z-index
(取决于在 DOM 中的位置或被遮挡的内容)。只需使用适合你的应用程序或用例的值设置 z-index
属性。默认 z-index
为 10
。
辅助功能
请注意,遮罩层仅是视觉上的。当遮罩层显示时,你必须禁用任何交互元素(按钮、链接等),否则仍然可以通过键盘导航访问被遮挡的元素(即仍然在文档选项卡序列中)。
如果你在被遮挡的内容中有任何链接,我们建议使用 <b-link>
组件,因为它支持 disabled
状态,而本机链接(<a href="...">
)和 <router-link>
组件不支持禁用状态。
还建议在遮罩层可见时,向你的被遮挡内容添加 aria-hidden="true"
或 aria-busy="true"
属性。但请小心不要将 aria-hidden="true"
添加到包含 <b-overlay>
组件的包装器(在使用 no-wrap
时),因为这会向屏幕阅读器用户隐藏 overlay
插槽中的任何交互内容。
如果你在 overlay
插槽中放置交互式内容,则应在发出 'shown'
事件后聚焦内容。你可以根据需要使用 hidden
事件来触发将焦点返回到元素,当 overlay 不再可见时。
当使用包装模式(未设置 prop no-wrap
)时,包装器将具有属性 aria-busy="true"
,以允许屏幕阅读器用户知道包装的内容处于繁忙或加载状态。当设置 prop no-wrap
时,将不应用该属性。
当使用 no-wrap
prop,以及可能的 fixed
prop,来隐藏整个应用程序或页面时,你必须确保所有内部页面元素(overlay 内容除外)已被禁用,并且不在文档选项卡序列中。
用例示例
这里仅列出 <b-overlay>
的一些常见用例示例。在所有情况下,我们都会禁用被遮挡区域中的任何交互式元素,以防止通过键盘导航(即 Tab 键)或屏幕阅读器访问来实现可达性。
有关其他详细信息和注意事项,请参阅 辅助功能部分。
轻松创建加载按钮
<template>
<div>
<b-overlay
:show="busy"
rounded
opacity="0.6"
spinner-small
spinner-variant="primary"
class="d-inline-block"
@hidden="onHidden"
>
<b-button
ref="button"
:disabled="busy"
variant="primary"
@click="onClick"
>
Do something
</b-button>
</b-overlay>
</div>
</template>
<script>
export default {
data() {
return {
busy: false,
timeout: null
}
},
beforeDestroy() {
this.clearTimeout()
},
methods: {
clearTimeout() {
if (this.timeout) {
clearTimeout(this.timeout)
this.timeout = null
}
},
setTimeout(callback) {
this.clearTimeout()
this.timeout = setTimeout(() => {
this.clearTimeout()
callback()
}, 5000)
},
onHidden() {
this.$refs.button.focus()
},
onClick() {
this.busy = true
this.setTimeout(() => {
this.busy = false
})
}
}
}
</script>
在此示例中,我们隐藏了输入和按钮
<template>
<div>
<b-overlay :show="busy" rounded="lg" opacity="0.6" @hidden="onHidden">
<template #overlay>
<div class="d-flex align-items-center">
<b-spinner small type="grow" variant="secondary"></b-spinner>
<b-spinner type="grow" variant="dark"></b-spinner>
<b-spinner small type="grow" variant="secondary"></b-spinner>
<span class="sr-only">Please wait...</span>
</div>
</template>
<b-input-group size="lg" :aria-hidden="busy ? 'true' : null">
<b-form-input v-model="value" :disabled="busy"></b-form-input>
<b-input-group-append>
<b-button ref="button" :disabled="busy" variant="primary" @click="onClick">
Do something
</b-button>
</b-input-group-append>
</b-input-group>
</b-overlay>
</div>
</template>
<script>
export default {
data() {
return {
value: 'Some value',
busy: false,
timeout: null
}
},
beforeDestroy() {
this.clearTimeout()
},
methods: {
clearTimeout() {
if (this.timeout) {
clearTimeout(this.timeout)
this.timeout = null
}
},
setTimeout(callback) {
this.clearTimeout()
this.timeout = setTimeout(() => {
this.clearTimeout()
callback()
}, 5000)
},
onHidden() {
this.$refs.button.focus()
},
onClick() {
this.busy = true
this.setTimeout(() => {
this.busy = false
})
}
}
}
</script>
此示例稍微复杂一些,但展示了 no-wrap
的用法,并使用 overlay
插槽向用户显示提示对话框,一旦确认,它将显示一个上传状态指示器。此示例还演示了其他辅助功能标记。
<template>
<div>
<b-form class="position-relative p-3" @submit.prevent="onSubmit">
<b-form-group label="Name" label-for="form-name" label-cols-lg="2">
<b-input-group>
<b-input-group-prepend is-text>
<b-icon icon="person-fill"></b-icon>
</b-input-group-prepend>
<b-form-input id="form-name" :disabled="busy"></b-form-input>
</b-input-group>
</b-form-group>
<b-form-group label="Email" label-for="form-mail" label-cols-lg="2">
<b-input-group>
<b-input-group-prepend is-text>
<b-icon icon="envelope-fill"></b-icon>
</b-input-group-prepend>
<b-form-input id="form-email" type="email" :disabled="busy"></b-form-input>
</b-input-group>
</b-form-group>
<b-form-group label="Image" label-for="form-image" label-cols-lg="2">
<b-input-group>
<b-input-group-prepend is-text>
<b-icon icon="image-fill"></b-icon>
</b-input-group-prepend>
<b-form-file id="form-image" :disabled="busy" accept="image/*"></b-form-file>
</b-input-group>
</b-form-group>
<div class="d-flex justify-content-center">
<b-button ref="submit" type="submit" :disabled="busy">Submit</b-button>
</div>
<b-overlay :show="busy" no-wrap @shown="onShown" @hidden="onHidden">
<template #overlay>
<div v-if="processing" class="text-center p-4 bg-primary text-light rounded">
<b-icon icon="cloud-upload" font-scale="4"></b-icon>
<div class="mb-3">Processing...</div>
<b-progress
min="1"
max="20"
:value="counter"
variant="success"
height="3px"
class="mx-n4 rounded-0"
></b-progress>
</div>
<div
v-else
ref="dialog"
tabindex="-1"
role="dialog"
aria-modal="false"
aria-labelledby="form-confirm-label"
class="text-center p-3"
>
<p><strong id="form-confirm-label">Are you sure?</strong></p>
<div class="d-flex">
<b-button variant="outline-danger" class="mr-3" @click="onCancel">
Cancel
</b-button>
<b-button variant="outline-success" @click="onOK">OK</b-button>
</div>
</div>
</template>
</b-overlay>
</b-form>
</div>
</template>
<script>
export default {
data() {
return {
busy: false,
processing: false,
counter: 1,
interval: null
}
},
beforeDestroy() {
this.clearInterval()
},
methods: {
clearInterval() {
if (this.interval) {
clearInterval(this.interval)
this.interval = null
}
},
onShown() {
this.$refs.dialog.focus()
},
onHidden() {
this.$refs.submit.focus()
},
onSubmit() {
this.processing = false
this.busy = true
},
onCancel() {
this.busy = false
},
onOK() {
this.counter = 1
this.processing = true
this.clearInterval()
this.interval = setInterval(() => {
if (this.counter < 20) {
this.counter = this.counter + 1
} else {
this.clearInterval()
this.$nextTick(() => {
this.busy = this.processing = false
})
}
}, 350)
}
}
}
</script>
在 <b-modal>
中使用
设置了模态正文 position: relative;
,因此当在模态正文中使用 <b-overlay no-wrap ...>
时,只有模态正文会被隐藏。如果你希望隐藏整个模态(包括页眉和页脚),则需要将 <b-modal>
prop body-class
设置为 position-static
,还要在 <b-overlay>
上设置 rounded
prop。