# 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)