Safe area

Keep content clear of the notch, the status bar and the home indicator. Lynx reads the same env(safe-area-inset-*) values that iOS Safari does.

The safe area is the part of the screen that hardware and system bars don't cover. On a recent iPhone, the notch or Dynamic Island covers the top edge, and the home indicator (the bar you swipe up) covers the bottom. On the web, a page with viewport-fit=cover pads itself with env(safe-area-inset-top) and its siblings. Lynx supports the same four values.

Pad with env()

.screen {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

.tab-bar {
  /* a 56px bar, plus room for the home indicator */
  height: calc(56px + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
}
  • There are four values: safe-area-inset-top, safe-area-inset-right, safe-area-inset-bottom and safe-area-inset-left.
  • They work inside calc(), as in .tab-bar above.
  • Where no inset is known, the value is 0. The padding collapses instead of breaking the layout.

Where the insets come from

Where the app runsWhat env() gives
iPhone, in Lynx Explorer or any appThe window's insets, wherever your page sits on screen
Android0 on every side: Lynx doesn't read insets on Android
Web preview0

Apps you build with ng build --platform ios or --platform android already keep the whole page inside the safe area. The native app places it below the status bar and above the home indicator, so you don't need inset padding there. If you add it anyway, check the result on a device.

Tailwind utilities

The Tailwind plugin that comes with the UI components, blotchPlugin, adds padding utilities built on env(). npx @blotch/dolan init copies it into your project.

<!-- padding equal to the inset -->
<view class="pb-safe">...</view>

<!-- 1rem of padding plus the inset: calc(1rem + env(safe-area-inset-bottom)) -->
<view class="pb-safe-4">...</view>
ClassPadding
pt-safe pr-safe pb-safe pl-safeThe inset on one side
px-safe py-safeThe insets on two opposite sides
p-safeThe insets on all four sides
pt-safe-<n> pb-safe-<n> and so onA spacing value plus the inset

The <n> takes any value from your spacing scale, as p-<n> does: pb-safe-8, pt-safe-2.

Check for a notch in TypeScript

Prefer CSS: env() adapts to every device without code. For logic CSS can't express, inject LynxSafeArea.

Known issue

On iOS and Android, inject(LynxSafeArea) currently throws on the main thread. It reads Lynx's SystemInfo object, which the main thread doesn't have. Until that's fixed, use the CSS approach on devices.

src/app/header.ts
import { Component, inject } from '@angular/core';
import { LYNX_ELEMENTS, LynxSafeArea } from '@blotch/angular-lynx';

@Component({
  selector: 'app-header',
  imports: [LYNX_ELEMENTS],
  template: `
    <view
      class="app-header"
      [class.app-header-notch]="safeArea.isNotchScreen()"
    >
      <text>Inbox</text>
    </view>
  `,
  styles: `
    .app-header {
      padding: 12px 16px;
    }
    .app-header-notch {
      padding-top: calc(12px + env(safe-area-inset-top));
    }
  `,
})
export class Header {
  protected readonly safeArea = inject(LynxSafeArea);
}
  • isNotchScreen() is a signal that's true when the device has a notch or camera cutout. It comes from the host app (the native app that runs your bundle): Lynx Explorer passes it, and the apps that ng build --platform makes don't, so there it's always false.
  • platform is the operating system. On phones it's 'iOS', 'Android' or 'Harmony', which is Huawei's HarmonyOS.
  • SAFE_AREA_INSET_TOP, SAFE_AREA_INSET_RIGHT, SAFE_AREA_INSET_BOTTOM and SAFE_AREA_INSET_LEFT are the env() strings, such as 'env(safe-area-inset-top)', for building styles in TypeScript.