---
title: Row
description: Horizontal flex container
visibility: guest
draft: false
---

# Row

A horizontal flex layout that places children side by side with consistent spacing. The horizontal counterpart to [Stack](/components/stack).

## Basic Usage

:::preview{title="Default row"}
<x-wirekit::row>
    <x-wirekit::card><x-wirekit::card.body>First</x-wirekit::card.body></x-wirekit::card>
    <x-wirekit::card><x-wirekit::card.body>Second</x-wirekit::card.body></x-wirekit::card>
    <x-wirekit::card><x-wirekit::card.body>Third</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::row>
:::

## Gap Sizes

:::preview{title="Small gap"}
<x-wirekit::row gap="sm">
    <x-wirekit::card><x-wirekit::card.body>One</x-wirekit::card.body></x-wirekit::card>
    <x-wirekit::card><x-wirekit::card.body>Two</x-wirekit::card.body></x-wirekit::card>
    <x-wirekit::card><x-wirekit::card.body>Three</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::row>
:::

:::preview{title="Large gap"}
<x-wirekit::row gap="lg">
    <x-wirekit::card><x-wirekit::card.body>First</x-wirekit::card.body></x-wirekit::card>
    <x-wirekit::card><x-wirekit::card.body>Second</x-wirekit::card.body></x-wirekit::card>
</x-wirekit::row>
:::

## Justify Between

A common pattern for headers and toolbars: items at each end.

:::preview{title="Space between"}
<x-wirekit::row justify="between">
    <x-wirekit::button intent="neutral">Back</x-wirekit::button>
    <x-wirekit::button intent="primary">Continue</x-wirekit::button>
</x-wirekit::row>
:::

## Alignment

:::preview{title="Baseline alignment"}
<x-wirekit::row align="baseline" gap="md">
    <x-wirekit::badge size="lg">Large</x-wirekit::badge>
    <x-wirekit::badge size="sm">Small</x-wirekit::badge>
</x-wirekit::row>
:::

## A row of form controls

A row of fields does not line up on any single edge. A labeled field is taller than an
unlabeled one, and a field with a hint is taller still — so `align="center"` leaves the
controls apart, and `align="end"` fixes that until one field carries a hint.

`align-fields` makes the row three shared tracks — labels, controls, messages — and every
field hands its parts to them. A control sits on the control track whatever its neighbors
carry, and a submit button beside them stretches to match.

:::preview{title="Controls on one line, with only one label between them"}
<x-wirekit::row gap="sm" align-fields>
    <x-wirekit::field name="share-email">
        <x-wirekit::input name="share-email" placeholder="Share list..." aria-label="Email address to share with" />
    </x-wirekit::field>
    <x-wirekit::field label="Role" name="share-role">
        <x-wirekit::select name="share-role" :options="['guest' => 'Guest', 'editor' => 'Editor']" />
    </x-wirekit::field>
    <x-wirekit::button>Share</x-wirekit::button>
</x-wirekit::row>
:::

It is opt-in because it changes the row's display model, and `align` / `justify` stop applying
once it is on — the row is a grid rather than a flex line at that point.

**Below 48rem the row stacks**, and that is the point rather than a limitation: three controls
side by side on a phone are three sixty-pixel columns, which is not a narrower control but an
unusable one. The shared tracks come back with the room to hold them, and nothing about the
markup changes — the same row is a column on a phone and a line on a desktop.

::: info Older browsers keep the fields usable
The shared tracks use CSS `subgrid`, which is newer than WireKit's support baseline. Where it
is missing, the row still renders every field and every control; they simply line up the way
they do without this prop. Nothing depends on it.
:::

## Wrapping

Enable wrapping for rows that may overflow.

:::preview{title="Wrapping row"}
<x-wirekit::row :wrap="true" gap="sm">
    <x-wirekit::badge intent="primary">Tag 1</x-wirekit::badge>
    <x-wirekit::badge intent="success">Tag 2</x-wirekit::badge>
    <x-wirekit::badge intent="warning">Tag 3</x-wirekit::badge>
    <x-wirekit::badge intent="danger">Tag 4</x-wirekit::badge>
    <x-wirekit::badge intent="info">Tag 5</x-wirekit::badge>
    <x-wirekit::badge intent="neutral">Tag 6</x-wirekit::badge>
</x-wirekit::row>
:::

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `gap` | string | `'md'` | Spacing: `none`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl` |
| `align` | string | `'center'` | Cross-axis: `start`, `center`, `end`, `stretch`, `baseline` |
| `alignFields` | bool | `false` | Line the row's form controls up on one line — see below |
| `justify` | string | `'start'` | Main-axis: `start`, `center`, `end`, `between`, `around`, `evenly` |
| `wrap` | bool | `false` | Allow wrapping |
| `as` | string | `'div'` | HTML element to render |
| `scope` | string\|null | `null` | Scoped personalization name |

## Keyboard Interaction

This component is a layout wrapper. Keyboard interaction is delegated to its children.

## Design Tokens

Same spacing tokens as [Stack](/components/stack):

| Token | Default | Description |
| --- | --- | --- |
| `--space-wk-xs` | `0.25rem` | Extra small gap |
| `--space-wk-sm` | `0.5rem` | Small gap |
| `--space-wk-md` | `1rem` | Medium gap |
| `--space-wk-lg` | `1.5rem` | Large gap |
| `--space-wk-xl` | `2.5rem` | Extra large gap |
| `--space-wk-2xl` | `4rem` | Double extra large gap |

**The rung names are shared with a second ladder, and the values are not.** This prop reads `--space-wk-*`; the tighter `--gap-wk-*` ladder uses the same `xs`…`2xl` labels with different values from `md` up, and WireKit's own components read it for spacing inside a component. Swapping one for the other by name silently re-spaces the container — see [Two spacing ladders, same rung names](/theming/design-tokens#two-spacing-ladders-same-rung-names).
