search ESC

Searching…

No results for "".

Type at least 2 characters to search.

Docs
You are viewing an older version (1.0.0). Go to the latest.

Flexbox & Layout

Utilities for controlling flex containers, direction, alignment, wrapping, and spacing.

// 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.

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.

// 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.

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:

// 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])
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:

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.

// 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
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
// Vertically center items in a row
WDiv(className: 'flex items-center h-20')

Column default: smart cross-axis stretch. A flex flex-col with no explicit items-* token stretches each WDiv, WAnchor (any child), and WButton child that does not control its own width to the column width, matching CSS align-items: stretch. For WAnchor: when the anchor wraps a WDiv, the inner WDiv's className decides (so WAnchor > WDiv(w-32) keeps 128 px; a WAnchor > WDiv with a self-flex token is excluded just as a direct self-flexing WDiv is); when the anchor wraps a WText or raw widget, the anchor stretches by policy so its tap surface fills the column. Left untouched: children with an explicit width (w-* / min-w-* / max-w-* / w-full, in any state/breakpoint variant), children that self-wrap in Expanded/Flexible (grow, flex-grow, flex-auto, flex-initial, shrink, flex-shrink, flex-N), absolute children, bare WText leaves, and raw Flutter widgets. shrink-0 / flex-none children still stretch on the cross axis (flex-shrink is main-axis only, matching CSS). Add any items-* token (e.g. items-start) to turn this off and let children size to content. Rows are never auto-stretched on the cross axis. When the column itself sits in an unbounded-width context (a bare Row slot, UnconstrainedBox, horizontal scroll), the stretch safely falls back to content-sized children instead of forcing an infinite width.

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

Tailwind's shorthand self-start / self-end / self-center / self-stretch / self-auto is accepted as an alias for the matching align-self-* class, so either form works.

WDiv(
  className: 'flex items-start h-20',
  children: [
    WDiv(className: '...'),
    // This item centers itself (self-center is shorthand for align-self-center)
    WDiv(className: '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 / grow Alias for flex-1 (Tailwind v3 and v4 names).
grow-0 Do not grow — child keeps its intrinsic main-axis size.
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 CSS flex: 0 0 auto: do not grow AND do not shrink. Keeps intrinsic size (same no-shrink path as shrink-0).
basis-1/2 / basis-1/3 / basis-1/4 / basis-full Fractional flex-basis: initial main-axis size (width in a row, height in a column). Approximates CSS flex-basis; ignores grow/shrink interplay.
basis-[Npx] Fixed flex-basis: a fixed main-axis size in logical pixels (e.g., basis-[120px]).

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.

// 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.

// 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.

// 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.

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":

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.