Safe Area
Region exposing env(safe-area-inset-*) as CSS variables, data attributes, and optional padding.
| Package | @vizejs/ui/safe-area |
| Maturity | stable |
| Own the source | vize lib pull safe-area |
| Requires | — |
| Aliases | safe area, notch insets, env safe-area-inset, home indicator padding |
| Covers | CSS env(safe-area-inset-*), Ionic safe area, react-native-safe-area-context |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { SafeArea } from "@vizejs/ui/safe-area";
Or copy the source into your project with vize lib pull safe-area (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Footer toolbar padded past the device home indicator using the bottom safe-area inset. -->
<script setup lang="ts">
import { SafeArea } from "@vizejs/ui/safe-area";
import type { SafeAreaEdge } from "@vizejs/ui/safe-area";
const edges: readonly SafeAreaEdge[] = ["bottom", "left", "right"];
</script>
<template>
<SafeArea v-slot="{ insets }" as="footer" :edges apply="padding">
<button type="button">Reply</button>
<button type="button">Forward</button>
<small>Bottom inset: {{ insets.bottom }}px</small>
</SafeArea>
</template>
API
SafeArea
Source: src/families/layout/safe-area/safe-area.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as |
PrimitiveAs |
"div" |
Element or component to render. |
edges |
readonly SafeAreaEdge[] |
["top", "right", "bottom", "left"] |
Edges this region respects (published as data-edges and applied by apply). |
apply |
"margin" | "none" | "padding" |
"none" |
Apply the selected insets as inline padding or margin; "none" only exposes CSS variables. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
{ readonly insets: SafeAreaEdgeInsets } |
Region contents with the measured insets (zero on the server and before hydration). |
Behavior
Normative state x input -> outcome table for safe-area.vue and
useSafeAreaInsets (@vizejs/ui/safe-area). Every row is proven by the named
test in safe-area.test.ts or safe-area-ssr.test.ts; compile-only assertions
live in safe-area.types.test-d.ts.
| # | State | Input | Outcome | Proven by |
|---|---|---|---|---|
| SA1 | any | render | --vize-safe-area-inset-* map to env(safe-area-inset-*, 0px); data-edges lists edges; apply pads/margins only those edges |
exposes env() insets as CSS variables and applies only the selected edges |
| SA2 | mounted | microtask / resize | a hidden probe measures insets after hydration; non-zero edges appear in data-insets and the slot; unmount removes the probe |
measures insets after a microtask, publishes non-zero edges, and re-measures on resize |
| SA3 | composable | scope / no document | useSafeAreaInsets runs in any effect scope, stops with it, and stays at zero without a document |
useSafeAreaInsets works in any scope and is inert without a document |
| SA4 | slot | render | the default slot renders contents with typed insets | renders slot content with typed insets |
| SA5 | SSR / hydration | isolated requests | byte-identical markup with CSS variables and no measured data; hydration without diagnostics | renders byte-identical safe-area markup and hydrates without mismatches |
Non-zero insets require <meta name="viewport" content="viewport-fit=cover">.
The subpath is tree-shakable and ships no CSS.