Learn Vortex's data-driven layout vocabulary and responsive behavior.

Layout Guide - Vortex

Layout in Vortex is data, not code: arrangement is authored as style attributes, resolved by the core, and interpreted by each platform's reconciler (Qt box layouts on desktop, CSS flexbox on web, native LinearLayout-style weights on Android). One vocabulary, three native implementations.

Containers

A Box arranges its children with these attributes:

Attribute Values Default
Layout.Direction Row | Column Column
Layout.Spacing gap between children, px 0
Layout.Align cross-axis placement: Start | Center | End | Stretch Center
Layout.Justify main-axis placement of the child block when nothing grows: Start | Center | End Center
Layout.Scroll Vertical | Horizontal | Both: overflow scrolls instead of clipping no scroll

Direction can vary by state: the shell's window flips to Column-Reverse in @Narrow so the titlebar sits at the bottom on phones.

Children

How a node sits inside its parent:

Attribute Meaning
Layout.Grow Main-axis flex factor; 0 (default) means don't grow.
Size.Width / Size.Height Fixed pixel size; unset means intrinsic content size.
Size.Max Width A fill-then-cap constraint: the node expands to fill the parent's cross axis up to the cap, then shrinks with the parent below it. With the parent's default Layout.Align: Center, this yields the classic centered content column that stays comfortable on wide windows and reflows on small ones.
Aspect Ratio Image/Video only: width over height (e.g. 1.7778 for 16:9). Height derives from the laid-out width, so the media keeps a proportional shape at any parent width; Size.Height is ignored while set, and Fit resolves any mismatch with the artwork's own ratio (Cover crops, Contain letterboxes). Overridable per list row via the Aspect:<field> bind.
Layout.Shrink Main-axis shrink factor for the static-web emitter (0 pins a section at content size inside a scrollable page). Runtime reconcilers size scroll regions natively and ignore it.

A titlebar is the vocabulary in one line: a Row bar whose title has Layout.Grow: 1 (pushing the controls to the far edge) over a Layout.Grow: 1 content area.

Box model

  • Margins.*: external space around a node, contributed by the parent's layout.
  • Padding.*: internal space between a node's border and its content.
  • Border/Thickness also insets content: content inset = border + padding. Border is a child layer of style data (see the styling guide), so its color is Border/Fill.
  • Corner Radii.*: per-corner rounding.

Layers name expansions keep these compact: Padding.(Bottom,Left,Right,Top): 10 sets all four sides.

Overlays

A node can leave the normal flow via the Overlay attribute:

  • Modal: lifted out and centered over a darkening backdrop (a movable frameless dialog window on desktop; a fixed centered element on web/Android). Shown and hidden through normal visibility, so open/close rides the render diff.
  • PinnedBottom: floated over the content, anchored to the bottom edge, and reserving space there. Used by the titlebar in @Narrow, where it slides away on scroll.
  • BottomSheet: like PinnedBottom but reserving no space: the node overlays content and can grow upward when expanded (collapsible drawers that peek as a header).
  • SideSheet: a detail panel floated at the right edge, full height, capped at Size.Max Width, behind a click-to-dismiss scrim; slides in and out horizontally via an @Open variant.

Motion and visibility

  • Transform.Offset Y / Transform.Offset X: render-time offsets as a fraction of the node's own size (1.0 = fully off by its own height/width), animated by the reconcilers. These drive the hide-away titlebar and sheet slides.
  • Transform.Rotation: degrees clockwise, purely visual (layout keeps the un-rotated slot); handy for reusing one icon in two orientations.
  • Opacity: fades a node without reflowing; it keeps its layout slot.
  • Visible: false: removes the node (and subtree) from the render tree entirely.
  • Collapsed: true: keeps the node in the tree but animates its height to zero and back, so collapse/expand can tween.

Responsive behavior

The core tracks the viewport and folds window states into style resolution:

  • Below 600 px the window is @Narrow; below 900 px, "medium" (app code can also branch with app.is_narrow() / app.is_medium()).
  • Scrolling content hides chrome: after a scroll threshold the @ControlsHidden state pushes pinned bars off-screen (via Transform.Offset Y), and reverse scrolling reveals them.
  • Maximized windows carry @Maximized (the shell drops its border and corner rounding there).

Mobile scaling

On phone-class platforms (the @Mobile state), desktop-tuned pixel values are generally too small, so the core auto-scales resolved values instead of requiring @Mobile overrides on every attribute:

  • Icons (icon Size.Width/Size.Height): ×1.5
  • Fonts (Font.Size): ×1.25
  • Metrics (other sizes, spacing, margins, padding, radii, border thickness): ×1.25

An explicit @Mobile value on an attribute always wins verbatim, so per-attribute exceptions still work. Unitless values (Layout.Grow, transform fractions, Font.Weight) are never scaled. The three factors are adjustable per app.

Appearance
Theme
—