# Flexbox & Layout
Utilities for controlling flex containers, direction, alignment, wrapping, and spacing.
- [Basic Usage](#basic-usage)
- [Quick Reference](#quick-reference)
- [Flex Direction](#flex-direction)
- [Reversing Direction](#reversing-direction)
- [Child Order](#child-order)
- [Wrapping](#wrapping)
- [Justify Content](#justify-content)
- [Align Items](#align-items)
- [Align Content](#align-content)
- [Align Self](#align-self)
- [Flex, Grow & Shrink](#flex-grow--shrink)
- [Gap & Spacing](#gap--spacing)
- [Responsive Design](#responsive-design)
- [Arbitrary Values](#arbitrary-values)
- [Customizing Theme](#customizing-theme)
- [Flex Children Inside a Scrollable Axis](#flex-and-overflow)
- [Related Documentation](#related-documentation)
```dart
// Basic flex row
WDiv(className: 'flex gap-4 items-center')
// Vertical column
WDiv(className: 'flex flex-col gap-2')
```
## Basic Usage
Flexbox in Wind mirrors CSS Flexbox behavior but maps to Flutter's `Row` and `Column` widgets. Use `flex` to initialize a flex container, then apply utilities to control direction, alignment, and spacing.
```dart
WDiv(
className: 'flex flex-col md:flex-row justify-between items-center gap-4 p-6 bg-white',
children: [
WText('Logo'),
WDiv(
className: 'flex gap-2',
children: [
WText('Home'),
WText('About'),
],
),
],
)
```
## Quick Reference
| Class | CSS Equivalent | Flutter Equivalent |
|:------|:---------------|:-------------------|
| `flex` | `display: flex` | `Row` / `Column` |
| `wrap` | `flex-wrap: wrap` | `Wrap` |
| `flex-row` | `flex-direction: row` | `Row()` |
| `flex-col` | `flex-direction: column` | `Column()` |
| `flex-row-reverse` | `flex-direction: row-reverse` | `Row(textDirection: mirrored)` |
| `flex-col-reverse` | `flex-direction: column-reverse` | `Column(verticalDirection: up)` |
| `order-{n}` | `order: {n}` | Stable-sort children before layout |
| `justify-{alignment}` | `justify-content: ...` | `MainAxisAlignment` |
| `items-{alignment}` | `align-items: ...` | `CrossAxisAlignment` |
| `gap-{n}` | `gap: {n}` | `SizedBox` (spacer) |
| `flex-1` | `flex: 1` | `Expanded()` |
| `shrink-0` | `flex-shrink: 0` | No wrapper — preserves intrinsic size |
## Flex Direction
Control the axis of your layout.
```dart
// Row (Horizontal) - Default for 'flex'
WDiv(className: 'flex flex-row')
// Column (Vertical)
WDiv(className: 'flex flex-col')
```
## Reversing Direction
Use `flex-row-reverse` or `flex-col-reverse` to reverse the main-axis direction. Rather than reversing the children list, Wind flips the axis itself (via `Row.textDirection` / `Column.verticalDirection`), so alignment tokens mirror correctly: `justify-start` anchors to what is now the visual end, matching CSS's `flex-direction: *-reverse`. Cross-axis alignment is unaffected.
```dart
WDiv(
className: 'flex flex-row-reverse gap-2',
children: [
WText('First in code'),
WText('Last in code'),
],
)
// Renders as: [Last in code] [First in code]
```
Responsive prefixes work as expected:
```dart
// Column on mobile, row-reverse on md+
WDiv(className: 'flex flex-col md:flex-row-reverse gap-4')
```
## Child Order
Use `order-*` on individual flex children to override their paint order without changing the source order. The parent flex container stable-sorts children by their resolved `order` value before laying them out; children without `order-*` default to `0`.
| Class | Behavior |
|:------|:---------|
| `order-0` .. `order-12` | Explicit index (integers only) |
| `order-first` | Placed before everything else (sentinel `-9999`) |
| `order-last` | Placed after everything else (sentinel `9999`) |
| `order-none` | Resets to `0` |
| `order-[n]` | Arbitrary integer (supports negative, e.g. `order-[-3]`) |
```dart
WDiv(
className: 'flex',
children: [
WDiv(className: 'order-3', child: WText('A')),
WDiv(className: 'order-1', child: WText('B')),
WDiv(className: 'order-2', child: WText('C')),
],
)
// Visual order: B, C, A
```
Responsive reordering is a common use case — swap the layout per breakpoint without duplicating children:
```dart
WDiv(
className: 'flex flex-col md:flex-row gap-4',
children: [
WDiv(className: 'order-2 md:order-1', child: WText('Sidebar')),
WDiv(className: 'order-1 md:order-2', child: WText('Main content')),
],
)
```
When combined with `flex-*-reverse`, children are sorted by `order-*` first; the container then flips the main-axis direction so `justify-*` still applies against the (now reversed) axis.
## Wrapping
Use `wrap` to create a wrapping layout (Flutter's `Wrap` widget).
> [!WARNING]
> Flutter's `Row` and `Column` do **not** wrap. You must use the `wrap` class instead of `flex` if you want wrapping behavior.
```dart
// Items wrap to the next line when they run out of space
WDiv(
className: 'wrap gap-2',
children: [
WDiv(className: 'px-2 py-1 bg-gray-200 rounded', child: WText('Tag 1')),
WDiv(className: 'px-2 py-1 bg-gray-200 rounded', child: WText('Tag 2')),
// ...
],
)
```
## Justify Content
Controls how children are distributed along the **main axis** (Horizontal for `row`, Vertical for `col`).
| Class | Flutter `MainAxisAlignment` |
|:------|:----------------------------|
| `justify-start` | `start` |
| `justify-end` | `end` |
| `justify-center` | `center` |
| `justify-between` | `spaceBetween` |
| `justify-around` | `spaceAround` |
| `justify-evenly` | `spaceEvenly` |
```dart
WDiv(
className: 'flex justify-between',
children: [
WDiv(className: 'w-10 h-10 bg-red-500'),
WDiv(className: 'w-10 h-10 bg-blue-500'),
],
)
```
## Align Items
Controls how children are distributed along the **cross axis** (Vertical for `row`, Horizontal for `col`).
| Class | Flutter `CrossAxisAlignment` |
|:------|:-----------------------------|
| `items-start` | `start` |
| `items-end` | `end` |
| `items-center` | `center` |
| `items-baseline` | `baseline` |
| `items-stretch` | `stretch` |
```dart
// Vertically center items in a row
WDiv(className: 'flex items-center h-20')
```
## Align Content
Only applicable when using `wrap`. Controls how lines of wrapped content are aligned.
| Class | Flutter `WrapAlignment` |
|:------|:------------------------|
| `align-content-start` | `start` |
| `align-content-end` | `end` |
| `align-content-center` | `center` |
| `align-content-between` | `spaceBetween` |
| `align-content-around` | `spaceAround` |
| `align-content-evenly` | `spaceEvenly` |
| `align-content-stretch` | `start` (Flutter limitation) |
## Align Self
Control alignment of an individual flex item, overriding the container's `items-*` setting.
| Class | Flutter `Alignment` |
|:------|:--------------------|
| `align-self-start` | `topCenter` |
| `align-self-end` | `bottomCenter` |
| `align-self-center` | `center` |
| `align-self-stretch` | `center` |
| `align-self-auto` | `center` |
```dart
WDiv(
className: 'flex items-start h-20',
children: [
WDiv(className: '...'),
// This item centers itself
WDiv(className: 'align-self-center ...'),
],
)
```
## Flex, Grow & Shrink
Control how individual children resize to fill available space.
| Class | Description |
|:------|:------------|
| `flex-1` | Allow child to grow and fill available space (`Expanded`). |
| `flex-grow` | Alias for `flex-1`. |
| `flex-{n}` | Specific flex factor (e.g., `flex-2`). |
| `shrink` | Allow child to shrink if needed (`FlexFit.loose`). |
| `shrink-0` | Preserve intrinsic size — no Flexible wrapper, child keeps its natural dimensions. |
| `flex-none` | Do not grow or shrink. |
```dart
WDiv(
className: 'flex',
children: [
// Sidebar: Fixed width, won't shrink
WDiv(className: 'w-16 shrink-0 bg-gray-200'),
// Content: Fills remaining space
WDiv(
className: 'flex-1 bg-white p-4',
child: WText('Main Content'),
),
],
)
```
## Gap & Spacing
Wind's `gap` utilities add space between flex or grid items without using margin on the children themselves.
| Class | Value (Default) | Description |
|:------|:----------------|:------------|
| `gap-0` | 0px | No gap |
| `gap-1` | 4px | Small gap |
| `gap-2` | 8px | Medium gap |
| `gap-4` | 16px | Large gap |
| `gap-x-{n}` | - | Horizontal gap only |
| `gap-y-{n}` | - | Vertical gap only |
> [!NOTE]
> `space-x-{n}` and `space-y-{n}` are supported as aliases for `gap`, but `gap` is preferred for consistency with Grid.
```dart
// 16px gap horizontally and vertically
WDiv(className: 'flex gap-4')
// 8px horizontal, 16px vertical
WDiv(className: 'flex flex-col gap-x-2 gap-y-4')
```
## Responsive Design
Change layout direction or spacing based on screen size. This is extremely powerful for mobile-first designs.
```dart
// Column on mobile, Row on tablet+
WDiv(className: 'flex flex-col md:flex-row gap-4 md:gap-8')
```
## Arbitrary Values
Need a specific gap or flex value not in the theme? Use bracket notation.
```dart
// Specific 23px gap
WDiv(className: 'flex gap-[23px]')
// Specific pixel gap
WDiv(className: 'flex gap-[1.5rem]')
```
## Customizing Theme
To change the default spacing scale used by `gap`, modify `baseSpacingUnit` or the `containers` map in `WindThemeData`.
```dart
WindThemeData(
baseSpacingUnit: 8.0, // Now gap-1 = 8px, gap-2 = 16px
)
```
## Flex Children Inside a Scrollable Axis
When a flex container's own main axis is scrollable (`flex-row` with `overflow-x-auto|scroll`, or `flex-col` with `overflow-y-auto|scroll`), Flutter's `Expanded`/`Flexible` cannot resolve — the incoming constraint is unbounded. Wind detects this at resolution time and skips the `Expanded`/`Flexible` wrap for direct flex children in that pass, so `flex-N` becomes a no-op while the axis is scrollable.
This enables the common responsive pattern of "scroll on narrow, distribute on wide":
```dart
WDiv(
className: 'flex flex-row gap-1 overflow-x-auto sm:overflow-visible',
children: [
for (final tab in tabs)
WDiv(className: 'flex-1', child: _tabBtn(tab)),
],
)
```
At `base` the row scrolls horizontally and children keep their intrinsic width. At `sm+` the overflow is removed and `flex-1` distributes width equally. Nested non-scrolling flex subtrees under a scrolling ancestor behave normally.
## Related Documentation
- [Grid Layout](./grid.md)
- [Display Modes](./display.md)
- [Sizing](../sizing/width.md)