customization
conditions

Conditions

Learn how to customize conditions in your Panda config

Conditions allow you to apply different styles and behaviors based on specific conditions or states. They provide a way to target specific elements or apply styles in response to certain events or conditions.

Creating a condition

To create a condition, you can use the conditions property in the config. Let's say we want to create a groupHover pseudo condition that applies styles to an element when a parent container with the group role is hovered.

panda.config.ts

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  conditions: {
    extend: {
      groupHover: '[role=group]:where(:hover, [data-hover]) &'
    }
  }
})
💡

⚠️ The & character is mandatory, it is a placeholder for the current selector. It will be replaced with the actual selector when the condition is used. It has to be used either at the beginning or at the end of the condition.

Then you can run the following command to generate the conditions JS code:

pnpm panda codegen

Now, we can use the groupHover condition in our components.

import { css } from '../styled-system/css'
 
function App() {
  return (
    <div role="group">
      <span
        className={css({
          color: { base: 'blue.400', _groupHover: 'blue.600' }
        })}
      />
    </div>
  )
}

Customizing Built-in Conditions

You can extend the default conditions by using the conditions.extend property in the config.

panda.config.ts

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  conditions: {
    extend: {
      // Extend the default `dark` condition
      dark: '.dark &, [data-theme="dark"] &'
    }
  }
})

Then you can run the following command to update the conditions JS code:

pnpm panda codegen

Using tokens

You can also use tokens in your conditions, and they will be resolved to their actual values:

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  conditions: {
    extend: {
      mq: '@media (min-width: token(sizes.4xl))',
      size2: '&[data-size=token(spacing.2)]'
    }
  }
})

Mixed conditions

You can also use mixed conditions (nested at-rules/selectors) under a single condition name:

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  conditions: {
    extend: {
      supportHover: ['@media (hover: hover) and (pointer: fine)', '&:hover']
    }
  }
})
import { css } from '../styled-system/css'
 
css({
  _supportHover: {
    color: 'red'
  }
})

will generate the following CSS:

@media (hover: hover) and (pointer: fine) {
  &:hover {
    color: red;
  }
}

Multi-block conditions

Sometimes you need a single condition to generate multiple independent CSS blocks, each with its own at-rule. For example, you might want hover feedback on desktop (pointer devices) and active/press feedback on touch devices.

Use the object syntax with @slot markers to define multi-block conditions. Each path from the root of the object to a @slot value becomes an independent CSS block:

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  conditions: {
    extend: {
      hoverActive: {
        '@media (hover: hover)': {
          '&:is(:hover, [data-hover])': '@slot',
        },
        '@media (hover: none)': {
          '&:is(:active, [data-active])': '@slot',
        },
      },
    },
  },
})
import { css } from '../styled-system/css'
 
css({
  _hoverActive: {
    bg: 'red',
  },
})

will generate the following CSS:

@media (hover: hover) {
  .hoverActive\:bg_red:is(:hover, [data-hover]) {
    background: red;
  }
}
@media (hover: none) {
  .hoverActive\:bg_red:is(:active, [data-active]) {
    background: red;
  }
}

This is also useful for any scenario where a single condition needs to apply the same styles across multiple independent at-rule blocks. Objects with a single @slot path behave identically to the mixed conditions array syntax.

Container queries

Read more about how to define type-safe container queries here

Minimal setup

If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it here