Concepts

Patterns

Patterns are layout primitives can be used to create robust and responsive layouts with ease. Panda comes with predefined patterns like stack, hstack, vstack, wrap, etc. These patterns can be used as functions or JSX elements.

💡

Think of patterns as a set of predefined styles to reduce repetition and improve readability. You can override the properties as needed, just like in the css function.

Creating Patterns

To learn how to create patterns, check out the customization section.

Predefined Patterns

Box

The Box pattern does not contain any additional styles. With its function form it's the equivalent of the css function. It can be useful with its JSX form and is the equivalent of a styled.div component, serving mostly to get style props available in JSX.

import { Box } from '../styled-system/jsx'
 
function App() {
  return (
    <Box color="blue.300">
      <div>Cool !</div>
    </Box>
  )
}

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>
  )
}

Stack

The Stack pattern is a layout primitive that can be used to create a vertical or horizontal stack of elements.

The stack function accepts the following properties:

  • direction: The flex direction of the stack. Can be either vertical or horizontal.
  • gap: The gap between the elements in the stack.
  • align: An alias for the css align-items property.
  • justify: An alias for the css justify-content property.
import { stack } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={stack({ gap: '6', padding: '4' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

HStack

The HStack pattern is a wrapper around the stack pattern that sets the direction property to horizontal, and centers the elements vertically.

import { hstack } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={hstack({ gap: '6' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

VStack

The VStack pattern is a wrapper around the stack pattern that sets the direction property to vertical, and centers the elements horizontally.

import { vstack } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={vstack({ gap: '6' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

Wrap

The Wrap pattern is used to add space between elements and wraps automatically if there isn't enough space.

The wrap function accepts the following properties:

  • gap: The gap between the elements in the stack.
  • columnGap: The gap between the elements in the stack horizontally.
  • rowGap: The gap between the elements in the stack vertically.
  • align: An alias for the css align-items property.
  • justify: An alias for the css justify-content property.
import { wrap } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={wrap({ gap: '6' })}>
      <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: Whether to wrap the flex items. The value is a boolean.
  • 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.
import { flex } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={flex({ direction: 'row', align: 'center' })}>
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
    </div>
  )
}

Center

The Center pattern is used to center the content of a container.

The center function accepts the following properties:

  • inline: Whether to use inline-flex or flex for the container. The value is a boolean.
import { center } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={center({ bg: 'red.200' })}>
      <Icon />
    </div>
  )
}

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 top-start, top, top-end, bottom-start, bottom, bottom-end, left-start, left, left-end, right-start, right or right-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 elements in the stack.
  • columnGap: The gap between the elements in the stack horizontally.
  • rowGap: The gap between the elements in the stack vertically.
  • minChildWidth: The minimum width of the child elements before wrapping.
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, stack } from '../styled-system/patterns'
 
function App() {
  return (
    <div className={stack()}>
      <button>First</button>
      <div className={divider({ orientation: 'horizontal' })} />
      <button>Second</button>
    </div>
  )
}

Circle

The Circle pattern is used to create a circle.

The circle function accepts the following properties:

  • size: The size of the circle. Can be a sizing token, or arbitrary value.
import { circle } from '../styled-system/patterns'
 
function App() {
  return <div className={circle({ size: '12', bg: 'red.300' })} />
}

Square

The Square pattern is used to create a square with equal width and height.

The square function accepts the following properties:

  • size: The size of the square. Can be a sizing token, or arbitrary value.
import { square } from '../styled-system/patterns'
 
function App() {
  return <div className={square({ size: '12', bg: 'red.300' })} />
}

Visually Hidden

The Visually Hidden pattern is used to hide an element visually, but keep it accessible to screen readers.

import { visuallyHidden } from '../styled-system/patterns'
 
export function Checkbox() {
  return (
    <label>
      <input type="checkbox" className={visuallyHidden()}>
        I'm hidden
      </input>
      <span>Checkbox</span>
    </label>
  )
}

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>
  )
}

cq (Container Query)

To make it easier to use container queries, we've added a new cq pattern to @pandacss/preset-base. It is used to apply styles based on the width of the container.

The cq function accepts the following properties:

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

You can also named container queries:

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

Read more about container queries here.

Usage with JSX

To use the pattern in JSX, you need to set the jsxFramework property in the config. When this is set, Panda will emit files for JSX elements based on the framework.

Every pattern can be used as a JSX element and imported from the /jsx entrypoint. By default, the pattern name is the function name in PascalCase. You can override both the component name (with the jsx config property) and the element rendered (with the jsxElement config property).

Learn more about pattern customization here.

import { VStack, Center } from '../styled-system/jsx'
 
function App() {
  return (
    <VStack gap="6" mt="4">
      <div>First</div>
      <div>Second</div>
      <div>Third</div>
      <Center>4</Center>
    </VStack>
  )
}

Advanced JSX Tracking

We recommend that you use the pattern functions in most cases, in design systems there might be a need to compose existing components to create new components.

To track the usage of the patterns in these cases, you'll need to add the jsx hint for the pattern config

button.pattern.ts
import { definePattern } from '@pandacss/dev'
 
const scrollable = definePattern({
  // ...
  // Add the jsx hint to track the usage of the pattern in JSX, you can also use a regex to match multiple components
  jsx: ['Scrollable', 'PageScrollable']
})

Then you can create a new component that uses the PageScrollable component and Panda will track the usage of the scrollable pattern as well.

const PageScrollable = (props: ButtonProps) => {
  const { children, size } = props
  return (
    <Scrollable {...props} size={size}>
      {children}
    </Scrollable>
  )
}