Concepts

Responsive Design

Container-aware layouts and predictable server rendering.

Stacks and grids use CSS layout. Give containers room to shrink, wrap long text, and avoid fixed widths larger than the available space.

Adaptive split navigation

NavigationSplitView observes its own container. Two columns collapse below 768px; three collapse below 1024px. Compact navigation lets users reach every column. Set defaultCompactColumn to choose the initial screen, or control compactColumn and onCompactColumnChange with React state. Set compact explicitly to override automatic adaptation.

<NavigationSplitView
  defaultCompactColumn="content"
  sidebar={<Navigation />}
  content={<Settings />}
  detail={<Preview />}
/>

ViewThatFits also observes its container, but requires data-min-width hints. Order variants from spacious to compact. Explicit width overrides observation; intrinsic content measurement is not implemented.

Viewport hooks

useViewport, useSizeClass, useHorizontalSizeClass and useVerticalSizeClass share one resize subscription, removed when the last subscriber unmounts. A viewport narrower than 768px is horizontally compact; below 667px high it is vertically compact. These are web breakpoints, not Apple's device classification rules.

All four hooks return null on the server and during initial hydration. Prefer CSS for visual adaptation; when rendering depends on a hook, provide a stable fallback for null.

Use an axis hook when you only need a breakpoint. It updates when that axis crosses the breakpoint; useSizeClass and useViewport also update their pixel dimensions during resizing.

import { useHorizontalSizeClass } from '@swiftuijs/ui/contexts/size-class';

function AdaptiveContent() {
  const horizontal = useHorizontalSizeClass();
  if (horizontal === null) return <LoadingLayout />;
  return horizontal === 'compact' ? <CompactLayout /> : <WideLayout />;
}

Check your composition

Sheet fills the width and attaches to the bottom below 768px, including wider touch screens under 500px high (phone landscape). Other wide viewports center page and form sheets with width caps of 600px and 420px. fullScreen always fills the viewport. Alert, confirmation dialog and menu content scrolls when the viewport is short.

For edge-to-edge mobile pages, set viewport-fit=cover in the viewport meta tag so browsers expose env(safe-area-inset-*). Sheet content and confirmation dialogs account for those insets. Embedded hosts can supply --safe-area-top, --safe-area-right, --safe-area-bottom, and --safe-area-left instead. These are Web presentation rules; native SwiftUI adapts by platform, OS version and size class.

Test narrow phones, tablets and desktop containers, including long labels, enlarged text, keyboard navigation and dark mode. Container width can be much smaller than viewport width when a component appears in a sidebar or dialog.