Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Accessibility
Vuetify

Scrim

A headless backdrop component that integrates with the stack system to provide a shared overlay for all active modals and dialogs.


RenderlessIntermediateFeb 3, 2026

Installation

The Scrim component uses the global stack context. For SSR applications, install the stack plugin:

main.ts
import { createApp } from 'vue'
import { createStackPlugin } from '@vuetify/v0'
import App from './App.vue'

const app = createApp(App)

app.use(createStackPlugin())

app.mount('#app')
Tip

For client-side only apps, you can skip plugin installation. The Scrim will use the default stack singleton automatically.

Usage

The Scrim component renders a backdrop that appears when any overlay is active. It automatically positions itself below the topmost overlay using z-index management from the stack context.

vue
<script setup lang="ts">
  import { Scrim } from '@vuetify/v0'
</script>

<template>
  <Scrim class="fixed inset-0 bg-black/50" />
</template>

Anatomy

Anatomy
<script setup lang="ts">
  import { Scrim } from '@vuetify/v0'
</script>

<template>
  <!-- Teleports to body by default -->
  <Scrim class="fixed inset-0 bg-black/50 transition-opacity" />
</template>

Custom Styling via Slot Props

Access the stack state through slot props for custom rendering:

vue
<script setup lang="ts">
  import { Scrim } from '@vuetify/v0'
</script>

<template>
  <Scrim
    v-slot="{ isActive, isBlocking, zIndex, dismiss }"
    :teleport="false"
    class="fixed inset-0"
  >
    <div
      class="size-full bg-black/50"
      :class="{ 'cursor-not-allowed': isBlocking }"
      @click="dismiss"
    >
      Active: {{ isActive }}, Z-Index: {{ zIndex }}
    </div>
  </Scrim>
</template>

Blocking Mode

When the topmost overlay has blocking: true, the scrim will not dismiss on click. The isBlocking slot prop reflects this state:

vue
<template>
  <Scrim v-slot="{ isBlocking }" class="fixed inset-0">
    <div :class="isBlocking ? 'bg-black/70' : 'bg-black/50'" />
  </Scrim>
</template>

Inline Rendering

By default, Scrim teleports to body. Disable teleport for inline rendering:

vue
<template>
  <div class="relative">
    <Scrim :teleport="false" class="absolute inset-0 bg-black/50" />
    <!-- Content -->
  </div>
</template>

Custom Stack Context

For isolated overlay systems, create a custom stack and provide it via Vue’s injection system:

vue
<script setup lang="ts">
  import { provide } from 'vue'
  import { createStack, Scrim } from '@vuetify/v0'

  // Create isolated stack (doesn't interfere with global stack)
  const stack = createStack()
  provide('v0:stack', stack)
</script>

<template>
  <Scrim class="fixed inset-0 bg-black/50" />
</template>

Transitions

The default transition is fade. Customize with the transition prop:

vue
<template>
  <Scrim transition="slide-fade" class="fixed inset-0 bg-black/50" />
</template>

<style>
  .slide-fade-enter-active,
  .slide-fade-leave-active {
    transition: opacity 0.3s ease;
  }

  .slide-fade-enter-from,
  .slide-fade-leave-to {
    opacity: 0;
  }
</style>

API Reference

The following API details are for all variations of the Scrim component.

Scrim

Props

transition

string

Transition name for enter/leave animations

Default: "fade"

teleport

boolean

Whether to teleport the scrim to the body element

Default: true

teleportTo

string | HTMLElement

Target selector or element for teleport

Default: "body"

Slots

default

ScrimSlotProps
Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/