Skip to content

Position

Use position utilities like relative and absolute to control how elements are positioned within their container. A relative parent becomes the anchor for any absolute descendants, which are rendered via a Flutter Stack + Positioned combination that reads top / right / bottom / left offsets from utility classes.

Not yet supported: fixed and sticky parse but currently render as normal flow — they require Flutter Overlay / Sliver integration which is tracked in PLAYGROUND_PARITY.md under library prerequisites.

Style('static ...', children: [
Text('Static parent'),
Style('absolute bottom-0 left-0 ...', child: Text('Absolute child')),
])

Offsets on static elements are ignored, and they do not serve as a positioning reference for absolutely positioned descendants.

Style('relative ...', children: [
Text('Relative parent'),
Style('absolute bottom-0 left-0 ...', child: Text('Absolute child')),
])

A relative element stays in normal flow but serves as the positioning reference for any absolute descendants.

Style('static ...', children: [
Style('static ...', child: Text('Static child')),
Style('...', child: Text('Static sibling')),
Style('absolute ...', child: Text('Absolute child')),
Style('...', child: Text('Static sibling')),
])

An absolute element leaves normal flow and is placed relative to the nearest relative ancestor. Sibling content behaves as if the absolute element doesn’t exist.

const _avatarUrl =
'https://images.unsplash.com/photo-1501196354995-cbb51c65aaea'
'?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8'
'&auto=format&fit=facearea&facepad=4&w=256&h=256&q=80';
const _contacts = <String>[
'Andrew Alfred',
'Debra Houston',
'Jane White',
'Ray Flint',
'Mindy Albrect',
'David Arnold',
];
class PositionFixedExample extends StatelessWidget {
const PositionFixedExample({super.key});
@override
Widget build(BuildContext context) {
return Style(
'px-3',
children: [
Style(
'relative mx-auto h-80 max-w-md overflow-hidden bg-white'
' shadow-lg ring-1 ring-gray-900/5 dark:bg-gray-800',
children: [
Style(
'absolute top-0 right-0 left-0 flex items-center'
' bg-gray-50/90 px-4 py-3 text-sm font-semibold'
' text-gray-900 ring-1 ring-gray-900/10 backdrop-blur-sm'
' dark:bg-gray-700/90 dark:text-gray-200 dark:ring-black/10',
child: const Text('Contacts'),
),
Style(
'flex h-80 flex-col divide-y divide-gray-200 overflow-auto'
' dark:divide-gray-200/5',
children: [
for (final name in _contacts)
Style(
'flex items-center gap-4 p-4',
children: [
Style(
'size-12 rounded-full',
child: Image.network(_avatarUrl, fit: BoxFit.cover),
),
Style(
'text-sm font-medium text-gray-900 dark:text-gray-200',
child: Text(name),
),
],
),
],
),
],
),
],
);
}
}
class PositionFixedPage extends StatelessWidget {
const PositionFixedPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(body: const PositionFixedExample());
}
}

Not yet supported — today this renders as a normal column. In browsers, fixed would pin the header to the viewport while the body scrolls.

Style('sticky top-0 ...', child: Text('A'))
Image.network('/img/andrew.jpg')
Text('Andrew Alfred')
Image.network('/img/aisha.jpg')
Text('Aisha Houston')
// ...
Style('sticky top-0', child: Text('B'))
Image.network('/img/bob.jpg')
Text('Bob Alfred')
// ...
// ...

Not yet supported — today this renders as a normal column. In browsers, sticky headers lock to the top of their scroll container until their parent group scrolls past.

ClassFlutterNotes
relativeServes as Stack anchor when children have absolute
absolutePositioned(top:, right:, bottom:, left:) inside nearest relative Stack
staticNo-op / normal flowDefault; explicit reset
fixedRenders as normal flowNot yet supported
stickyRenders as normal flowNot yet supported