---
title: Theming
description: Customize colors, radii, and light and dark themes with tokens.
group: Get Started
order: 4
---

Theme arctis/ui with CSS variables and semantic tokens.

```card
title: Want a visual starting point?
description: Soon, ui create will let you preview colors, radii, and fonts before adding a matching preset to your project. For now, the tokens below are the source of truth.
```

CSS variables are the recommended way to theme the components.

They provide semantic tokens such as `background`, `foreground`, and `primary`, which components use by default. Change a token in CSS and the UI follows, without rewriting classes across every component.

```tsx
<div className="bg-background text-foreground" />
```

Keep CSS variables enabled in your config. This is the default:

```json
// @file components.json
{
  "style": "ui",
  "rsc": true,
  "tailwind": {
    "css": "src/app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  }
}
```

Tailwind maps the tokens to utilities such as `bg-background`, `text-foreground`, and `border-border`.

For dark mode, override the same tokens under a `.dark` or `html.dark` selector. This documentation site uses the same pattern.

## Token convention

Tokens use background and foreground pairs. The base token defines the surface, while the `-foreground` token defines the text and icons placed on it.

The surface token omits the word `background`. For example, `primary` pairs with `primary-foreground`.

```css
--primary: #000000;
--primary-foreground: #ffffff;
```

Use the pair together:

```tsx
<div className="bg-primary text-primary-foreground">Hello</div>
```

For solid fills, use the pair (`bg-destructive text-destructive-foreground`). For softer surfaces, reuse the same color with opacity (`border-destructive/25 bg-destructive/5 text-destructive`).

Use `text-muted-foreground` for muted copy and `text-muted-foreground/50` for disabled or faint chrome.

## Theme tokens

Define these tokens in your global CSS under `:root` and `.dark`.

```tokens
```

## Radius scale

`--radius` is the base radius token. Derive a small scale from it to keep corners consistent from a single source of truth.

```css
// @file src/app/globals.css
@theme inline {
  --radius-sm: calc(var(--radius) * 0.6);
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) * 1.4);
}
```

Change `--radius` once, and every derived size updates with it.

## Adding new tokens

Define the variable in both `:root` and `.dark`, then expose it in `@theme inline`.

```css
// @file src/app/globals.css
:root {
  --info: #2563eb;
  --info-foreground: #ffffff;
}

.dark {
  --info: #60a5fa;
  --info-foreground: #000000;
}

@theme inline {
  --color-info: var(--info);
  --color-info-foreground: var(--info-foreground);
}
```

You can then use `bg-info` and `text-info-foreground` in your components.

## Default theme CSS

Use this starter scaffold as-is or adjust it to fit your project. It matches the neutral arctis/ui baseline used on this site.

```css
// @file src/app/globals.css
// @expand
@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-success: var(--success);
  --color-success-foreground: var(--success-foreground);
  --color-warning: var(--warning);
  --color-warning-foreground: var(--warning-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --radius-sm: calc(var(--radius) * 0.6);
  --radius-md: calc(var(--radius) * 0.8);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) * 1.4);
}

:root {
  --radius: 0.625rem;
  --background: #ffffff;
  --foreground: #000000;
  --card: var(--muted);
  --card-foreground: #000000;
  --popover: #ffffff;
  --popover-foreground: #000000;
  --primary: #000000;
  --primary-foreground: #ffffff;
  --secondary: #e4e4e7;
  --secondary-foreground: #000000;
  --muted: #f4f4f5;
  --muted-foreground: #71717a;
  --accent: #e4e4e7;
  --accent-foreground: #000000;
  --destructive: #dc2626;
  --destructive-foreground: #ffffff;
  --success: #059669;
  --success-foreground: #ffffff;
  --warning: #d97706;
  --warning-foreground: #ffffff;
  --border: #e4e4e7;
  --input: #e4e4e7;
  --ring: #a1a1aa;
}

.dark {
  --background: #000000;
  --foreground: #ffffff;
  --card: var(--muted);
  --card-foreground: #ffffff;
  --popover: #141414;
  --popover-foreground: #ffffff;
  --primary: #ffffff;
  --primary-foreground: #000000;
  --secondary: #1f1f1f;
  --secondary-foreground: #ffffff;
  --muted: #141414;
  --muted-foreground: #a1a1aa;
  --accent: #1f1f1f;
  --accent-foreground: #ffffff;
  --destructive: #ef4444;
  --destructive-foreground: #ffffff;
  --success: #34d399;
  --success-foreground: #000000;
  --warning: #fbbf24;
  --warning-foreground: #000000;
  --border: rgb(255 255 255 / 0.1);
  --input: rgb(255 255 255 / 0.15);
  --ring: #71717a;
}

@layer base {
  body {
    @apply bg-background text-foreground;
  }
}
```

## Without CSS variables

If you prefer utility colors, you can still use the components, but you will need to override classes more often. Theme tokens remain the recommended approach for dark mode and consistency.
