How to Override Astryx Component Styles Using Tailwind or Custom CSS
You can override Astryx component styles by passing Tailwind utility classes or custom CSS class names to the className prop, which gets merged with internal StyleX-generated classes and rendered on the final DOM element.
Astryx is a React component library built by Meta that uses StyleX for its internal styling architecture. Despite being powered by StyleX, every component in the facebook/astryx repository exposes a standard className prop that accepts any string, allowing you to override Astryx component styles using Tailwind or custom CSS without forking the library or wrapping components.
How the className Prop Works in Astryx
Astryx components are designed with styling flexibility in mind. The library intentionally avoids style lock-in by forwarding your className values directly to the rendered DOM elements alongside its internal StyleX-generated classes.
Prop Definition and Type Safety
In packages/core/src/Button/Button.tsx, the Button component defines className as an optional string prop:
// Lines 55-57 in Button.tsx
interface ButtonProps {
className?: string;
// ... other props
}
This type definition appears consistently across all Astryx components, ensuring TypeScript safety while allowing arbitrary class names.
StyleX Class Merging Logic
The internal implementation uses mergeProps to combine your overrides with the component's default styles. In packages/core/src/Button/Button.tsx (lines 52-57), the component merges the provided className with StyleX-generated classes via themeProps:
// Internal merging logic
const mergedProps = mergeProps(themeProps, {
className: props.className
});
This merging strategy places your custom classes after the StyleX classes in the final HTML output, ensuring your styles take precedence in the CSS cascade.
Overriding Styles with Tailwind CSS
Because Astryx renders your className value directly to the DOM, you can apply Tailwind utilities exactly as you would on a native HTML element. The Tailwind classes appear after StyleX classes in the class attribute, giving them higher specificity in the cascade.
import {Button} from '@astryxdesign/core'
export function MyPage() {
return (
<Button
label="Save"
variant="primary"
className="rounded-xl bg-purple-600 hover:bg-purple-700 text-white"
/>
)
}
In this example, rounded-xl and bg-purple-600 override the default border radius and background color defined by the component's internal StyleX tokens.
Using Custom CSS Classes
For complex overrides or when integrating with existing CSS modules, pass a custom class name defined in your stylesheet:
.my-custom-btn {
background-color: #ffcc00 !important;
color: #222 !important;
}
Component usage:
import {Button} from '@astryxdesign/core'
import './my-button.css'
export function MyPage() {
return (
<Button
label="Download"
variant="secondary"
className="my-custom-btn"
/>
)
}
Using !important ensures your custom properties win against StyleX's generated utility classes.
Combining Tailwind and Custom CSS
You can mix Tailwind utilities with custom class names for layered styling:
<Button
label="Create"
className="my-custom-btn py-2 px-4 md:py-3 md:px-6"
/>
Here, my-custom-btn handles color overrides while Tailwind utilities manage responsive spacing (py-2, md:py-3), demonstrating how to override Astryx component styles using both approaches simultaneously.
Applying Overrides to Other Components
The className prop pattern works consistently across the entire Astryx component library. For example, to override TextInput styles:
import {TextInput} from '@astryxdesign/core'
export function SearchBox() {
return (
<TextInput
placeholder="Search…"
className="border-2 border-green-500 focus:border-green-700"
/>
)
}
All Astryx components that forward className behave identically, as documented in the root README (line 18): "Override with className using Tailwind, CSS modules, or plain CSS".
Summary
- Standard prop API: Every Astryx component accepts a
className?: stringprop defined in files likepackages/core/src/Button/Button.tsx. - StyleX merging: Internal styles from StyleX are merged with your
classNameviamergePropsandthemeProps, placing your classes last in the DOM. - Tailwind compatible: Pass Tailwind utility classes directly to apply utility-first overrides without configuration changes.
- Custom CSS support: Reference external CSS files or CSS modules via
classNamefor complex design requirements. - No lock-in: The
facebook/astryxdesign system deliberately prevents style lock-in, allowing complete visual customization while maintaining the component's behavioral logic.
Frequently Asked Questions
Can I use CSS Modules with Astryx components?
Yes. Since className accepts any string, you can pass CSS Module references exactly as you would with standard React components. Import your module and pass the scoped class string to the className prop. The StyleX-generated classes will coexist with your CSS Module classes on the same element.
Do Tailwind classes always override Astryx's default styles?
Generally yes, because Astryx appends your className value after its internal StyleX classes in the final HTML output. However, for CSS properties defined with !important in the component's StyleX styles, you may need to use !important in your Tailwind classes (e.g., bg-red-500!) or custom CSS to ensure specificity.
Is there a performance penalty for using className overrides?
No. The className prop is processed at the same time as other props via mergeProps in packages/core/src/Button/Button.tsx. The merging operation is lightweight (simple string concatenation), and the final class string is passed directly to the DOM element without additional runtime overhead.
Can I override styles on nested elements within Astryx components?
The className prop applies to the root element only. For nested elements (like icons within a Button), you should use the specific props provided for that sub-element (e.g., iconClassName if available) or wrap the component in a custom container. Refer to the component's documentation in packages/core/src/*/*.doc.mjs files to see available override props for child elements.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →