Flex

Flex lines up its children in a row or a column and sets the space between them.

Flex places its children along one axis, as a row or a column, with gap between them. Use it for toolbars, form rows, stacks of text and anything that runs in one direction. When children need to line up in rows and columns at once, use Grid.

Playground

Usage

import { Avatar, Button, Flex, Text } from '@kushagradhawan/kookie-ui';
 
export function MemberRow({ name, email }: { name: string; email: string }) {
  return (
    <Flex align="center" gap="3" py="2">
      <Avatar fallback={name[0]} />
      <Flex direction="column" flexGrow="1" minWidth="0">
        <Text size="2" weight="medium" truncate>
          {name}
        </Text>
        <Text size="2" emphasis="medium" truncate>
          {email}
        </Text>
      </Flex>
      <Button emphasis="quiet">Remove</Button>
    </Flex>
  );
}

Best practices

Space children with gap, not margins. gap sets one distance between every child and leaves no extra space at the ends. It also works with components that don't take margin props.

Let one child grow. Give the flexible child flexGrow="1" and minWidth="0", and leave the rest at their natural size. Without minWidth="0", long text can't shrink or truncate.

Turn a row into a column on small screens. A responsive direction, such as { initial: 'column', sm: 'row' }, keeps one layout for every width.

Use Grid for two dimensions. Flex with wrap lines up items in each row but not across rows. Cards in a gallery or fields in a form belong in a Grid.

Direction and alignment

direction sets the main axis. justify places children along it and align places them across it.

PropValuesDefault
directionrow, column, row-reverse, column-reverserow
justifystart, center, end, betweenstart
alignstart, center, end, baseline, stretchstretch
wrapnowrap, wrap, wrap-reversenowrap

justify="between" pushes the first and last children to the ends, as in a header with a title on the left and actions on the right. align="baseline" lines up text of different sizes on one baseline.

Gap

gap takes a step from the space scale, '0' to '12', or a CSS string. Steps 2, 3 and 4 are 4, 8 and 12 pixels, and cover most rows of controls. gapX and gapY set the column and row gap apart, which matters once wrap is on. The full scale is on the Box page.

Examples

<Flex justify="between" align="center" gap="3">
  <Heading size="5">Projects</Heading>
  <Button emphasis="loud">New project</Button>
</Flex>

Stacked form fields

<Flex direction="column" gap="4" maxWidth="400px">
  <TextField.Root aria-label="Name" />
  <TextField.Root aria-label="Email" type="email" />
</Flex>

Wrapping chips

wrap="wrap" moves children to a new line when the row runs out of room. Set gapY when the rows need a different gap from the items.

<Flex wrap="wrap" gapX="2" gapY="2">
  {tags.map((tag) => (
    <Chip key={tag}>{tag}</Chip>
  ))}
</Flex>

Hidden on small screens

display accepts a responsive object. display={{ initial: 'none', md: 'flex' }} hides the row below 1024 pixels.

Props

PropTypeDefaultDescription
as'div' | 'span''div'The element to render
asChildbooleanfalseRenders the child element with the flex props
display'none' | 'inline-flex' | 'flex', responsive'flex'The CSS display
direction'row' | 'column' | 'row-reverse' | 'column-reverse', responsive'row'The main axis
justify'start' | 'center' | 'end' | 'between', responsive'start'Placement along the main axis
align'start' | 'center' | 'end' | 'baseline' | 'stretch', responsive'stretch'Placement across the main axis
wrap'nowrap' | 'wrap' | 'wrap-reverse', responsive'nowrap'Whether children wrap onto new lines
gap, gapX, gapY'0'–'12' or string, responsiveSpace between children

Flex also takes every layout prop that Box takes: padding, margin, width, height, position, inset, overflow, and the flex and grid child props. It accepts every attribute of the HTML div element, or span with as="span".