Mask — Overlay
17:06Description
A full-screen fixed mask used to emphasize a specific element and block interaction with the content beneath. The node stays mounted and its visibility is toggled through visibility + opacity class channels; on close a visible window is kept until the fade-out (and content scaling) finishes. The component has no built-in close logic — the page controls show.
Compatibility
| Platform | Support |
|---|---|
| App | ✅ Supported (on HarmonyOS duration has no effect and the stylesheet base value of 300ms is used) |
| H5 | ✅ Supported |
| WeChat Mini Program | ✅ Supported |
Examples
Basic Usage
Tap the button to show the mask; tap the mask area to close it.
View source
<template>
<ux-button type="primary" @click="showMask">显示遮罩</ux-button>
<ux-mask :show="show" :zoom="zoom" @click="closeMask"></ux-mask>
</template>
<script setup lang="uts">
const show = ref<boolean>(false);
const zoom = ref<boolean>(true);
function showMask(): void {
show.value = true;
}
function closeMask(): void {
show.value = false;
}
</script>Zoom Effect (zoom)
When zoom=true the content animates with a scale (0.8 → 1 on open, back to 0.8 on close; the mask background does not scale); when zoom=false there is no zoom.
View source
<template>
<view class="btn-wrap">
<ux-button :type="zoom ? 'primary' : 'default'" custom-class="btn-item" @click="setZoom(true)">开启缩放</ux-button>
<ux-button :type="!zoom ? 'primary' : 'default'" custom-class="btn-item" @click="setZoom(false)">关闭缩放</ux-button>
</view>
<ux-mask :show="show" :zoom="zoom" @click="closeMask"></ux-mask>
</template>
<script setup lang="uts">
const show = ref<boolean>(false);
const zoom = ref<boolean>(true);
function setZoom(val: boolean): void {
zoom.value = val;
show.value = true;
}
function closeMask(): void {
show.value = false;
}
</script>
<style scoped>
.btn-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
.btn-item {
margin-right: 12px;
margin-bottom: 12px;
}
</style>Content Slot
Fill custom content inside the mask via the default slot; tapping the content will not close the mask.
View source
<template>
<ux-button type="primary" @click="showContent">显示内容</ux-button>
<ux-mask :show="show" @click="closeMask">
<view class="wrap">
<view class="rect">
<text class="rect-text">自定义内容</text>
</view>
</view>
</ux-mask>
</template>
<script setup lang="uts">
const show = ref<boolean>(false);
function showContent(): void {
show.value = true;
}
function closeMask(): void {
show.value = false;
}
</script>
<style scoped>
.wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.rect {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 240px;
height: 240px;
background-color: #ffffff;
border-radius: 8px;
}
.rect-text {
font-size: 14px;
color: #606266;
}
</style>Animation Duration (duration)
Set the show/hide animation duration of the mask in milliseconds via duration.
View source
<template>
<view class="btn-wrap">
<ux-button v-for="(item, index) in durationList" :key="index" :type="duration == item.value ? 'primary' : 'default'" custom-class="btn-item" @click="setDuration(item.value)">{{ item.label }}</ux-button>
</view>
<ux-mask :show="show" :duration="duration" @click="closeMask"></ux-mask>
</template>
<script setup lang="uts">
const show = ref<boolean>(false);
const duration = ref<number>(300);
const durationList = [
{ value: 100, label: '100ms' },
{ value: 300, label: '300ms' },
{ value: 800, label: '800ms' }
];
function setDuration(val: number): void {
duration.value = val;
show.value = true;
}
function closeMask(): void {
show.value = false;
}
</script>
<style scoped>
.btn-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
.btn-item {
margin-right: 12px;
margin-bottom: 12px;
}
</style>Not Clickable to Close (mask-click-able)
When mask-click-able=false, tapping the mask will not close it; close it via the button inside the content instead.
View source
<template>
<ux-button type="primary" @click="showNotClickable">显示遮罩</ux-button>
<ux-mask :show="show" :mask-click-able="false" @click="closeMask">
<view class="wrap">
<view class="rect" @click.stop>
<text class="rect-text">点击遮罩无法关闭</text>
<ux-button size="small" type="primary" @click="closeMask">关闭</ux-button>
</view>
</view>
</ux-mask>
</template>
<script setup lang="uts">
const show = ref<boolean>(false);
function showNotClickable(): void {
show.value = true;
}
function closeMask(): void {
show.value = false;
}
</script>
<style scoped>
.wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.rect {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 240px;
height: 240px;
background-color: #ffffff;
border-radius: 8px;
}
.rect-text {
font-size: 14px;
color: #606266;
margin-bottom: 16px;
}
</style>API
Props
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
customStyle | Custom root element style | string | UTSJSONObject | - | - |
customClass | Custom root element style class | string | '' | - |
show | Whether to show the mask | boolean | false | - |
zIndex | z-index level | string | number | '' | - |
zoom | Whether to scale the content layer with scale (the mask background does not scale) | boolean | true | - |
duration | Transition duration of the mask, in ms | string | number | 300 | - |
maskClickAble | Whether the mask can be tapped to close | boolean | true | - |
Events
| Event | Description | Params | Version |
|---|---|---|---|
click | Emitted when the mask is tapped while maskClickAble is true | - | - |
Slots
| Slot | Description | Version |
|---|---|---|
default | Mask content, filling the whole mask; add @click.stop on the content box to keep taps from firing the mask's click | - |
Notes
- The component has no built-in close logic: setting
showtofalseonly plays the fade-out/scale-out transition, so the page must maintain the visible state;@clickmerely emits an event and never writes back toshow. - With
mask-click-able=false, tapping the mask emits noclickevent at all (not merely "does not close"), so you must close it from a button inside the content — which is exactly what the demo does. zoomonly affects the content layer; the mask background never scales. On close the content goes fromscale(1)back toscale(0.8).- The mask is
position: fixedand stopstouchmoveinternally, so the page beneath does not scroll while it is visible. - The mask node stays mounted: after closing, a primary plus a fallback timer retract the visible window once the transition finishes, and rapid re-toggles clear the stale timers.
- An empty
z-indexfalls back to the global mask level ($u.zIndex.mask); use it to control stacking order when several masks coexist. durationhas no effect on HarmonyOS: the inline assignment is excluded by#ifndef APP-HARMONY, so the stylesheet base value of 300ms is always used.