> Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

---
title: Styling, Dark Mode & Responsive Variants
sidebarTitle: Styling & Variants
description: Customize sizing, colors, dark mode, responsive breakpoints, and localization for your exported Framer components.
icon: lucide:palette
---

# Styling & responsive variants

Exported Framer components accept standard React props like `className` and `style`. This page covers how to customize their appearance, use responsive variants, enable dark mode, and work with color styles and localization.

## Overriding styles

Framer components come with **generated CSS classes** for dimensions (fixed width, height, etc.). To override them, use `className` with `!important` or the `style` prop which has higher CSS specificity:

```tsx
import './framer/styles.css'
import Hero from './framer/hero'

export default function App() {
    return (
        <div>
            {/* className with !important */}
            <Hero className="!w-full !h-auto" />

            {/* style prop (higher specificity, no !important needed) */}
            <Hero style={{ width: '100%', height: 'auto' }} />
        </div>
    )
}
```

<Aside>
  <Tip>
    The `!important` is needed because Framer's generated classes have specific dimensions. The `style` prop is a cleaner alternative since it has higher specificity than class-based styles.
  </Tip>
</Aside>

## Responsive variants

If your Framer component uses **variants** placed inside differently sized frames (breakpoints), Unframer generates a `.Responsive` sub-component. It switches variants based on **CSS media queries**:

```tsx
import './framer/styles.css'
import Logos from './framer/logos'

export default function App() {
    return (
        <Logos.Responsive
            variants={{
                lg: 'Desktop',
                md: 'Tablet',
                base: 'Mobile',
            }}
        />
    )
}
```

The **variants prop is optional**. By default, Unframer generates the variant mapping automatically from your Framer breakpoints. Only pass `variants` if you want to override the defaults.

Under the hood, `.Responsive` renders all variants and uses CSS `display: none` to show only the active one. Before hydration, unused variants are removed via React's `useSyncExternalStore` for better performance.

## Dark mode

Unframer supports dark mode through the **`dark` CSS class**. Add it to any parent element and all color style variables automatically switch to their dark values:

```tsx
import './framer/styles.css'
import Hero from './framer/hero'

export default function App() {
    return (
        <div className="dark">
            <Hero />
        </div>
    )
}
```

This is the same pattern **Tailwind CSS** uses. If your app already toggles a `dark` class on `<html>` or `<body>`, Framer components will follow automatically.

## Color styles as CSS variables

Unframer exports all your Framer **color styles** as CSS variables prefixed with `--unframer-`. These are defined in `styles.css`:

```css
:root {
    --unframer-primary: rgb(231, 34, 8);
    --unframer-white: rgb(255, 255, 255);
    --unframer-off-black: rgb(16, 16, 16);
}

.dark {
    --unframer-primary: rgb(231, 34, 8);
    --unframer-white: rgb(16, 16, 16);
    --unframer-off-black: rgb(255, 255, 255);
}
```

You can reference these variables in your own styles, including **Tailwind**:

```tsx
<div className="bg-(--unframer-primary) text-(--unframer-white)">
    Styled with Framer color tokens
</div>
```

## Localization

If your Framer project has **locales** configured, pass the `locale` prop to render component text in a specific language:

```tsx
import Hero from './framer/hero'

<Hero locale="de" />
<Hero locale="it-IT" />
<Hero locale="ja" />
```

To set locale **globally** for all components, wrap your app with `UnframerProvider`:

```tsx
import { UnframerProvider } from 'unframer'

export function Providers({ children }: { children: React.ReactNode }) {
    return (
        <UnframerProvider locale="de">
            {children}
        </UnframerProvider>
    )
}
```

## Client-side navigation

By default, links inside Framer components trigger **full page refreshes**. If you use a framework like Next.js or react-router, pass a `navigate` function to use client-side routing instead:

```tsx
import { useRouter } from 'next/navigation'
import { UnframerProvider } from 'unframer'

export function Providers({ children }: { children: React.ReactNode }) {
    const router = useRouter()

    return (
        <UnframerProvider navigate={router.push}>
            {children}
        </UnframerProvider>
    )
}
```

All Framer components under the provider will use this function for **relative links**, giving you instant page transitions without losing Framer's link behavior.

<Aside>
  <Note>
    For react-router, use `useNavigate()` instead of `useRouter()`. The API is the same: pass the navigate function to `UnframerProvider`.
  </Note>
</Aside>
