Centralizing Design with Chakra UI’s extendTheme and useStyleConfig: A Practical Guide
Learn how to define design tokens once with extendTheme, apply them to custom components via useStyleConfig, and leverage responsive style props in Chakra UI v2.0 for consistent, maintainable React apps.
12 Jul 2025, 13:10 UTC

The Problem
When a React project grows, component styles tend to become scattered. Each Button, Card, or FormField may declare its own colors, spacing, or variant logic, making the codebase hard to maintain and breaking design consistency. Chakra UI offers a way to centralize these decisions with extendTheme and to propagate them automatically to custom components via useStyleConfig.
Why Centralize with extendTheme
Chakra’s extendTheme is a function that merges a user‑supplied configuration object into the default theme. The resulting theme contains design tokens (colors, spacing, fonts) and component style overrides (size maps, variants, default props). By defining tokens once, you:
- Guarantee that all components use the same palette and spacing scale.
- Allow designers to change a color or spacing value in a single place and have the whole app update automatically.
- Reduce duplication: you no longer need to write
color="brand.500"in every component.
Example: extendTheme adds a new primary color and a custom breakpoint.
import { extendTheme } from "@chakra-ui/react";
const theme = extendTheme({
colors: {
brand: {
50: "#e3f2f9",
500: "#2c7be5",
900: "#1a5fb4",
},
},
breakpoints: {
sm: "30em",
md: "48em",
lg: "62em",
xl: "80em",
"2xl": "96em",
},
});
export default theme;
Wrap your app with ChakraProvider and pass the theme. All Chakra components will now see brand.500 as a valid color.
Using useStyleConfig for Custom Components
When you build a reusable component that should look like a Button or a Box, you can tap into Chakra’s component style system with useStyleConfig. The hook accepts a component name (matching the key in theme.components) and optional props, and returns a style object that you spread onto a Chakra primitive.
Consider a <Card> component that should inherit Button’s layout logic but has its own visual style.
import { Box, useStyleConfig } from "@chakra-ui/react";
export const Card = ({
variant = "solid",
size = "md",
children,
...rest
}) => {
const styles = useStyleConfig("Card", { variant, size });
return (
<Box __css={styles} {...rest}>
{children}
</Box>
);
};
In extendTheme, you would now specify the Card component’s style definitions:
const theme = extendTheme({
components: {
Card: {
baseStyle: {
borderRadius: "md",
boxShadow: "md",
p: 4,
},
sizes: {
sm: { p: 2 },
md: { p: 4 },
lg: { p: 6 },
},
variants: {
solid: { bg: "brand.50" },
outline: { bg: "white", border: "1px solid", borderColor: "brand.500" },
},
defaultProps: {
variant: "solid",
size: "md",
},
},
},
});
Now every <Card> automatically adopts the consistent spacing, variant colors, and responsive sizes defined in the theme. If you later change Card.baseStyle.p, all cards update.
Responsive Style Props in Action
Chakra’s style props accept objects or arrays to specify values per breakpoint. The keys must match the theme’s breakpoint names.
Example: a <Box> that has padding of 2 on small screens and 6 on medium and larger.
import { Box } from "@chakra-ui/react";
const ResponsiveBox = () => (
<Box p={{ base: 2, md: 6 }} bg="brand.50">Responsive Padding</Box>
);
When you resize the viewport across the md breakpoint (48em), the padding changes. You can verify this by inspecting the computed style in DevTools.
Trade‑offs and Limitations
- Version Mismatch:
extendThemeanduseStyleConfigsignatures differ between Chakra v2 and v3. Always checknpm ls @chakra-ui/reactto confirm the major version before copying examples. - Breakpoint Consistency: Adding custom breakpoints requires that every responsive object uses the exact names defined in the theme. A typo like
md:vsmd:will silently fall back tobase. - Undefined Style Config: If you pass an unknown component name to
useStyleConfig, the hook returnsundefinedinstead of throwing. This can lead to unstyled components if you misspell the key. - SSR Hydration: When server‑side rendering, the theme context must be hydrated on the client. If you toggle the color mode or lazy‑load the theme, you may see a flash of unstyled content.
- Bundle Size: Importing the entire theme object can increase bundle size if you include many unused component overrides. Consider splitting the theme or using
createBreakpointsto keep it lean.
How to Verify Your Theme
- Run
npm ls @chakra-ui/reactand confirm you’re on v2.x or v3.x. - In the browser, open DevTools and inspect a component that uses a theme token (e.g.,
bg="brand.500"). The computed background color should match the value defined inextendTheme. - Resize the viewport and verify that responsive props generate the expected media queries. Look for CSS rules like
@media (min-width: 48em). - Use
useBreakpointValuein a test component to confirm it returns the correct breakpoint name as you resize.
Takeaway
By defining a single, well‑structured theme with extendTheme and letting custom components consume it with useStyleConfig, you keep your style logic DRY, maintainable, and in sync with your design system. Responsive style props give you fine‑grained control over layout without writing raw media queries. Just remember to check your Chakra version, keep breakpoint names consistent, and verify the theme in the browser before committing.
Next steps: experiment by adding a new component style to the theme, tweak the responsive breakpoints, and watch the changes propagate instantly. Happy theming!
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.