Docs
Flex

Flex

Flex is the main layout container of Apollion. It renders a <div> with display: flex and accepts the structural style API — spacing (margin/padding), size, container geometry, the flex layout props (gap, flexDirection, alignItems, justifyContent, …) and the responsive channels — in addition to the native <div> props.

Flex is layout only (ADR-028): it carries no background, border, elevation, typography or motion. Seeing a Flex (or Box / Grid) in a tree always means "this arranges things". When a block needs a visual ground — background, rounded border, shadow — that is a Paper or Card, and text styling belongs to Text. (Some examples below still paint their demo items to make the layout visible; author real UI with Paper for the surface.)

When to use

✅ Use when…🚫 Avoid when…
  • As the default container for any layout. Instead of stacking divs with CSS, declare gap, flexDirection, alignItems etc. directly.
  • When you need predictable spacing between children (gap).
  • To apply background, borders and padding without creating a dedicated styled-component.
  • For two-dimensional layouts with named areas. Use Grid.
  • When you need ready-made depth shadows. Use Paper, which already applies deep by default.

Spacing

With Flex you can create spacing between elements and orient them in a row or column, using the gap and flexDirection props.

loading

You can also control margin and padding using shorthands:

<Flex p="micro" />     // padding
<Flex pt="xs" />       // padding-top
<Flex pb="small" />    // padding-bottom
<Flex pl="medium" />   // padding-left
<Flex pr="large" />    // padding-right
<Flex py="xl" />       // vertical padding
<Flex px="xxl" />      // horizontal padding
 
<Flex m="micro" />     // margin
<Flex mt="xs" />       // margin-top
<Flex mb="small" />    // margin-bottom
<Flex ml="medium" />   // margin-left
<Flex mr="large" />    // margin-right
<Flex my="xl" />       // vertical margin
<Flex mx="xxl" />      // horizontal margin

Flex children

flex="initial"

Allows a child to shrink, but not grow — it respects the initial size.

Items do not grow when there is extra space
Short
Medium length
Items shrink when needed
Short
Medium length

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui ad labore ipsam.

<Flex flexDirection="row" wrap="wrap" gap="small">
  <Flex flex="initial">{/* does not grow; shrinks if needed */}</Flex>
  <Flex flex="initial">{/* does not grow; shrinks if needed */}</Flex>
</Flex>

flex="fluid"

Makes the child grow and shrink as needed, ignoring the initial size.

Default behavior
Short
Medium length
With flex="fluid"
Short
Medium length
Significantly larger amount of content.
<Flex flexDirection="row" wrap="wrap" gap="small">
  <Flex flex="fluid" />
  <Flex flex="fluid" />
  <Flex flex="fluid" />
</Flex>

flex="auto"

Makes the child grow and shrink, respecting the initial size.

Default behavior
Short
Medium length
Significantly larger amount of content.
With flex="auto"
Short
Medium length
Significantly larger amount of content.
<Flex flexDirection="row" wrap="wrap" gap="small">
  <Flex flex="auto" />
  <Flex flex="auto" />
</Flex>

flex="none"

Prevents both growing and shrinking — useful to "pin" a child between fluid elements.

Can grow and shrink
Fixed
Can grow and shrink
<Flex flexDirection="row" wrap="wrap" gap="small">
  <Flex flex="fluid" />
  <Flex flex="none">{/* neither grows nor shrinks */}</Flex>
  <Flex flex="fluid" />
</Flex>

Borders

loading

Background — that's Paper's job

Flex technically accepts bgColor (the prop surface is shared with every container), but reaching for it is the signal you want Paper instead. The division is semantic, and it is meant to be read in the code: a Flex declares structure — rows, columns, gaps, alignment — while a Paper declares a content surface — something the user is meant to look at. Paper has every Flex prop, plus the two things only a content surface earns: a background and a shadow. Painting a background on a Flex gives a structural node a visual role, and the next reader can no longer tell the skeleton from the skin.

// Structure: invisible skeleton — Flex.
<Flex flexDirection="row" wrap="wrap" gap="medium">
  {/* Content surface: visible sheet — Paper. */}
  <Paper p="medium" borderRadius="xs">
    <Text text="Content" />
  </Paper>
</Flex>

Responsive by viewport (viewportMedias)

There are three responsive channels; pick by what the layout should react to:

  • viewportMedias — one object per viewport breakpoint. The viewport sibling of cq, and the replacement for the flat md_/lg_/xl_ prefixes. Use it for genuine viewport cases — page shells, chrome shown/hidden by screen — where a container query is not an option (containment is barred on page-level shells).
  • cq — one object per container size. The layout reacts to the width of its own slot (see container queries).
  • flat sm_/md_/lg_/xl_ prefixes — the original per-prop viewport channel, now superseded by viewportMedias.
// flat prefixes — one prop per (axis × breakpoint):
<Flex md_flexDirection="row" md_gap="large" xl_p="small" />
 
// viewportMedias — one object per breakpoint:
<Flex viewportMedias={{ md: { flexDirection: 'row', gap: 'large' }, xl: { p: 'small' } }} />

The base (unprefixed) props are the mobile style; each breakpoint opts in on top, ascending min-width. viewportMedias accepts the same factory surface as cq (spacing, size, color, flex, font, background, deep — Border excluded).

Polymorphic as on a typed layout object

The styled Flex accepts as / forwardedAs natively. To annotate a plain layout object and still set as, type it as FlexProps (not DefaultFlexInterface) — FlexProps adds the polymorphic keys without a local augmentation:

import type { FlexProps } from '@apollion-dsi/core/containers/flex';
 
const shell: FlexProps = { as: 'section', gap: 'large', viewportMedias: { md: { flexDirection: 'row' } } };

Examples

Flex provides many styles as props, simplifying common layouts without requiring a dedicated styled-component.

Mixed layout (image + grid)

<Flex gap="small">
  <Paper bgColor="primary.light" height={150} deep={0}>
    <Image cover src="https://picsum.photos/500?random=10" />
  </Paper>
  <Flex flexDirection="row" wrap="wrap" gap="small" height={150}>
    <Paper bgColor="danger.light" flex="fluid" deep={0} />
    <Paper bgColor="danger.light" flex="fluid" deep={0} />
    <Paper bgColor="danger.light" flex="fluid" deep={0} />
  </Flex>
</Flex>

Product card

Lorem ipsum

R$ 1.900,00

/ month

<Paper
  maxWidth={280}
  minWidth={220}
  borderWidth="thin"
  borderRadius="xs"
  borderStyle="solid"
  borderColor="neutral.40"
  overflow="hidden"
  deep={0}
>
  <Flex height={200}>
    <Image cover src="https://picsum.photos/200" />
  </Flex>
  <Flex p="small">
    <Text text="Lorem ipsum" color="grayscale.80" fontSize="medium" fontWeight="bold" />
    <Text color="grayscale.80">
      R$ 1.900,00
      <Text color="grayscale.50" fontSize="small">
        {' '}
        / month
      </Text>
    </Text>
    <Flex flexDirection="row" wrap="wrap" justifyContent="end" mt="small">
      <Button size="small" variant="outlined" text="Rent" />
    </Flex>
  </Flex>
</Paper>

API summary

PropTypeDefaultDescription
gapnumber | SpacingInterfaceSpacing between children.
flexDirection'row' | 'column' | 'row-reverse' | 'column-reverse''column'Main-axis direction.
flex'fluid' | 'initial' | 'auto' | 'none'Grow/shrink behavior.
justifyContent'start' | 'end' | 'center' | 'between' | 'around' | 'evenly''start'Main-axis alignment.
alignItems'start' | 'end' | 'center' | 'baseline' | 'stretch''stretch'Cross-axis alignment.
wrap'wrap' | 'reverse' | 'nowrap'Line wrapping.
bgColor / colorstringBackground / text color via theme.
borderStyle / borderWidth / borderColor / borderRadiusstringBorders via theme.
height / maxHeight / minHeightnumber | stringVertical dimensions.
width / maxWidth / minWidthnumber | stringHorizontal dimensions.
p / px / py / pt / pb / pl / prnumber | SpacingInterfacePadding (shorthands).
m / mx / my / mt / mb / ml / mrnumber | SpacingInterfaceMargin (shorthands).
viewportMediasPartial<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', …>>One object per viewport breakpoint (sibling of cq).
cqPartial<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', …>>One object per container size.
as / forwardedAsReact.ElementTypeRender as another element (type a layout object as FlexProps).

This component's API is the system's layout props (spacing, color, flex/grid, size, border).

Avoid reaching for Paper out of habit when Flex would do — Paper only adds value when the content actually needs a depth shadow.

See also

  • Base primitive: Base.
  • Two-dimensional layouts: Grid.
  • Variant with shadows: Paper.