Vize

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.