"Why would I choose Panda CSS ?"
And why it's easier to answer this question
It’s another question that I see a lot, a bit different than the previous one.
The previous question was more about comparing two solutions (what does Panda has that xxx
doesn’t and vice-versa). Since I wanted this question to be fair from both sides by anyone debating on the topic, and as I am pretty knowledgeable with Panda; I mostly wrote about Panda’s limitations, their reasons and some workarounds.
This time, I feel like this question is more about what strengths Panda has to offer. And I’ve got tons of answers for that !
This post will be split in 4 parts:
1. An overview of the main features
- 1.0. Build-time CSS
- 1.1. Atomic CSS
- 1.2. Type-safety
- 1.3. Batteries included
- 1.4. Extendable
- 1.5. CSS-in-JS
- 1.6. Style props
- 1.7. Merging styles
- 1.8. Static analysis
- 1.9. Runtime dynamic styling
- 1.10. Static generator
- 1.11. Modern
- 1.12. Multi-Theme tokens
- 1.13. Virtual color palette
2. A look at the possible use-cases
- 2.0. Styling solution
- 2.1. Design system
- 2.2 Token generator
- 2.3 Styling engine
3. A summary of the DX
- 3.0. Easy to learn
- 3.1. Easy to use
- 3.2. Easy to customize
- 3.3. Easy to distribute
4. A concise API reference with examples
- 4.0. css
- 4.1. cx
- 4.2. cva
- 4.3. config recipes
- 4.4. slot recipes
- 4.5. sva
- 4.6. styled
- 4.7. patterns
- 4.8. utility
- 4.9. Runtime token()
- 4.10. Compile-time string token()
- 4.11. JSX style props
- 4.12. JSX css prop
- 4.13. .raw(xxx) merging
- 4.14. Runtime conditions
- 4.15. CSS nesting
- 4.16. colorPalette
- 5.0. Theme
- 5.1. tokens
- 5.2. semantic tokens
- 5.3. conditions
- 5.4. breakpoints
- 5.5. shorthands
- 5.6. textStyles
- 5.7. keyframes
- 6.0. CLI
- 7.0. Online playground
So, from the endless list of styling solutions and CSS-in-JS
libraries, why should you choose Panda?
Build-time CSS
Panda CSS uses static analysis
on your code to generate CSS. This means that we look at the code you wrote (source files) and generate CSS from it.
This is a huge advantage over runtime
styling solutions, not only because it’s faster (no need to compute/inject style at runtime, on each render, which could cause style recalculations for the browser), but also because it means that we can generate a raw CSS file that you can use (and cache !) anywhere.
Atomic CSS
Also sometimes called utility-first
, this is a very popular way of writing CSS.
The idea is to write 1 CSS class per CSS property, and then compose them together. This leads to a small optimized CSS file, since most of the time you’ll reuse the same CSS classes.
Built-in Type-safety
Panda CSS leverages TypeScript
to provide type-safety.
This means that you’ll get autocompletion, type-checking and you’ll be yelled at if you do something wrong. ⚠️
This also means that you don’t need a VSCode extension to get autocompletion and type-safety, it’s built-in. (tho, we’ve been working on a VSCode extension that provides super-powered autocompletion and even more features)
ℹ️ Note: By default, config.strictTokens
is set to false
and that means you’ll get autocompletions from your config.theme
but you’ll also be able to use any CSS value.
If you set config.strictTokens
to true
, you’ll only be able to use tokens
that are included in your config
, unless using the escape-hatch syntax [xxx]
:
Batteries included
Built-in presets
We provide 2 different presets out of the box (you don’t need to install anything):
@pandacss/preset-base
, which contains the default conditions / utilities / patterns@pandacss/preset-panda
, which contains the default theme (keyframes
/breakpoints
/tokens
/textStyles
)
If those presets don’t fit your needs, you can always set config.eject
to true
to remove them and start from scratch with a minimal setup.
You can also create your own presets and share them with the community !
No additional tooling
Since Panda is based on Typescript
, you don’t need to install any VSCode extension to get autocompletion (and inline documentation from MDN through csstype
), it’s built-in.
Prettier just works, it’s just functions and objects.
Merging styles ? Covered. Recipes (cva) ? Gotcha.
Extendable
Theming
I mentioned the ability to create your own presets, but of course you can also just customize your panda.config.ts
with your theme (keyframes
/ breakpoints
/ tokens
/ textStyles
) / conditions / utilities / patterns to fit your needs.
Using the extend
keyword inside of any of those config options will allow you to add your own customizations on top of the default presets (and any other that you added).
Everything will be deep merged, that means keys with the same name will be merged together, arrays will be concatenated, etc.
Outdir
Panda CSS is very flexible and can be used in many different ways. That’s partly because we’re using a codegen step that allows us to generate a style-system
tailored to your needs.
Let’s say you don’t like
shorthands
? Setconfig.shorthands
tofalse
and they won’t be allowed anymore.Stricter type-safety ? Set
config.strictTokens
totrue
Too many properties suggested in the
styled
factory andJSX patterns
? Setconfig.jsxStyleProps
tominimal
(that only allows thecss
special property) ornone
to disable them completely.Need to change the
@layer
names ? Setconfig.layers
to whatever you need. (Can be useful to avoid naming conflicts with other styling libraries !)
CSS generation
You can also customize the way we generate CSS, like which separator
should be used in the generated class names, or config.prefix
to add a prefix to all your class names.
We also include a CSS reset by default, but you can disable it with config.preflight
set to false
.
Config
You can see the full list of config options here: https://panda-css.com/docs/references/config
CSS-in-JS
Ever since the rise of CSS-in-JS (thanks to @vjeux !), there’s been a lot of debates about it. Some people love it, some people hate it.
I personally love it, I think it just makes sense to have your whole UI component in one place, markup AND styling. This is basically the idea of colocation taken to the next level.
Well, actually with Panda it’s not really CSS-in-JS
, it’s more like CSS-in-TS
since we’ve got type-safety all over the place.
And that works with most JSX-like frameworks: React / Preact / Svelte / Vue / Solid / Qwik
RSC compatible
Panda CSS is compatible with React Server Components (RSC), you don’t need to do anything special, after all we’re just generating CSS at build-time
. 😁
Style props
Not only you can use the css
function inside your components file to style them, but you can also use any JSX props that matches either a CSS property name, shorthand
or a utility
defined in your config (or from a preset
).
Merging styles
Related docs : https://panda-css.com/docs/concepts/merging-styles
css merging
For example, you can just pass multiple arguments to the css
function, and they’ll be merged together.
raw() marker
This can be especially useful with the .raw()
function, available on css
/ recipes
/ patterns
.
This raw
function will return what you passed in (except when used on patterns
, it will transform the object back to a css
-compatible object), and serves as a marker for the static analysis
, to tell the Panda extractor
that you’re creating a style object
and we should generate the CSS for it.
cx
You can also use the cx
function to merge multiple class names together.
More examples are available here
Static analysis
Pit of success
Given we want to generate a CSS file at build-time
, we need to know what CSS to generate before running your app, and that’s where static analysis
comes in: by scanning your source files and finding style usage in there.
I would not really say that static analysis
is an intended feature, as it also introduces some limitations, but I feel like it incidentally forces you to write better code, basically it acts like a pit of success.
Since you can’t (easily/directly) use runtime dynamic values
, you’ll have to find a way to make it static, and that’s actually a good thing both in term of code maitainability and performance !
Smart
In addition to that benefit, our static extractor is pretty smart, it can detect style usage in many different ways to the point where it doesn’t seem static anymore.
I’m pretty confident it’s one of the most advanced static extractor among build-time
styling solutions !
Extractor Examples
Runtime conditions, identifier resolving, static evaluation, all of those just work.
There are of course still some limitations to static analysis, I wrote a bit about it here
Runtime dynamic styling
I just said that Panda CSS uses static analysis
to generate CSS, but that doesn’t mean you can’t use runtime dynamic values
! You just have to find a way to make it static.
Related documentation is here
Using CSS variables
It’s true that you cannot directly use runtime
values (like variables created from useState
) inside Panda’s functions like css
or cva
, since those need statically analyzable arguments.
But you can use CSS variables to achieve the same result, using the style
attribute.
Using variants
You might have seen this kind of prop-based code with other styling solutions:
With Panda CSS, you could use an atomic recipe
(2nd argument of the styled factory
or cva
) to keep the style definition static.
Not only does it achieve the same result but you also unlock the possibilities of having multiple styles bound to the same variant, and of course you can create as many variants as you want.
Best practices
Avoid dynamically updating the styles, and instead use CSS selectors to style your components based on their state.
For example, you can use the data-xxx
attributes to store the state, and then use the &[data-xxx]
selector to style it.
ℹ️ Note that this specific data-selected
example is built-in with the default conditions, so you could use it like _selected: { color: "blue.500" }
.
Static generator
Panda analyzes your code to generate CSS, but it also provides a way to generate CSS from rules that you can provide in the config.staticCss
option. This is useful:
- when the static extractor can’t find a style usage in your code (e.g. if you’re using something too dynamic or a runtime-only value)
- to get rid of the lightweight JS runtime entirely by directly using the generated CSS atomic classes
- to pre-generate the CSS for a component library
https://panda-css.com/docs/guides/static
Modern
Panda uses modern CSS features like cascade layers (@layer
), CSS variables, modern selectors like :where
and :is
in generated styles.
Using the CSS @layer
, there’s no specificity war, for example your utilities
style would always prevail on your recipes
style, since they’re always applied in the right order. Read more here.
That being said, if you need to support older browsers you can always use this postcss
plugin to polyfill the @layer
syntax and specifity.
Multi-Theme tokens
You can use custom conditions
to create multi-theme tokens, and since you can nest them, you can create as many combinations as you want.
Pink dark
Blue dark
Pink light
Blue light
Since Panda is based on CSS variables, that also means you can override the data-theme
anytime in the DOM, and it will automatically update the colors. You could even replace the theme colors by overriding the current CSS variables with a style={xxx}
attribute, useful for example if you want to let your users customize the colors at runtime.
Virtual color palette
One of the most powerful feature, yet not very well known, is the ability to create a virtual color palette from your tokens.
This allows you to refer to a dynamic color by its shade (50
to 900
in the built-in preset) or its semantic name, and it will automatically resolve to the current color palette.
Multi-theme color palette
Combined with custom conditions
, you can create a multi-theme color palette that can also handle color modes (light/dark), statically. I went a bit crazy with this next example, but it shows the power of Panda CSS.
No theme, variant shades
Main theme
Secondary theme
ℹ️ Note that you could duplicate that button
object in the semanticTokens
and just change the color values to get another color palette, with the same nested semantic names, reacting to the same conditions.
e.g you could name it alert
and have alert.info
/ alert.warning
/ alert.warning.accent
/ alert.warning.accent.secondary
all able to handle light
/ dark
color modes for both the main
and secondary
theme.
Use cases
Styling solution
This is the most common scenario, styling your appliction UI with Panda CSS.
While Panda brings many features to the table, you can choose to use a very small API surface, using only the css
function to style your components, and that’s it.
Panda definitely brings some cool features for CSS-in-JS
, but if that’s not your thing, that’s ok too.
Maybe colocation isn’t your thing at all ? It’s fine, you can keep your style objects in a separate file (.css.ts
?).
Design-system / Component library
Panda comes with many tools for creating a design system
or component library. :
Using the panda.config
you can create a theme (tokens
/ breakpoints
/ textStyles
/ etc .. ) and even create your own utilities
/ conditions
/ patterns.
If needed, you can enforce type-safety by setting config.strictTokens
to true
.
The tokens (and semantic tokens) format is largely influenced by the W3C Token Format
Recipes and slot recipes are a great way to style reusable components that can be used in many different ways through their variants.
Patterns saves you from writing the same CSS or props over and over again.
Token generator
If you prefer writing raw CSS, you can still leverage Panda’s token generator to generate CSS variables for each of your tokens
/semantic tokens
.
https://panda-css.com/docs/overview/why-panda#token-generator
Styling engine
Panda CSS being a styling engine, it’s not tied to any framework or library, you can use it anywhere. You could even build your own abstractions on top of it !
With the @pandacss/node
package, you can have access to the same API as we use in the CLI and VSCode extension. The PandaContext
contains lots of useful methods, for example you can generate each @layer
CSS independently, manipulate the TokenDictionary
, extract CSS from your code… You could create a bundler’s plugin with that, or you could probably even create your own extractor
and use it to generate CSS from your non-typescript code.
Static Extractor
Speaking of the static @pandacss/extractor
, it actually doesn’t use any Panda-related code, its only dependency is ts-morph
(a wrapper around typescript
parser). You could also use it to extract static values from any function or JSX in your code.
Developer experience (DX)
Easy to learn
It’s just the CSS you know already, using camelCase
instead of kebab-case
, with the additions of type-safety
autosuggestions for tokens
and conditions
while still allowing raw values and selectors.
There’s no need to learn a new syntax, no need to remember which class to use for whatever property, everything will feel very familiar and intuitive, in addition to the autocompletion and type-safety built-in.
Easy to use
Since all Panda does it generating a CSS, you can use it anywhere with our CLI
. ¹
We also provide a postcss
plugin to skip the CSS file import step and having another process (CLI with --watch
) to run in parallel.
While Panda brings many features to the table, you can choose to use a very small API surface, using only the css
function to style your components, and that’s it. If you’re not a fan of CSS-in-JS
, that’s also fine.
Maybe colocation isn’t your thing at all ? It’s fine, you can keep your style objects in a separate file. It just works.
Getting started is as easy as installing the CLI and running the panda init -p
command in your project.
¹. A real-world example : I’m not really familiar with Angular, but it seems to require a dedicated integration to work with CSS-in-JS libraries. There’s even an issue opened to get one for Panda, but as the author mentioned, it’s not really needed since you can just use the CLI + the generated CSS file. Still, I can see the convenience !
Easy to customize
Even though Panda CSS comes with batteries-included, you can customize it to fit your needs.
Using the panda.config
you can extend the default one or create your own theme (tokens
/ breakpoints
/ textStyles
/ etc .. ) and even create your own utilities
/ conditions
/ patterns.
You can disable/omit features that you don’t need, like shorthands
, jsxStyleProps
or even jsxFramework
entirely ! If you feel like type-safety
must be enforced, you can set strictTokens
to true
.
Easy to distribute
Panda can be distributed in different ways, depending on your needs.
We have a documentation page related to this topic: component library and there are a few examples in this repository
Preset
Using a preset is the easiest way to distribute your Design System (tokens
, breakpoints
, recipes
, etc) with other Panda users.
It’s as simple as picking a few options from your panda.config.ts
, creating a new preset.ts
file and exporting those options.
You can then publish it to npm and anyone can use it by installing it and adding it to their own panda.config.ts
file.
There are a few hand-picked presets listed in EcoPanda, by Abraham.
CSS file
You can also distribute your library CSS by generating a static file using the CLI, and use it anywhere.
⚠️ This of course means that you shouldn’t directly expose any Panda API (
css
/recipes
/ etc..) to your users because it would not generate any additional CSS.
Component library
Panda allows you to create a component library, it could be intended for other Panda users or for anyone.
If you intend to distribute it to other Panda users:
- you should distribute a
preset
along with your components, so that your users can generate the CSS for yourtokens
/recipes
/ etc - make a package dedicated to the
config.outdir
(defaults tostyled-system
, for this example we’ll use@acme/styled-system
) - both you and your users must set your
config.importMap
to be the same as your outdir package name (@acme/styled-system
)
This is because:
- Panda uses the
importMap
to know which imports should matching your theme (tokens
/recipes
/ etc..) - by sharing the same
module specifier
(the right part of imports, e.gabc
inimport xxx from 'abc'
), your bundler (vite
for example) will be able to deduplicate the lightweight JS runtime (config.outdir
) between the one from your library and the one from your users.
If you don’t share the same module specifier, users will end up bundling the code for 2 different css
functions, cva
etc; one from your library (@acme/styled-system
) and one from your users outdir (styled-system
by default) which is not ideal.
set your outdir package name (
@acme/styled-system
) as external in your build step so that you don’t bundle it with your components, ex:tsup src/index.tsx --external @acme-org/styled-system
you can expose any Panda API (
css
/recipes
/ etc..)
Summary:
- publish a Panda
preset
so people can use your design system tokens - an outdir package (
@acme-org/styled-system
) so your users can override or extend your design system tokens - and of course your components (
@acme-org/components
) using the@acme-org/styled-system
asexternal
Copy-paste
There’s a recent trend of creating a component library and distributing it as a copy-paste
solution.
For example, Park UI and Shadow Panda (shadcn-ui
equivalent using Panda) are both component libraries that only rely on a preset
published on npm and then you can just pick the components you need and copy-paste them in your project.
Interlude
Let’s take a little break. If you reached this far, you probably have a good idea of what Panda CSS
is, and what it can do for you.
The part below is mostly concise explanations/examples of what the documentation already covers (I shamelessly took small parts of it), so that you can have a quick overview/reference of the API surface.
This should also help searching for a specific feature, since the documentation is pretty long, and this is a one-page reference searchable with cmd+f
.
If you want to learn more about a specific topic, I encourage you to read the related documentation, it’s pretty good !
API examples
What better way to showcase what Panda CSS can do than with some concrete examples ?
css
The css
function is the main API of Panda CSS, it’s used to generate CSS from your style objects.
In the static analysis step we extract each arguments, resolving each style object property/value combinations, and generating an atomic CSS rule for each of them.
At runtime, it transforms the object-syntax (that you provide) to a class string composed of atomic classes. Most Panda features are using the css
function under the hood. (cva
, recipes
, patterns
, styled
factory, etc…). That means that anything you can do with the css
function, you can do the same in those features.
Property keys can be: any config
breakpoints
/conditions
/utility
/shorthands
/arbitrary
selectors / CSS built-in properties / CSS variablesProperty values can be: any config
tokens
/semantic tokens
/utility
specific values / arbitrary values / CSS built-in values / conditions as object / token path (only when using a CSS variable as key)Has a
.raw()
function to mark the object as a style object for the Panda static extractorCan use the inline
token(value, fallback)
function that will be transformed at compile-time to a CSS variable (using postcss)Will smartly merge each arguments together, including
css.raw()
,{cvaFn}.raw()
or{patternFn}.raw()
calls
cx
You can use the cx
function to concatenate multiple class names together.
cva
cva
allows you to create a re-usable styles based on variants, that still produces atomic CSS classes. They’re the atomic equivalent of the config recipe
.
cva
base and variants styles will be always be generated, no matter if they’re used or not.
You can read more here to understand the difference between recipes and cva.
Inside the base
and variants
styles, you can use anything that you can use in the css
function and even merge multiple css
and cva
together.
recipes
tl;dr: Like cva
but scoped with a className instead of generating atomic CSS classes.
config recipes
allows you to create a re-usable styles based on variants, including responsive variants, that produce scoped CSS classes. They’re the scoped equivalent of the cva
atomic fn.
config recipes
base and variants styles will be generated JIT, as in, only when found in the source files.
Since config recipes
are scoped by a className that you provide, they generate very predictable CSS rules, which makes them very easy to override using raw CSS. This can be particularly useful when creating a component library.
You can read more here to understand the difference between recipes and cva.
Inside the base
and variants
styles, you can use anything that you can use in the css
function.
slot recipes
tl;dr: Like config recipes
but with slots
, allowing you to style multipart components.
This is a special kind of recipe that allows you to create a re-usable styles based on slots
, that produce scoped CSS classes. Each slot should map to a component part, for example a button
could have a icon
slot, a label
slot, a loading
slot, etc.
These slots can then be styled together, reacting to the same variants. For example, your button
could have a size
variant that would apply to both the icon
and label
slots, slightly changing their font-size and padding.
The same upside and downsides from the config recipes
apply here.
You can read more here to understand the difference between config (slot) recipes and sva.
sva
tl;dr: Like cva
but for slot recipes
.
This is a special kind of recipe that allows you to create a re-usable styles based on slots
, that produce atomic CSS classes. Each slot should map to a component part, for example a button
could have a icon
slot, a label
slot, a loading
slot, etc.
These slots can then be styled together, reacting to the same variants. For example, your button
could have a size
variant that would apply to both the icon
and label
slots, slightly changing their font-size and padding.
The same upside and downsides from the cva
fn apply here.
You can read more here to understand the difference between config (slot) recipes and sva.
styled
When using a JSX
-like framework, you can use the styled
factory to create a styled component
, e.g a component that can receive JSX style props
.
style props
are just properties matching the same name as your css()
function keys (which means any breakpoints
/ conditions
/ utility
/ shorthands
/ CSS built-in property).
⚠️ You should NOT rename JSX properties, like using myColor={color}
instead of color={color}
. This is due to static limitations
You can use the 2nd
argument of the styled
factory to create an inline atomic recipe
or re-use an existing one. (could also be a config recipe
)
You can also create a styled
component using another one as basis (1st arg), and the previous atomic recipe
base and variants styles will automatically be deep merged with the new one. (new wins in case of conflict)
Finally, the 3rd
argument of the styled
factory allows you to provide default props for your component or override which props should be forwarded to the underlying DOM element.
patterns / jsx patterns
Patterns are layout primitives that you can use to avoid writing the same CSS over and over again. They also have access to the same features as the css()
function, with the addition of specific utility
props per pattern (e.g direction
that maps to the flexDirection
property inside of the flex
pattern config).
If using a config.jsxFramework
, Panda will also generate JSX patterns
, matching the function version. (e.g flex
and <Flex />
)
You can read more on customizing patterns and see the list of built-in patterns here
utility
With utilities
, you can create your own CSS properties that can leverage the same features as the css()
function: tokens
, conditions
, etc…
For example, one of our most requested feature is integrating Color opacity modifiers, so that you could do something like color: "red.200/50"
and it would change the alpha
value to 0.5
of the red.200
color.
It’s actually pretty easy to do so with a custom utility
:
There are other use cases for utilities
, like enum values
, mapped values
or even boolean values.
You can read more on customizing utilities and see the list of built-in utilities here
Debug utility
This is a built-in utility, included in the base preset, that you can use to debug your styles, it will add an outline
attribute to the element and all its children. Simple, but quite useful !
If you wonder how it works, here’s the full code of the debug
utility:
The debug utility is already in the built-in presets so you don’t need to add it manually !
Runtime token()
Panda CSS provides a token
function that you can use in your runtime JS code to reference a token value.
You can specify a fallback
argument that will be used if the token value is not found.
It also has a .var()
function that will return the token CSS variable instead of a value.
Compile-time string token()
And then there’s the string token
function, which is a compile-time version of the runtime token
function mentioned above.
Using the inline token
fn, you can also create composite values, like a border
that would be composed of a width
, style
and a color
.
And can also be used in at-rule
values, like @media
:
JSX style props
When using a JSX framework, any property matching the same name as your css()
function keys (which means any breakpoints
/ conditions
/ utility
/ shorthands
/ CSS built-in property) will be extracted by the static extractor and transformed to a class string.
The static extractor will extract every PascalCased
component, so that things “just work” out of the box.
You can use the
jsxStyleProps
config to customize which style props are available to your components:all
/minimal
(only thecss
property) /none
JSX css prop
The css
property is a special property that will always be extracted without the need for the .raw
marker. You can use it to dynamically merge styles together.
Since every PascalCased component will be extracted, as long as what you pass in the css
property remains statically analyzable, everything will work as expected without any effort.
.raw(xxx) merging
See raw()
Runtime conditions
See the first static extractor example or more examples in the docs.
CSS nesting
Panda supports CSS nesting, which means that you can use the &
syntax to target children and siblings.
Quoting the docs:
⚠️ We recommend not using descendant selectors as they can lead to specificity issues when managing style overrides. Colocating styles directly on the element is the preferred way of writing styles in Panda.
colorPalette
See virtual color
Theme
tokens
Tokens are at the core of the Panda CSS design system. They’re a way to define your design system values in a centralized place, and then reference them in your styles.
Design tokens in Panda are largely influenced by the W3C Token Format
They are grouped in predefined categories, the exhaustive list is: zIndex, opacity, colors, fonts, fontSizes, fontWeights, lineHeights, letterSpacings, sizes, shadows, spacing, radii, borders, durations, easings, animations, gradients, assets
- Each token will create a CSS variable
- You can nest tokens indefinitely
- Nested tokens can be used to create groups and will generate dot-separated names
Docs: https://panda-css.com/docs/theming/tokens
semantic tokens
Same as tokens but can reference other tokens.
Docs: https://panda-css.com/docs/theming/tokens#semantic-tokens
conditions
- You can use them with the
css
function,cva
,recipes
,patterns
,styled
factory, etc… nestable - Every condition starts with a
_
prefix to differentiate them - You can use a condition object or a property-based condition
- You can nest conditions indefinitely
- You can find the list of built-in conditions here.
Docs: https://panda-css.com/docs/concepts/conditional-styles
breakpoints
A special kind of conditions
that allows you to create responsive styles and directly maps to CSS @media
queries.
Docs: https://panda-css.com/docs/concepts/responsive-design
Docs: https://panda-css.com/docs/utilities/display#hiding-elements
textStyles
textStyles
are a practical way to compose styles for typography properties (fontSize
, fontWeight
, lineHeight
, letterSpacing
, etc…) under a single utility.
Docs: https://panda-css.com/docs/theming/text-styles
shorthands
Shorthands
are a way to create shorter names for properties that you use often. They are enabled by default in the config and the built-in presets
come with a few of them.
If you prefer not to use them, you can disable them by setting shorthands: false
in your config.
Docs: https://panda-css.com/docs/concepts/writing-styles#shorthand-properties
keyframes
Docs: https://panda-css.com/docs/customization/theme#keyframes
without surprise, will generate the following CSS:
CLI
Panda CLI, included when you install @pandacss/dev
, allows you to generate CSS in any project that has a panda.config.{js,ts,etc}
file.
Although the postcss plugin is very convenient, it’s not required to use Panda CSS. You can use the CLI to generate the CSS and runtime, and then use them in your project however you want.
CLI reference is here.
Here’s a quicky summary:
panda init
will help you get started with apanda.config.ts
, or can also be used if you don’t remember the@layer
orderpanda
will generate the CSS (from yourconfig.include
) + and lightweight runtime in yourconfig.outdir
, and watch for changes with the-w
or--watch
flag. It’s the same aspanda cssgen && panda codegen
panda cssgen
will only generate the CSS (from yourconfig.include
)panda cssgen [artifact]
, will only generate the CSS related to the givenartifact
, which can be one of:preflight
|tokens
|static
|global
|keyframes
panda cssgen --minimal
will only generate the CSS related to the style usage found in yourconfig.include
panda codegen
will generate the lightweight runtime in yourconfig.outdir
panda debug
will generate 1.css
file and 1.json
file for each of your source files, allowing you to see what was generated (css) and what was extracted (json) by file.panda ship
will generate 1.json
file that contains the summary of the style usage found from your source files. You can then use this.json
file in anyconfig.include
as if you had included the source files, which can be useful to distribute the CSS of a npm package using Panda without publishing the source files.
ℹ️ If you’re concerned about the performance of the postcss plugin, the CLI is a great alternative. We don’t have much control over how often the postcss plugin will be called, but we can control how many times we call the CLI. (e.g only when we need to)
Online Playground
We also have an online playground that you can use to try out Panda CSS using the basic examples and see if it fits your needs.
There’s also special tab named AST
at the bottom of the screen in which you can see exactly what the Panda extractor sees, which property and values were resolved, there’s also a CSS
tab what CSS will be generated from your code.
These are great tools to debug your code and understand how Panda works. You can also open your developer tools (F12) to see the Panda context (just like the one used in the CLI through @pandacss/node
) that handles the CSS and artifact generation.
Conclusion
I hope this post will help give more exposure to Panda CSS and its many features. I’m really excited to see what people will build with it and how it will evolve in the future.
I’m happy to answer any specific questions you have about Panda CSS. Feel free to @ me on Twitter or on Panda CSS discord.