Build faster with Premium Chakra UI Components 💎
Learn moreNovember 19, 2025
Optimizing styling performance is crucial for maintaining smooth user experiences, especially in complex applications. This guide covers best practices for styling components in Chakra UI with a focus on performance.
Dynamic styling through inline CSS props can impact performance in several ways:
// ❌ Avoid: Dynamic styles recalculated on every render
const Component = ({ isActive, size }) => {
return (
<Box
padding={isActive ? "8" : "4"}
background={isActive ? "blue.500" : "gray.100"}
fontSize={size === "large" ? "xl" : "md"}
>
Content
</Box>
)
}Data attributes provide a performant way to handle state-based styling without dynamic CSS props. The styles are pre-compiled and don't change at runtime.
// ✅ Better: Use data attributes with static styles
const Component = ({ isActive, isDisabled }) => {
return (
<Box
data-active={isActive || undefined}
data-disabled={isDisabled || undefined}
css={{
padding: "4",
background: "gray.100",
fontSize: "md",
"&[data-active]": {
padding: "8",
background: "blue.500",
},
"&[data-disabled]": {
opacity: 0.5,
cursor: "not-allowed",
},
}}
>
Content
</Box>
)
}For truly dynamic values (like animations or user-controlled properties), use CSS variables instead of inline styles.
// ✅ Better: CSS variables for dynamic values
const ProgressBar = ({ progress }) => {
return (
<Box
style={{ "--progress": `${progress}%` }}
css={{
width: "100%",
height: "8px",
background: "gray.200",
"&::before": {
content: '""',
display: "block",
width: "var(--progress)",
height: "100%",
background: "blue.500",
transition: "width 0.3s ease",
},
}}
></Box>
)
}Recipes provide the most performant way to handle variant-based styling. All styles are pre-compiled and optimized at build time.
// ✅ Best: Use recipes for variants
import { createRecipeContext, defineRecipe } from "@chakra-ui/react"
const cardRecipe = defineRecipe({
className: "card",
base: {
padding: "4",
borderRadius: "md",
transition: "all 0.2s",
},
variants: {
variant: {
elevated: {
boxShadow: "md",
background: "white",
},
outline: {
borderWidth: "1px",
borderColor: "gray.200",
},
},
size: {
sm: { padding: "2" },
md: { padding: "4" },
lg: { padding: "6" },
},
isActive: {
true: {
borderColor: "blue.500",
background: "blue.50",
},
},
},
compoundVariants: [
{
variant: "elevated",
isActive: true,
css: {
boxShadow: "lg",
transform: "translateY(-2px)",
},
},
],
})
// Create component with recipe context
const { withContext } = createRecipeContext({ recipe: cardRecipe })
// Usage - variant props are passed directly
const Card = withContext<HTMLDivElement, CardProps>("div")
// In your app
const App = () => (
<Card variant="elevated" size="lg" isActive>
Content
</Card>
)For single dynamic values that don't fit into variants, use the style attribute sparingly with CSS variables.
// ✅ OK for one-off dynamic values
const CustomComponent = ({ rotation, scale }) => {
return (
<Box
transform="rotate(var(--rotation)) scale(var(--scale))"
transition="transform 0.3s ease"
style={{ "--rotation": `${rotation}deg`, "--scale": scale }}
>
Content
</Box>
)
}Before shipping your component, consider:
If your application requires absolute zero runtime CSS-in-JS overhead, consider using Panda CSS with Ark UI as an alternative stack:
Panda CSS is a build-time CSS-in-JS solution that
generates static CSS files with zero runtime overhead. You can use the
@chakra-ui/panda-preset to get all of Chakra UI's design tokens, recipes, and
patterns in a zero-runtime environment.
# Install dependencies
npm install -D @pandacss/dev @chakra-ui/panda-preset// panda.config.ts
import { defineConfig } from "@pandacss/dev"
export default defineConfig({
presets: ["@chakra-ui/panda-preset"],
include: ["./src/**/*.{js,jsx,ts,tsx}"],
outdir: "styled-system",
})// Use Chakra UI recipes with zero runtime
import { css } from "styled-system/css"
import { hstack, vstack } from "styled-system/patterns"
import { button, card } from "styled-system/recipes"
function App() {
return (
<div className={vstack({ gap: "4" })}>
<button className={button({ variant: "solid", size: "lg" })}>
Click me
</button>
<div className={card({ variant: "outline" })}>Card content</div>
</div>
)
}For unstyled, accessible components with zero runtime, combine Panda CSS with Ark UI:
import { Dialog } from "@ark-ui/react/dialog"
import { button, dialog } from "styled-system/recipes"
const styles = dialog({ size: "md" })
export const Modal = () => {
return (
<Dialog.Root>
<Dialog.Trigger className={button({ variant: "solid", size: "lg" })}>
Open
</Dialog.Trigger>
<Dialog.Positioner className={styles.positioner}>
<Dialog.Content className={styles.content}>
{/* Your content */}
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
)
}By following these patterns, you'll create applications that are not only fast but also maintainable and scalable. The key is to move styling logic from runtime to build time whenever possible.