# How to Override Astryx Component Styles Using Tailwind or Custom CSS

> Easily override Astryx component styles with Tailwind or custom CSS. Learn how to apply your own className to customize Astryx elements for your project.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: how-to-guide
- Published: 2026-07-02

---

**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`](https://github.com/facebook/astryx/blob/main/packages/core/src/Button/Button.tsx), the Button component defines `className` as an optional string prop:

```typescript
// 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`](https://github.com/facebook/astryx/blob/main/packages/core/src/Button/Button.tsx) (lines 52-57), the component merges the provided `className` with StyleX-generated classes via `themeProps`:

```typescript
// 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.

```tsx
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-button.css`](https://github.com/facebook/astryx/blob/main/my-button.css)**

```css
.my-custom-btn {
  background-color: #ffcc00 !important;
  color: #222 !important;
}

```

**Component usage:**

```tsx
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:

```tsx
<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:

```tsx
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?: string` prop defined in files like [`packages/core/src/Button/Button.tsx`](https://github.com/facebook/astryx/blob/main/packages/core/src/Button/Button.tsx).
- **StyleX merging**: Internal styles from StyleX are merged with your `className` via `mergeProps` and `themeProps`, 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 `className` for complex design requirements.
- **No lock-in**: The `facebook/astryx` design 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`](https://github.com/facebook/astryx/blob/main/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.