concepts
patterns

Patterns

Patterns are layout primitives that can be used to create robust and responsive layouts with ease. Bamboo comes with predefined patterns like flex, grid, center, container, etc. Each one is a function that returns a class name.

Pattern properties can be overridden as needed, just like in the css function. To define your own, see customization.

Predefined Patterns

💡

Patterns are removed whenever one turns out to be a second spelling of something the system already had. box(styles) was exactly css(styles) and visuallyHidden() was css({ srOnly: true }); stack, hstack, vstack and wrap were flex with defaults frozen; square and circle were center with a size; and cq was css({ containerType, containerName }). Each section below says what to write instead.

Container

The Container pattern is used to create a container with a max-width and center the content.

By default, the container sets the following properties:

  • maxWidth: 8xl
  • marginX: auto
  • position: relative
  • paddingX: { base: 4, md: 6, lg: 8 }
import { container } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={container()}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

Aspect Ratio

The Aspect Ratio pattern is used to create a container with a fixed aspect ratio. It is used when displaying images, maps, videos and other media.

💡

Note: In most cases, we recommend using the aspectRatio property instead of the pattern.

The aspectRatio function accepts the following properties:

  • ratio: The aspect ratio of the container. Can be a number or a string.
import { aspectRatio } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={aspectRatio({ ratio: 16 / 9 })}>
      <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m1" title="Google map" frameBorder="0" />
    </div>
  )
}

Flex

The Flex pattern is used to create a flex container and provides some shortcuts for the flex property.

The flex function accepts the following properties:

  • direction: The flex direction of the container. Can be row, column, row-reverse or column-reverse.
  • wrap: An alias for the css flex-wrap property.
  • align: An alias for the css align-items property.
  • justify: An alias for the css justify-content property.
  • basis: An alias for the css flex-basis property.
  • grow: An alias for the css flex-grow property.
  • shrink: An alias for the css flex-shrink property.

Any other style property is accepted too, so gap and the rest of the box model work here without being listed above.

import { flex } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={flex({ direction: 'row', align: 'center', gap: '6' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

stack, hstack, vstack and wrap were removed. Each was flex with defaults frozen, so writing the default you want is the whole migration — and the gap they applied silently is now yours to choose:

flex({ direction: 'column', gap: '8px' }) // was stack()
flex({ align: 'center', gap: '8px' }) // was hstack()
flex({ direction: 'column', align: 'center', gap: '8px' }) // was vstack()
flex({ wrap: 'wrap', gap: '8px' }) // was wrap()

Center

The Center pattern is used to center the content of a container, optionally at a fixed size.

The center function accepts the following properties:

  • inline: Whether to use inline-flex or flex for the container. The value is a boolean.
  • size: Sets width and height together, and stops a flex parent from shrinking the result.
import { center } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={center({ bg: 'red.200' })}>
      <Icon />
    </div>
  )
}

Pass size for a fixed square, and add borderRadius for a circle:

import { center } from '../styled-system/patterns'
 
function App() {
  return (
    <>
      <div className={center({ size: '12', bg: 'red.300' })}>1</div>
      <div className={center({ size: '12', borderRadius: 'full', bg: 'red.300' })}>2</div>
    </>
  )
}

square and circle were removed. square({ size }) is center({ size }), and circle({ size }) is center({ size, borderRadius: 'full' }) — borderRadius is an ordinary style property, so the rounded case never needed a pattern of its own.

LinkOverlay

The link overlay pattern is used to expand a link's clickable area to its nearest parent with position: relative.

💡

We recommend using this pattern when the relative parent contains at most one clickable link.

import { css } from '../styled-system/css'
import { linkOverlay } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={css({ pos: 'relative' })}>
      <img src="https://via.placeholder.com/150" alt="placeholder" />
      <a href="#" className={linkOverlay()}>
        View more
      </a>
    </div>
  )
}

Float

The Float pattern is used to anchor an element to the top, bottom, left or right of the container.

💡

It requires a parent element with position: relative styles.

The float function accepts the following properties:

  • placement: The placement of the element. Can be bottom-end, bottom-start, top-end, top-start, bottom-center, top-center, middle-center, middle-end or middle-start. Defaults to top-end.
  • offset: The offset of the element from the edge of the container. Can be a number or a string.
  • offsetX: Same as offset, but only for the horizontal axis.
  • offsetY: Same as offset, but only for the vertical axis.
import { css } from '../styled-system/css'
import { float } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={css({ position: 'relative' })}>
      <div className={float({ placement: 'top-start' })}>3</div>
    </div>
  )
}

Grid

The Grid pattern is used to create a grid layout.

The grid function accepts the following properties:

  • columns: The number of columns in the grid.
  • gap: The gap between the grid items.
  • columnGap: The gap between the grid items horizontally.
  • rowGap: The gap between the grid items vertically.
  • minChildWidth: The minimum width of the child elements before wrapping (must not be used with columns).
import { grid } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={grid({ columns: 3, gap: '6' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

Grid Item

The Grid Item pattern is used to style the children of a grid container.

The gridItem function accepts the following properties:

  • colSpan: The number of columns the item spans.
  • rowSpan: The number of rows the item spans.
  • rowStart: The row the item starts at.
  • rowEnd: The row the item ends at.
  • colStart: The column the item starts at.
  • colEnd: The column the item ends at.
import { grid, gridItem } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={grid({ columns: 3, gap: '6' })}>
      <div className={gridItem({ colSpan: 2 })}>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

Divider

The Divider pattern is used to create a horizontal or vertical divider.

The divider function accepts the following properties:

  • orientation: The orientation of the divider. Can be horizontal or vertical.
  • thickness: The thickness of the divider. Can be a sizing token, or arbitrary value.
  • color: The color of the divider. Can be a color token, or arbitrary value.
import { divider, flex } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={flex({ direction: 'column', gap: '8px' })}>
      <button>First</button>
      <div className={divider({ orientation: 'horizontal' })} />
      <button>Second</button>
    </div>
  )
}

Spacer

The Spacer pattern is used to create an adjustable, empty space in a flex or grid layout.

The spacer function accepts the following properties:

  • size: The fixed size of the spacer. Can be a spacing token, or arbitrary value. When omitted, the spacer grows to fill the remaining space.
import { flex, spacer } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={flex({ align: 'center', gap: '8px' })}>
      <div>Logo</div>
      <div className={spacer()} />
      <div>Menu</div>
    </div>
  )
}

Bleed

The Bleed pattern is used to create a full width element by negating the padding applied to its parent container.

The bleed function accepts the following properties:

  • inline: The amount of padding to negate on the horizontal axis. Should match the parent's padding.
  • block: The amount of padding to negate on the vertical axis. Should match the parent's padding.
import { css } from '../styled-system/css'
import { bleed } from '../styled-system/patterns'
 
export function Page() {
  return (
    <div className={css({ px: '6' })}>
      <div className={bleed({ inline: '6' })}>Welcome</div>
    </div>
  )
}

Container Queries

There is no pattern for this — containerType and containerName are ordinary utilities, and containerName is already typed against the containerNames theme key.

import { css } from 'styled-system/css'
 
function Demo() {
  return (
    <nav className={css({ containerType: 'inline-size' })}>
      <div
        className={css({
          fontSize: { base: 'lg', '@/sm': 'md' },
        })}
      />
    </nav>
  )
}

You can also use named container queries:

// 1 - Define container conditions
 
export default defineConfig({
  // ...
  theme: {
    containerNames: ['sidebar', 'content'],
    containerSizes: {
      xs: '40em',
      sm: '60em',
      md: '80em',
    },
  },
})
// 2 - Name the container and query it
 
import { css } from 'styled-system/css'
 
function Demo() {
  return (
    <nav className={css({ containerType: 'inline-size', containerName: 'sidebar' })}>
      <div
        className={css({
          // When the sidebar container reaches the `sm` size
          // change font size to `md`
          fontSize: { base: 'lg', '@sidebar/sm': 'md' },
        })}
      />
    </nav>
  )
}

The cq pattern was removed. It renamed two properties onto containerType and containerName and defaulted the first to inline-size, which is one default's worth of value for a name that sat next to the unrelated container pattern in autocomplete.

Read more about container queries here.