Download

The app shell

The shell is the frame every Adom app shares: a header at the top, content that fills the rest, and an optional footer. Get the shell right and everything inside it sizes correctly; get it wrong and the page scrolls as a whole, a canvas refuses to fill its pane, or a panel overflows the screen.

The full-height column

.app                 position: fixed; inset: 0; display: flex; flex-direction: column;
  .app-header        height: 44px; flex: 0 0 auto;        (see adom-app-header)
  .app-body          flex: 1 1 auto; min-height: 0; overflow: auto / a grid of panes
  .app-footer        flex: 0 0 auto;  (optional status bar)
.app    { position: fixed; inset: 0; display: flex; flex-direction: column;
          background: #0d1117; color: #e6edf3; }
.app-header { flex: 0 0 44px; }
.app-body   { flex: 1 1 auto; min-height: 0; }   /* min-height:0 is load-bearing */
.app-footer { flex: 0 0 auto; }

The intrinsic-sizing traps (these cause most layout bugs)

  • min-height: 0 on the flex body. Without it a flex child refuses to shrink below its content, so a tall child makes the whole app overflow and the page scrolls. This single line fixes the most common "the whole page scrolls instead of the panel" bug.
  • minmax(0, 1fr) in grids. A grid track defaults to min-content, which will not shrink. Use minmax(0, 1fr) so a pane (especially one holding a canvas) can actually size down.
  • position: fixed on .app, anchored to inset: 0, so the shell is exactly the viewport and nothing relies on document flow. For a canvas, sync its pixel size to the pane's client size on resize, do not assume CSS size equals backing-store size.

The body: fluid panes and splits

  • A single scroll region uses overflow: auto on .app-body.
  • A multi-pane layout uses CSS grid with minmax(0, 1fr) tracks and a draggable splitter. Keep split ratios between 0.1 and 0.9 and persist them.
  • The body reshapes responsively: side-by-side panes on desktop become a single column or tabs on a phone (see responsive-ui).

A footer is optional. When present it is a thin status bar, not a second toolbar:

  • One row, muted, for ambient state: connection status, current mode, counts, a save indicator, the zoom level. Monospace for numeric/data readouts (see the type rules in adom-ui-design).
  • It does not hold primary actions (those live in the header's actions zone or a bottom bar on mobile). It must never grow or wrap.
  • flex: 0 0 auto, at --z-toolbar: 80.

Where overlays mount

  • HUDs (floating-windows) float over .app-body at --z-hud: 50.
  • Toasts (toasts) mount at the bottom center at --z-toast: 400.
  • The global tooltip div (tooltips) is appended to <body>, outside the shell, at 99999.

adom-app-header (the header), responsive-ui (how the shell reshapes), floating-windows, toasts, tooltips, and adom-ui-design (the hub).