Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

isStandalone

Determines if the app is running in standalone (PWA) mode. Works for modern browsers with navigator.standalone (iOS Safari) or display-mode: standalone via matchMedia.

TypeScript
Copied!
1/**
2 * Determines if the app is running in standalone (PWA) mode.
3 *
4 * Works for modern browsers with 'navigator.standalone' (iOS Safari)
5 * or 'display-mode: standalone' via matchMedia.
6 *
7 * @returns True if app is in standalone mode.
8 */
9export function isStandalone(): boolean {
10  if (typeof window === 'undefined') return false;
11  return (
12    (window.matchMedia?.('(display-mode: standalone)').matches) ||
13    (navigator as any).standalone === true
14  );
15}
  • Cross-Platform PWA Support

    Covers both modern standards (display-mode: standalone) and legacy iOS Safari (navigator.standalone), ensuring broader compatibility.

  • Non-Intrusive Detection

    Uses passive checks without requiring explicit permissions or impacting runtime behavior.

  • Environment-Safe Guarding

    Validates window availability to avoid runtime errors in SSR or Node environments.

  • Minimal Overhead

    Lightweight and efficient — uses built-in browser capabilities with no DOM or network interaction.

Tests | Examples

TypeScript
Copied!
1const originalMatchMedia = window.matchMedia;
2const originalNavigator = navigator;
3
4afterEach(() => {
5  window.matchMedia = originalMatchMedia;
6  // @ts-ignore
7  global.navigator = originalNavigator;
8});
9
10test('returns true if matchMedia detects standalone mode', () => {
11  window.matchMedia = jest.fn().mockImplementation(query => ({
12    matches: query === '(display-mode: standalone)',
13    media: query,
14    onchange: null,
15    addListener: jest.fn(),
16    removeListener: jest.fn(),
17    addEventListener: jest.fn(),
18    removeEventListener: jest.fn(),
19    dispatchEvent: jest.fn(),
20  }));
21  expect(isStandalone()).toBe(true);
22});
23
24test('returns true if navigator.standalone is true (iOS)', () => {
25  // @ts-ignore
26  global.navigator = { standalone: true };
27  window.matchMedia = jest.fn().mockReturnValue({ matches: false });
28  expect(isStandalone()).toBe(true);
29});
30
31test('returns false if neither matchMedia nor standalone apply', () => {
32  // @ts-ignore
33  global.navigator = { standalone: false };
34  window.matchMedia = jest.fn().mockReturnValue({ matches: false });
35  expect(isStandalone()).toBe(false);
36});

Common Use Cases

  • Conditional UI Adjustments for PWAs

    Hide navigation bars or add gestures tailored to full-screen environments.

  • Analytics for Install Mode Usage

    Track how many users are running your app as a standalone PWA versus in a browser tab.

  • Feature Restrictions or Enhancements

    Enable or disable certain features depending on whether the app is installed.

  • Prompting Reinstallation or Update

    Show installation banners or update messages only when the app is not in standalone mode.

Codebase: Utilities -> Platforms -> isStandalone | Yevhen Klymentiev