Positioning
Utilities for controlling how elements are positioned in the layout using relative and absolute placement.
- Position Types
- Offset Utilities
- Inset Shortcuts
- Negative Offsets
- Arbitrary Values
- Common Patterns
- Combining with Flex
- Future Work
- Related Documentation
// Badge overlay — red dot on an avatar
WDiv(
className: 'relative',
children: [
WDiv(className: 'w-12 h-12 rounded-full bg-gray-300'),
WDiv(className: 'absolute top-0 right-0 w-3 h-3 rounded-full bg-red-500'),
],
)
Position Types
Wind maps CSS position values to Flutter's Stack widget. A relative parent establishes a stacking context; absolute children are placed inside it using offset utilities.
| Wind className | CSS Equivalent | Flutter Widget |
|---|---|---|
relative |
position: relative |
Stack (parent) |
absolute |
position: absolute |
Positioned (child inside Stack) |
[!NOTE] An
absolutechild must live inside arelativeparent. Wind will wrap therelativecontainer in aStackand eachabsolutechild in aPositionedwidget automatically.
WDiv(
className: 'relative w-32 h-32 bg-gray-100',
children: [
WDiv(className: 'absolute top-2 left-2 w-8 h-8 bg-blue-500'),
],
)
Offset Utilities
Control the position of absolute children using directional offset classes. Values follow the spacing scale (spacing * n).
| Class | CSS Equivalent | Description |
|---|---|---|
top-{n} |
top: {n} |
Distance from the top edge |
right-{n} |
right: {n} |
Distance from the right edge |
bottom-{n} |
bottom: {n} |
Distance from the bottom edge |
left-{n} |
left: {n} |
Distance from the left edge |
Default spacing scale (base unit = 4px):
| Class | Value |
|---|---|
top-0 |
0px |
top-1 |
4px |
top-2 |
8px |
top-4 |
16px |
top-6 |
24px |
top-8 |
32px |
The same scale applies to right-*, bottom-*, and left-*.
WDiv(
className: 'relative h-48 bg-white border border-gray-200 rounded-lg',
children: [
WDiv(
className: 'absolute bottom-4 right-4 px-3 py-2 bg-blue-600 rounded',
child: WText('Action', className: 'text-sm text-white'),
),
],
)
Inset Shortcuts
Apply offsets to multiple sides at once with inset-* shorthand classes.
| Class | Sides Affected | Description |
|---|---|---|
inset-{n} |
top, right, bottom, left | All four sides |
inset-x-{n} |
left, right | Horizontal sides only |
inset-y-{n} |
top, bottom | Vertical sides only |
inset-0 |
top, right, bottom, left | Full stretch (fills parent) |
// Full overlay — covers the entire relative parent
WDiv(
className: 'relative w-full h-48',
children: [
WImage(src: 'assets/photo.jpg', className: 'w-full h-full'),
// Semi-transparent overlay that fills the image
WDiv(
className: 'absolute inset-0 bg-black opacity-40',
),
WText(
'Caption',
className: 'absolute bottom-4 left-4 text-white font-semibold',
),
],
)
// Horizontal inset — leaves top and bottom unconstrained
WDiv(
className: 'absolute inset-x-4 bottom-4 bg-white rounded p-3',
child: WText('Bottom bar'),
)
Negative Offsets
Prefix any offset class with - to pull an element outside its parent's boundary.
| Class | Value | Description |
|---|---|---|
-top-{n} |
negative top | Pulls element above the parent |
-right-{n} |
negative right | Pulls element to the right of the parent |
-bottom-{n} |
negative bottom | Pulls element below the parent |
-left-{n} |
negative left | Pulls element to the left of the parent |
-inset-{n} |
negative all sides | Expands element beyond all four parent edges |
// Notification badge — overlaps the top-right corner of an icon button
WDiv(
className: 'relative',
children: [
WDiv(className: 'w-10 h-10 rounded bg-gray-200 flex items-center justify-center'),
WDiv(
className: 'absolute -top-1 -right-1 w-4 h-4 rounded-full bg-red-500 flex items-center justify-center',
child: WText('3', className: 'text-[10px] text-white font-bold'),
),
],
)
Arbitrary Values
Use bracket notation when you need an exact pixel value not in the theme scale. Only px values are supported — percentage (%) offsets are not supported because Flutter's Positioned widget uses logical pixels, not relative units.
// Exact pixel value
WDiv(className: 'absolute top-[24px] left-[12px]')
// Mixed — precise multi-side offset
WDiv(className: 'absolute top-[12px] right-[8px] bottom-[12px] left-[8px]')
Common Patterns
Badge Overlay
A notification dot positioned on top of an avatar or icon.
WDiv(
className: 'relative w-12 h-12',
children: [
WDiv(className: 'w-12 h-12 rounded-full bg-indigo-500'),
WDiv(
className: 'absolute -top-1 -right-1 w-5 h-5 rounded-full bg-red-500 border-2 border-white flex items-center justify-center',
child: WText('2', className: 'text-[9px] text-white font-bold'),
),
],
)
Floating Action Button (FAB)
An action button pinned to the bottom-right corner of a scrollable view.
WDiv(
className: 'relative flex-1',
children: [
WDiv(
className: 'w-full h-full overflow-y-auto p-4',
child: WText('Scrollable content...'),
),
WDiv(
className: 'absolute bottom-6 right-6 w-14 h-14 rounded-full bg-blue-600 flex items-center justify-center shadow-lg',
child: WIcon(Icons.add_outlined, className: 'text-white'),
),
],
)
Full Overlay
A semi-transparent scrim that covers an entire card or image.
WDiv(
className: 'relative rounded-xl overflow-hidden',
children: [
WImage(src: 'assets/hero.jpg', className: 'w-full h-48 object-cover'),
WDiv(className: 'absolute inset-0 bg-gradient-to-t from-black/60 to-transparent'),
WDiv(
className: 'absolute bottom-0 left-0 right-0 p-4',
child: WText('Hero Title', className: 'text-white text-lg font-bold'),
),
],
)
Combining with Flex
relative and absolute compose naturally with flex layouts. The relative container itself can be a flex row or column — the Stack wraps around the flex widget, and absolute children are layered on top.
// Navigation bar with an absolute badge on the icon
WDiv(
className: 'flex flex-row items-center justify-between px-4 py-3 bg-white border-b border-gray-200',
children: [
WText('Inbox', className: 'text-base font-semibold text-gray-900'),
WDiv(
className: 'relative',
children: [
WIcon(Icons.notifications_outlined, className: 'text-gray-700'),
WDiv(
className: 'absolute -top-1 -right-1 w-4 h-4 rounded-full bg-red-500',
),
],
),
],
)
[!NOTE] When you add
absolutechildren to a flex item, Wind promotes that item to aStack. The flex layout of the parent is preserved.
Future Work
The following position types are tracked but not yet implemented in v1:
| Class | Status |
|---|---|
fixed |
Deferred — maps to Flutter's Overlay/Stack at the root level |
sticky |
Deferred — requires custom SliverPersistentHeader integration |
Until these land, use Overlay directly or Flutter's Stack at the Scaffold body level for fixed positioning.