Conditions
Add your own named conditions, like _hover or dark, on top of Panda's built-in set.
A condition is a name you can use as a style key, _hover, _dark, md, that expands to a selector or at-rule.
This page is about defining your own, on top of the built-in ones.
Creating a condition
Add a condition under conditions.extend. Here's a groupHover condition that styles a child when a parent with
role="group" is hovered:
panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
groupHover: '[role=group]:where(:hover, [data-hover]) &'
}
}
})The & is required. It's the placeholder for whatever selector the condition ends up applied to, and it has to sit
at the start or the end of the string.
Run codegen to generate the _groupHover key:
import { css } from '../styled-system/css'
function App() {
return (
<div role="group">
<span
className={css({
color: { base: 'blue.400', _groupHover: 'blue.600' }
})}
/>
</div>
)
}Overriding a built-in condition
conditions.extend also lets you replace what a built-in condition does. Here's dark redefined to also match a
data-theme attribute, on top of the .dark class it already matches:
panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
dark: '.dark &, [data-theme="dark"] &'
}
}
})Run codegen again after any change here, built-in or custom, since the condition's expansion is baked into the
generated styled-system package.
Referencing tokens
A condition's selector string can call token(), and it resolves the same way it would inside a style object:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
mq: '@media (min-width: token(sizes.4xl))',
size2: '&[data-size=token(spacing.2)]'
}
}
})Combining multiple rules under one name
Give a condition an array instead of a string, and every entry nests inside the last, all under the one 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'
}
})generates:
@media (hover: hover) and (pointer: fine) {
&:hover {
color: red;
}
}One condition, several independent blocks
The array form above nests every rule inside the previous one. Sometimes you need the opposite: one condition that emits multiple separate CSS blocks, each with its own at-rule, not nested inside each other. A common case is hover feedback on pointer devices and press feedback on touch devices, two different media queries, same condition name.
Use the object form with @slot markers. Each path from the root down to an @slot becomes its own 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'
}
})generates two independent blocks:
@media (hover: hover) {
.hoverActive\:bg_red:is(:hover, [data-hover]) {
background: red;
}
}
@media (hover: none) {
.hoverActive\:bg_red:is(:active, [data-active]) {
background: red;
}
}An object with just one @slot path behaves the same as the array form above, this is the general case, the array
form is the shorthand for the common single-block one.
Container queries
Type-safe container queries are their own topic. See container queries.
Starting from zero
Everything here assumes you're extending Panda's defaults with conditions.extend. For no built-in conditions at
all, see minimal setup.