---
title: "Theme Styles and CSS"
description: "Fumadocs provides a comprehensive styling system built around Tailwind CSS, custom design tokens, and modular stylesheets that configure layouts, typography, and code blocks across base-ui and radi..."
last_updated: "2026-10-12T07:53:59.981993+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/ui-layouts/theme-styles-and-css"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/base-ui/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/preset.css)
- [packages/radix-ui/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset.css)
- [packages/radix-ui/css/vitepress.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/vitepress.css)
- [packages/base-ui/css/vitepress.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/vitepress.css)
- [packages/tailwind/src/typography/styles.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/styles.ts)
- [packages/shadcn/src/manual-installation.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/shadcn/src/manual-installation.ts)
- [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts)
- [packages/preview/src/styles/globals.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/src/styles/globals.css)
- [packages/radix-ui/css/preset-legacy.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset-legacy.css)
- [packages/openapi/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/css/preset.css)
- [packages/base-ui/css/style.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/style.css)
- [packages/radix-ui/css/style.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/style.css)
- [packages/api-docs/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/css/preset.css)
- [packages/base-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/solar.css)
- [packages/preview/src/pages/_root.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/src/pages/_root.tsx)
- [packages/radix-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css)
- [packages/asyncapi/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/css/preset.css)
- [packages/radix-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/catppuccin.css)
- [packages/base-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/shadcn.css)
- [packages/python/styles/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/python/styles/preset.css)
- [packages/radix-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/shadcn.css)
- [packages/radix-ui/css/lib/shiki.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css)
- [packages/base-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/catppuccin.css)
- [packages/base-ui/css/lib/shiki.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/shiki.css)
- [packages/preview/waku.config.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/waku.config.ts)
- [packages/base-ui/tsdown.config.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/tsdown.config.ts)
- [packages/radix-ui/src/tailwind/typography.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/src/tailwind/typography.ts)
- [packages/base-ui/src/tailwind/typography.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/src/tailwind/typography.ts)
- [packages/radix-ui/css/ruby.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/ruby.css)
- [packages/base-ui/css/lib/base.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/base.css)
</details>

## Overview

Fumadocs provides a comprehensive styling system built around Tailwind CSS, custom design tokens, and modular stylesheets that configure layouts, typography, and code blocks across base-ui and radix-ui packages. This architecture bridges component primitives with preconfigured or custom theme variants such as Catppuccin, Shadcn, Vitepress, Solar, and Ruby.

Sources: [packages/base-ui/css/preset.css:1-11](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/preset.css#L1-L11), [packages/radix-ui/css/preset.css:1-11](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset.css#L1-L11), [packages/radix-ui/css/vitepress.css:1-40](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/vitepress.css#L1-L40), [packages/radix-ui/css/catppuccin.css:1-39](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/catppuccin.css#L1-L39), [packages/radix-ui/css/solar.css:1-16](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css#L1-L16), [packages/radix-ui/css/ruby.css:1-39](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/ruby.css#L1-L39), [packages/radix-ui/css/shadcn.css:1-21](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/shadcn.css#L1-L21)

## Preset Stylesheets and Base CSS

### Preset CSS Structures

The styling architecture relies on preset stylesheets located inside the `base-ui` and `radix-ui` packages [packages/base-ui/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/preset.css#L1-L11), [packages/radix-ui/css/preset.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset.css#L1-L11). Each preset consolidates base imports, typography plugins, and generated layout modules into a single entry point.

| Preset File | Primary Imports & Plugins | Layout / Generated Modules |
| :--- | :--- | :--- |
| `packages/base-ui/css/preset.css` | `./lib/base.css`, `./lib/shiki.css`, `../dist/tailwind/typography.js` | `flux.css`, `docs.css`, `home.css`, `notebook.css`, `shared.css` |
| `packages/radix-ui/css/preset.css` | `./lib/base.css`, `./lib/shiki.css`, `../dist/tailwind/typography.js` | `docs.css`, `home.css`, `notebook.css`, `flux.css`, `shared.css` |
| `packages/radix-ui/css/preset-legacy.css` | `./lib/base.css`, `./lib/shiki.css`, `../dist/tailwind/typography.js` | `docs.css`, `home.css`, `notebook.css`, `flux.css`, `shared.css`, legacy theme block |

Sources: [packages/base-ui/css/preset.css:1-11](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/preset.css#L1-L11), [packages/radix-ui/css/preset.css:1-11](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset.css#L1-L11), [packages/radix-ui/css/preset-legacy.css:1-22](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset-legacy.css#L1-L22)

### Base CSS Primitives and Animation Keyframes

The core imported primitives in `packages/base-ui/css/lib/base.css` define direction-aware drawer offsets, theme variables, and custom animation keyframes [packages/base-ui/css/lib/base.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/base.css#L1-L85). 

```css
@theme {
  --animate-fd-fade-in: fd-fade-in 300ms ease;
  --animate-fd-fade-out: fd-fade-out 300ms ease;

  --animate-fd-dialog-in: fd-dialog-in 300ms cubic-bezier(0.16, 1, 0.3, 1);
  --animate-fd-dialog-out: fd-dialog-out 300ms cubic-bezier(0.16, 1, 0.3, 1);

  --animate-fd-popover-in: fd-popover-in 100ms ease;
  --animate-fd-popover-out: fd-popover-out 100ms ease;

  --animate-fd-sidebar-in: fd-sidebar-in 250ms ease;
  --animate-fd-sidebar-out: fd-sidebar-out 250ms ease;

  @keyframes fd-sidebar-in {
    from {
      transform: translateX(var(--fd-sidebar-drawer-offset));
    }
  }

  @keyframes fd-sidebar-out {
    to {
      transform: translateX(var(--fd-sidebar-drawer-offset));
    }
  }

  @keyframes fd-dialog-in {
    from {
      transform: scale(1.06);
      opacity: 0;
    }
    to {
      transform: scale(1);
    }
  }

  @keyframes fd-dialog-out {
    from {
      transform: scale(1);
    }
    to {
      transform: scale(1.04);
      opacity: 0;
    }
  }

  @keyframes fd-popover-in {
    from {
      opacity: 0;
      transform: scale(0.9);
    }
  }

  @keyframes fd-popover-out {
    to {
      opacity: 0;
      transform: scale(0.9);
    }
  }

  @keyframes fd-fade-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  @keyframes fd-fade-out {
    from {
      opacity: 1;
    }
    to {
      opacity: 0;
    }
  }
}
```
Sources: [packages/base-ui/css/lib/base.css:9-85](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/base.css#L9-L85)

> [!NOTE]
> The sidebar drawer offset variable `--fd-sidebar-drawer-offset` switches dynamically between `100%` and `-100%` based on the document direction attribute `[dir='rtl']` to ensure slide transitions occur in the correct inline orientation.

Sources: [packages/base-ui/css/lib/base.css:1-8](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/base.css#L1-L8)

### Legacy Custom Theme Variables and Utilities

The legacy Radix UI preset provides specific theme tokens and utilities that define container widths, layout offsets, and custom scrollbar or step counters [packages/radix-ui/css/preset-legacy.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset-legacy.css#L13-L43), [packages/base-ui/css/lib/base.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/base.css#L102-L153).

```css
@theme {
  --spacing-fd-container: 1400px;
  --fd-page-width: 1200px;
  --fd-sidebar-width: 0px;
  --fd-toc-width: 0px;
  --fd-layout-width: 1600px;
  --fd-banner-height: 0px;
  --fd-nav-height: 0px;
  --fd-tocnav-height: 0px;
}

@layer base {
  :root,
  #nd-docs-layout {
    --fd-layout-offset: max(calc(50vw - var(--fd-layout-width) / 2), 0px);
  }
}

@utility container {
  margin-inline: auto;
  padding-inline: 1rem;

  @apply 2xl:max-w-(--spacing-fd-container);
}

/* Apply styles to :root */
@custom-variant on-root {
  :root:has(&) {
    @slot;
  }
}
```
Sources: [packages/radix-ui/css/preset-legacy.css:13-43](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset-legacy.css#L13-L43)

> [!WARNING]
> When using legacy layout definitions, the root layout offset calculation utilizes `calc(50vw - var(--fd-layout-width) / 2)`, clamping values at `0px` to handle wide-screen alignment correctly.

Sources: [packages/radix-ui/css/preset-legacy.css:24-29](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/preset-legacy.css#L24-L29)

## Theme Color Palettes

### Catppuccin Theme

The Catppuccin theme variant establishes distinct pastel and deep background color tokens inside both `packages/base-ui/css/catppuccin.css` and `packages/radix-ui/css/catppuccin.css` [packages/base-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/catppuccin.css#L1-L49), [packages/radix-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/catppuccin.css#L1-L49). Each variant imports `./lib/default-colors.css` and configures custom HSL color properties for both light mode (`@theme`) and dark mode (`.dark`) along with specialized sidebar variables [packages/base-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/catppuccin.css#L1-L49), [packages/radix-ui/css/catppuccin.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/catppuccin.css#L1-L49).

```css
@theme {
  --color-fd-popover: hsl(220, 22%, 92%);
  --color-fd-popover-foreground: hsl(234, 16%, 35%);
  --color-fd-secondary-foreground: hsl(234, 16%, 35%);
  --color-fd-border: hsl(223, 16%, 83%);
  --color-fd-primary: hsl(266, 85%, 58%);
  --color-fd-primary-foreground: hsl(220, 22%, 92%);
  --color-fd-muted: hsl(220, 22%, 92%);
  --color-fd-card: hsl(220, 22%, 92%);
  --color-fd-accent: hsl(223, 16%, 83%);
  --color-fd-accent-foreground: hsl(234, 16%, 35%);
  --color-fd-card-foreground: hsl(234, 16%, 35%);
  --color-fd-muted-foreground: hsl(233, 10%, 47%);
  --color-fd-foreground: hsl(234, 16%, 35%);
  --color-fd-secondary: hsl(220, 22%, 92%);
  --color-fd-background: hsl(220, 23%, 95%);
  --color-fd-ring: hsl(267, 84%, 81%);
}
```
Sources: [packages/base-ui/css/catppuccin.css:3-20](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/catppuccin.css#L3-L20)

> [!NOTE]
> In Catppuccin dark mode, `#nd-sidebar` overrides both `--color-fd-secondary` and `--color-fd-muted` to `hsl(237, 16%, 23%)`, matching the dark border and accent tone.

Sources: [packages/base-ui/css/catppuccin.css:46-49](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/catppuccin.css#L46-L49), [packages/radix-ui/css/catppuccin.css:46-49](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/catppuccin.css#L46-L49)

### Shadcn and Vitepress Themes

The Shadcn theme variant maps Fumadocs CSS variables directly to underlying `--background`, `--foreground`, `--muted`, `--popover`, `--card`, `--border`, `--primary`, `--secondary`, `--accent`, and `--ring` properties across `:root` and `.dark` selectors [packages/base-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/shadcn.css#L3-L21), [packages/radix-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/shadcn.css#L3-L21). Additionally, it configures `#nd-sidebar` bindings and declares a static theme variable `--color-fd-error: var(--destructive);` [packages/base-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/shadcn.css#L23-L36), [packages/radix-ui/css/shadcn.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/shadcn.css#L23-L36).

```css
#nd-sidebar {
  background-color: var(--sidebar);
  color: var(--sidebar-foreground);
  border-color: var(--sidebar-border);

  --color-fd-accent: var(--sidebar-accent);
  --color-fd-accent-foreground: var(--sidebar-accent-foreground);
  --color-fd-ring: var(--sidebar-ring);
  --color-fd-primary-foreground: var(--sidebar-primary-foreground);
}

@theme static {
  --color-fd-error: var(--destructive);
}
```
Sources: [packages/base-ui/css/shadcn.css:23-36](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/shadcn.css#L23-L36), [packages/radix-ui/css/shadcn.css:23-36](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/shadcn.css#L23-L36)

The Vitepress theme variant defines explicit neutral HSL values for light and dark modes, customizes prose links and code background color-mix styles, and modifies `#nd-sidebar` background colors [packages/base-ui/css/vitepress.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/vitepress.css#L3-L61), [packages/radix-ui/css/vitepress.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/vitepress.css#L3-L61).

```css
  --color-fd-background: hsl(0, 0%, 100%);
  --color-fd-card: hsl(0, 0%, 100%);
  --color-fd-foreground: hsl(240, 6%, 25%);
  --color-fd-muted-foreground: hsl(240, 6%, 50%);
  --color-fd-secondary: hsl(240, 6%, 97%);
  --color-fd-accent-foreground: hsl(240, 6%, 25%);
  --color-fd-primary: hsl(226, 55%, 45%);
}
```
Sources: [packages/base-ui/css/vitepress.css:14-21](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/vitepress.css#L14-L21), [packages/radix-ui/css/vitepress.css:14-21](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/vitepress.css#L14-L21)

### Solar and Ruby Themes

The Solar theme variant utilizes OKLCH color definitions for primary and article tokens alongside strict letter-spacing adjustments and responsive layout rules [packages/base-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/solar.css#L3-L16), [packages/radix-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css#L3-L16). Under `@variant md`, Solar injects absolute pseudo-elements before `#nd-page` with rounded borders, shadows, and margins for both `#nd-docs-layout` and `#nd-notebook-layout` [packages/base-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/solar.css#L18-L70), [packages/radix-ui/css/solar.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css#L18-L70).

```css
.dark {
  --color-fd-primary: oklch(0.902 0.0461 259.51);
  --color-fd-article: hsl(0, 0%, 7.04%);
  --color-fd-background: hsl(0, 0%, 5.04%);
}
```
Sources: [packages/base-ui/css/solar.css:12-16](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/solar.css#L12-L16), [packages/radix-ui/css/solar.css:12-16](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css#L12-L16)

The Ruby theme variant implements deep crimson, rose, and pink palettes tailored for light and dark environments [packages/radix-ui/css/ruby.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/ruby.css#L3-L39). It establishes primary colors using `hsl(348, 85%, 45%)` in light mode and `hsl(348, 90%, 62%)` in dark mode, with custom translucent border alphas set to `0.25` [packages/radix-ui/css/ruby.css](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/ruby.css#L3-L39).

```css
@theme {
  --color-fd-background: hsl(0, 0%, 98%);
  --color-fd-foreground: hsl(350, 45%, 14%);
  --color-fd-primary: hsl(348, 85%, 45%);
  --color-fd-primary-foreground: hsl(0, 0%, 100%);
  --color-fd-border: hsla(348, 40%, 60%, 0.25);
  --color-fd-ring: hsl(348, 85%, 45%);
  --color-fd-accent: hsl(348, 70%, 95%);
  --color-fd-accent-foreground: hsl(348, 70%, 22%);
  --color-fd-muted: hsl(0, 0%, 94%);
  --color-fd-muted-foreground: hsl(348, 25%, 42%);
  --color-fd-secondary: hsl(348, 55%, 92%);
  --color-fd-secondary-foreground: hsl(348, 50%, 20%);
  --color-fd-card: hsl(0, 0%, 100%);
  --color-fd-card-foreground: hsl(350, 45%, 14%);
  --color-fd-popover: hsl(0, 0%, 100%);
  --color-fd-popover-foreground: hsl(350, 45%, 14%);
}
```
Sources: [packages/radix-ui/css/ruby.css:3-20](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/ruby.css#L3-L20)

> [!CAUTION]
> When integrating the Solar theme, ensure that [table of contents](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/ui-layouts/table-of-contents) popover positioning rules calculate top offsets using `--fd-docs-row-1` or `--fd-docs-row-2` variables plus `2.5 * var(--spacing)`, or popover headers will detach from trigger elements.

Sources: [packages/base-ui/css/solar.css:34-68](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/solar.css#L34-L68), [packages/radix-ui/css/solar.css:34-68](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/solar.css#L34-L68)

## Tailwind Typography Plugin Engine

### Selector Manipulation and Scoping

The typography plugin architecture in `packages/tailwind` dynamically generates scoped prose component styles and custom Tailwind variants [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L149-L184). Built with Tailwind's `plugin.withOptions`, the plugin accepts an optional configuration object specifying a custom CSS class name (defaulting to `prose`) and a `disableRoundedTable` boolean flag [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L150-L150). It registers variants across a defined set of selectors using `addVariant` and injects component styles via `addComponents` [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L158-L182).

```typescript
export const typography: ReturnType<typeof plugin.withOptions<Options>> =
  plugin.withOptions<Options>(({ className = 'prose', ...styleOptions } = {}) => {
    return ({ addVariant, addComponents, ...rest }) => {
      const prefix = (rest as unknown as { prefix: Context['prefix'] }).prefix;

      for (const [name, ...values] of SELECTORS) {
        const selectors = values.length === 0 ? [name] : values;
        const selector = selectors.join(', ');

        addVariant(
          `${className}-${name}`,
          `& :is(${inWhere(selector, {
            prefix,
            className,
          })})`,
        );
      }

      addComponents({
        [`.${className}`]: configToCss(
          {
            ...styles.DEFAULT,
            css: [
              ...(styles.DEFAULT.css ?? []),
              styleOptions.disableRoundedTable ? styles.normalTable : styles.roundedTable,
            ],
          },
          {
            className,
            modifier: 'DEFAULT',
            prefix,
          },
        ),
      });
    };
  });
```
Sources: [packages/tailwind/src/typography/index.ts:149-184](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L149-L184)

Selector generation relies on `inWhere` and `commonTrailingPseudos` to construct robust CSS rules [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L21-L35), [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L68-L115). The `commonTrailingPseudos` function parses selectors with `postcss-selector-parser`, extracts pseudo-elements into a column-major 2D array, and hoists identical trailing pseudo elements to the end of the selector [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L68-L115). The `inWhere` wrapper wraps the selector in a `:where()` pseudo-class and appends a `:not(:where([class~="not-className"],[class~="not-className"] *))` exclusion to support nested unprose exceptions [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L21-L35).

```typescript
function inWhere(selector: string, { className, prefix, modifier }: Options & Context) {
  const prefixedNot = prefix(`.not-${className}`).slice(1);
  const selectorPrefix = selector.startsWith('>')
    ? `${modifier === 'DEFAULT' ? `.${className}` : `.${className}-${modifier}`} `
    : '';

  // Parse the selector, if every component ends in the same pseudo element(s) then move it to the end
  const [trailingPseudo, rebuiltSelector] = commonTrailingPseudos(selector);

  if (trailingPseudo) {
    return `:where(${selectorPrefix}${rebuiltSelector}):not(:where([class~="${prefixedNot}"],[class~="${prefixedNot}"] *))${trailingPseudo}`;
  }

  return `:where(${selectorPrefix}${selector}):not(:where([class~="${prefixedNot}"],[class~="${prefixedNot}"] *))`;
}
```
Sources: [packages/tailwind/src/typography/index.ts:21-35](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L21-L35)

The plugin registers variants for thirty distinct target identifiers using `SELECTORS` [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L117-L147), [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L154-L165).

| Variant Name | Target Elements / Selectors |
| :--- | :--- |
| `prose-headings` | `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `th` |
| `prose-h1` | `h1` |
| `prose-h2` | `h2` |
| `prose-h3` | `h3` |
| `prose-h4` | `h4` |
| `prose-h5` | `h5` |
| `prose-h6` | `h6` |
| `prose-p` | `p` |
| `prose-a` | `a` |
| `prose-blockquote` | `blockquote` |
| `prose-figure` | `figure` |
| `prose-figcaption` | `figcaption` |
| `prose-strong` | `strong` |
| `prose-em` | `em` |
| `prose-kbd` | `kbd` |
| `prose-code` | `code` |
| `prose-pre` | `pre` |
| `prose-ol` | `ol` |
| `prose-ul` | `ul` |
| `prose-li` | `li` |
| `prose-table` | `table` |
| `prose-thead` | `thead` |
| `prose-tr` | `tr` |
| `prose-th` | `th` |
| `prose-td` | `td` |
| `prose-img` | `img` |
| `prose-video` | `video` |
| `prose-hr` | `hr` |
| `prose-lead` | `[class~="lead"]` |

```typescript
const SELECTORS = [
  ['headings', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'th'],
  ['h1'],
  ['h2'],
  ['h3'],
  ['h4'],
  ['h5'],
  ['h6'],
  ['p'],
  ['a'],
  ['blockquote'],
  ['figure'],
  ['figcaption'],
  ['strong'],
  ['em'],
  ['kbd'],
  ['code'],
  ['pre'],
  ['ol'],
  ['ul'],
  ['li'],
  ['table'],
  ['thead'],
  ['tr'],
  ['th'],
  ['td'],
  ['img'],
  ['video'],
  ['hr'],
  ['lead', '[class~="lead"]'],
];
```
Sources: [packages/tailwind/src/typography/index.ts:117-147](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L117-L147)

### Calculated Styles and Tables

Calculated typographic styles use helper functions `round`, `rem`, and `em` defined in `packages/tailwind/src/typography/styles.ts` to convert pixel values into relative `rem` and `em` units [packages/tailwind/src/typography/styles.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/styles.ts#L1-L14). The engine merges default typography configurations with either `roundedTable` or `normalTable` based on the `disableRoundedTable` option [packages/tailwind/src/typography/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L167-L182). The `roundedTable` export configures separated borders, background colors using `var(--color-fd-card)`, border radii from `var(--radius-lg)`, and custom inline border start styles [packages/tailwind/src/typography/styles.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/styles.ts#L35-L72).

```typescript
export const roundedTable = {
  table: {
    borderCollapse: 'separate',
    borderSpacing: '0',
    background: 'var(--color-fd-card)',
    borderRadius: 'var(--radius-lg)',
    border: '1px solid var(--color-fd-border)',
    overflow: 'hidden',
  },
  th: {
    textAlign: 'start',
    padding: 'calc(var(--spacing) * 2.5)',
    'border-inline-start': '1px solid var(--color-fd-border)',
    background: 'var(--color-fd-muted)',
  },
  'th:first-child': {
    'border-inline-start': 'none',
  },
  'th:not(tr:last-child *), td:not(tr:last-child *)': {
    'border-bottom': '1px solid var(--color-fd-border)',
  },
  td: {
    textAlign: 'start',
    'border-inline-start': '1px solid var(--color-fd-border)',
    padding: 'calc(var(--spacing) * 2.5)',
  },
  'td:first-child': {
    'border-inline-start': 'none',
  },
  'tfoot th, tfoot td': {
    borderTopWidth: '1px',
    borderTopColor: 'var(--tw-prose-th-borders)',
  },
  'thead th, thead td': {
    borderBottomWidth: '1px',
    borderBottomColor: 'var(--tw-prose-th-borders)',
  },
};
```
Sources: [packages/tailwind/src/typography/styles.ts:35-72](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/styles.ts#L35-L72)

> [!NOTE]
> When `disableRoundedTable` is enabled, the plugin applies `normalTable` rules instead of `roundedTable`, setting explicit bottom borders on table headers and alternating body rows while omitting explicit card background wrappers.

Sources: [packages/tailwind/src/typography/index.ts:167-182](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/index.ts#L167-L182), [packages/tailwind/src/typography/styles.ts:74-113](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/tailwind/src/typography/styles.ts#L74-L113)

## Syntax Highlighting and Shiki Styling

### Shiki Theme Variables and Selectors

Fumadocs formats code blocks and inline code using Shiki via CSS stylesheets located in `packages/radix-ui/css/lib/shiki.css` and `packages/base-ui/css/lib/shiki.css`. The engine maps [syntax highlighting](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/core-architecture/syntax-highlighting) tokens to CSS variables for light and dark themes. For block-level code elements matching `.shiki:not(.not-fumadocs-codeblock *)`, token spans inherit `--shiki-light` colors and `--shiki-light-font-style` in light mode, while `.dark .shiki:not(.not-fumadocs-codeblock *)` selectors assign `--shiki-dark` colors and `--shiki-dark-font-style`. Inline code elements matching `code.shiki:not(.not-fumadocs-code *)` apply the identical theme variable mapping for both light and dark contexts.

```css
.shiki:not(.not-fumadocs-codeblock *) {
  --padding-left: calc(var(--spacing) * 4);
  --padding-right: calc(var(--spacing) * 4);

  code span {
    color: var(--shiki-light);
    font-style: var(--shiki-light-font-style);
  }
```
Sources: [packages/radix-ui/css/lib/shiki.css:1-8](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L1-L8), [packages/base-ui/css/lib/shiki.css:1-8](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/shiki.css#L1-L8)

```css
.dark .shiki:not(.not-fumadocs-codeblock *) {
  code span {
    color: var(--shiki-dark);
    font-style: var(--shiki-dark-font-style);
  }
}

/* inline code */
code.shiki:not(.not-fumadocs-code *) span {
  color: var(--shiki-light);
  font-style: var(--shiki-light-font-style);
}

.dark code.shiki:not(.not-fumadocs-code *) span {
  color: var(--shiki-dark);
  font-style: var(--shiki-dark-font-style);
}
```
Sources: [packages/radix-ui/css/lib/shiki.css:92-108](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L92-L108), [packages/base-ui/css/lib/shiki.css:92-108](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/shiki.css#L92-L108)

> [!NOTE]
> The `:not(.not-fumadocs-codeblock *)` and `:not(.not-fumadocs-code *)` exclusions prevent Shiki theme overrides from applying inside custom blocks that opt out of Fumadocs styling.

Sources: [packages/radix-ui/css/lib/shiki.css:1-1](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L1-L1), [packages/radix-ui/css/lib/shiki.css:100-100](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L100-L100)

### Line Decoration and Code Block Features

Code block layout is governed by variables setting padding-left and padding-right to 4 times the spacing scale (`--padding-left` and `--padding-right`). Empty code lines are forced to a height of `1lh`. Advanced features like line focus states, git diff markers, line highlights, and line numbers are implemented through specific CSS classes and pseudo-elements.

| Class Selector | Applied Styles & Variables | Purpose |
| :--- | :--- | :--- |
| `&.has-focused .line:not(.focused)` | `filter: blur(2px); transition: filter 200ms;` | Applies blur to non-focused lines when focus mode is active. |
| `&.has-focused:hover .line:not(.focused)` | `filter: blur(0);` | Clears blur when hovering over a code block with active focus lines. |
| `.diff.remove` | `--fd-counter-color: var(--color-fd-diff-remove-symbol); @apply bg-fd-diff-remove; opacity: 0.7;` | Styles deleted diff lines with background color and opacity. |
| `.diff.remove::before` | `content: '-'; @apply text-fd-diff-remove-symbol;` | Inserts the minus symbol before removed lines. |
| `.diff.add` | `--fd-counter-color: var(--color-fd-diff-add-symbol); @apply bg-fd-diff-add;` | Styles added diff lines with background color. |
| `.diff.add::before` | `content: '+'`; `@apply text-fd-diff-add-symbol;` | Inserts the plus symbol before added lines. |
| `.highlighted` | `--fd-counter-color: var(--color-fd-primary); @apply bg-fd-primary/10;` | Highlights entire code lines with primary theme tint. |
| `.highlighted::after` | `position: absolute; content: ''; @apply inset-y-0 left-0 border-l-2 border-fd-primary/50;` | Renders a left accent border on highlighted lines. |
| `.highlighted-word` | `padding: 1px; @apply border -my-px border-fd-primary/30 bg-fd-primary/10 rounded-md font-medium;` | Styles specific inline highlighted words within code spans. |

```css
.line {
  position: relative;
  padding-left: var(--padding-left);
  padding-right: var(--padding-right);
}

.line:empty {
  height: 1lh;
}

&.has-focused .line:not(.focused) {
  filter: blur(2px);
  transition: filter 200ms;
}

&.has-focused:hover .line:not(.focused) {
  filter: blur(0);
}

.diff::before {
  position: absolute;
  left: calc(var(--spacing) * 1.5);
}

.diff.remove {
  opacity: 0.7;
  --fd-counter-color: var(--color-fd-diff-remove-symbol);
  @apply bg-fd-diff-remove;
}

.diff.remove::before {
  content: '-';
  @apply text-fd-diff-remove-symbol;
}

.diff.add {
  --fd-counter-color: var(--color-fd-diff-add-symbol);
  @apply bg-fd-diff-add;
}

.diff.add::before {
  content: '+';
  @apply text-fd-diff-add-symbol;
}

.highlighted {
  --fd-counter-color: var(--color-fd-primary);
  @apply bg-fd-primary/10;
}

.highlighted::after {
  position: absolute;
  content: '';
  @apply inset-y-0 left-0 border-l-2 border-fd-primary/50;
}

.highlighted-word {
  padding: 1px;
  @apply border -my-px border-fd-primary/30 bg-fd-primary/10 rounded-md font-medium;
}
```
Sources: [packages/radix-ui/css/lib/shiki.css:10-69](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L10-L69), [packages/base-ui/css/lib/shiki.css:10-69](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/shiki.css#L10-L69)

When `data-line-numbers` is present on the container, line numbers are generated using CSS counters (`counter-increment: line`), positioning counter values inside a 7-space left column with a color mixed in oklab between `--fd-counter-color` and transparent.

```css

  &[data-line-numbers] .twoslash-meta-line {
    padding-left: calc(var(--padding-left) + 7 * var(--spacing));
  }

  &[data-line-numbers] .line {
    counter-increment: line;
    padding-left: calc(var(--padding-left) + 7 * var(--spacing));
  }

  &[data-line-numbers] .line::after {
    position: absolute;
    content: counter(line);
    color: color-mix(
      in oklab,
      var(--fd-counter-color, var(--color-fd-muted-foreground)) 60%,
      transparent
    );
    @apply inset-y-0 left-0 w-7 text-right;
  }
}
```
Sources: [packages/radix-ui/css/lib/shiki.css:70-90](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/lib/shiki.css#L70-L90), [packages/base-ui/css/lib/shiki.css:70-90](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/lib/shiki.css#L70-L90)

## Specialized Extension Stylesheets

### OpenAPI, AsyncAPI, and API Documentation Presets

Supplementary preset stylesheets configure styling rules for API documentation packages by importing shared base definitions and companion package styles. The OpenAPI preset (`packages/openapi/css/preset.css`) imports `./generated/shared.css` and `@import '@fumadocs/api-docs/css/preset.css'`. Similarly, the AsyncAPI preset (`packages/asyncapi/css/preset.css`) imports `./generated/shared.css` and `@import '@fumadocs/api-docs/css/preset.css'`. The core API docs preset (`packages/api-docs/css/preset.css`) imports only `./generated/shared.css`.

```css
@import './generated/shared.css';
@import '@fumadocs/api-docs/css/preset.css';
```
Sources: [packages/openapi/css/preset.css:1-2](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/css/preset.css#L1-L2), [packages/api-docs/css/preset.css:1-1](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/css/preset.css#L1-L1), [packages/asyncapi/css/preset.css:1-2](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/css/preset.css#L1-L2)

> [!NOTE]
> Both OpenAPI and AsyncAPI stylesheets reuse `@fumadocs/api-docs/css/preset.css`, ensuring uniform presentation across all API specification rendering packages.

Sources: [packages/openapi/css/preset.css:2-2](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/css/preset.css#L2-L2), [packages/asyncapi/css/preset.css:2-2](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/css/preset.css#L2-L2)

### Python Module Theme Configuration

The Python module preset (`packages/python/styles/preset.css`) sets up Tailwind scanning paths and defines custom inline theme variables for Python syntax elements. It scans distribution output files via `@source '../dist/**/*.js'` and configures color variables inside an `@theme inline` block.

| Theme Variable | Value | Purpose |
| :--- | :--- | :--- |
| `--color-fdpy-func` | `oklch(79.2% 0.209 151.711)` | Defines the color token for Python functions. |
| `--color-fdpy-class` | `red` | Defines the color token for Python classes. |
| `--color-fdpy-attribute` | `oklch(74% 0.238 322.16)` | Defines the color token for Python attributes. |
| `--color-fdpy-method` | `blue` | Defines the color token for Python methods. |

```css
@source '../dist/**/*.js';

@theme inline {
  --color-fdpy-func: oklch(79.2% 0.209 151.711);
  --color-fdpy-class: red;
  --color-fdpy-attribute: oklch(74% 0.238 322.16);
  --color-fdpy-method: blue;
}
```
Sources: [packages/python/styles/preset.css:1-8](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/python/styles/preset.css#L1-L8)

## Tailwind V4 Integration and Bundling

### Global Style Entry Points and Imports

Tailwind CSS v4 integration across Fumadocs relies on `@import 'tailwindcss'` statements coupled with layout presets and neutralization layers. The preview package style entry point (`packages/preview/src/styles/globals.css`) imports Tailwind alongside neutral and preset configurations.

```css
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
```
Sources: [packages/preview/src/styles/globals.css:1-3](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/src/styles/globals.css#L1-L3)

Both `packages/base-ui/css/style.css` and `packages/radix-ui/css/style.css` follow an identical import structure while additionally defining a base layer rule that configures the body element for flex column layout with a minimum height spanning the viewport.

```css
@import 'tailwindcss';
@import './neutral.css';
@import './preset.css';

@layer base {
  body {
    @apply flex flex-col min-h-screen;
  }
}
```
Sources: [packages/base-ui/css/style.css:1-9](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/css/style.css#L1-L9), [packages/radix-ui/css/style.css:1-9](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/css/style.css#L1-L9)

> [!NOTE]
> The root application layout (`packages/preview/src/pages/_root.tsx`) imports `globals.css` and attaches the identical flex column layout utility classes directly to the body element alongside hydration warning suppressions.

Sources: [packages/preview/src/pages/_root.tsx:3-11](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/src/pages/_root.tsx#L3-L11)

### Vite and Waku Configuration

Build tooling for the preview package is handled via Waku configuration (`packages/preview/waku.config.ts`), which integrates Vite plugins including `@tailwindcss/vite` and an internal Fumadocs configuration loader.

```typescript
vite: {
  resolve: {
    tsconfigPaths: true,
  },

  plugins: [
    tailwindcss(),
    {
      name: 'internal',
      config() {
        return getConfig({ root: process.cwd() });
      },
    },
  ],
},
```
Sources: [packages/preview/waku.config.ts:7-21](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/preview/waku.config.ts#L7-L21)

### Oxide Scanner and Dynamic CSS Compilation

The `tsdown` build configuration for `packages/base-ui/tsdown.config.ts` incorporates `@tailwindcss/oxide` via a programmatic `Scanner` implementation in `compileInline()`. This scanner extracts utility names from source code patterns and generates layout-specific inline source stylesheets inside `css/generated/`.

```typescript
export async function compileInline() {
  await mkdir('css/generated', { recursive: true });
  const scanner = new Scanner({
    sources: [
      {
        base: path.resolve('src'),
        pattern: 'components/**/*.{ts,tsx}',
        negated: false,
      },
      {
        base: path.resolve('src'),
        pattern: 'layouts/shared/**/*.{ts,tsx}',
        negated: false,
      },
      {
        base: path.resolve('src'),
        pattern: '*.{ts,tsx}',
        negated: false,
      },
    ],
  });

  const commonNames = scanner.scan();
  await writeFile('css/generated/shared.css', namesToFile(commonNames));

```
Sources: [packages/base-ui/tsdown.config.ts:50-74](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/tsdown.config.ts#L50-L74)

The compilation loop iterates through distinct layout identifiers (`flux`, `notebook`, `home`, and `docs`), filters out utilities already included in the shared scanner results, and writes out individual layout CSS files.

```typescript
  const layouts = ['flux', 'notebook', 'home', 'docs'];
  const commonNameSet = new Set(commonNames);

  for (const layout of layouts) {
    const scanner = new Scanner({
      sources: [
        {
          base: path.resolve('src'),
          pattern: `layouts/${layout}/**/*.{ts,tsx}`,
          negated: false,
        },
      ],
    });

    await writeFile(
      `css/generated/${layout}.css`,
      namesToFile(scanner.scan().filter((name) => !commonNameSet.has(name))),
    );
  }

  console.log('generated CSS files');
}
```
Sources: [packages/base-ui/tsdown.config.ts:75-96](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/tsdown.config.ts#L75-L96)

> [!CAUTION]
> The Oxide scanner explicitly excludes negated patterns and separates layout components so that shared utility names are compiled once into `shared.css` while layout-specific classes remain isolated in their respective generated files.

Sources: [packages/base-ui/tsdown.config.ts:52-70](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/tsdown.config.ts#L52-L70), [packages/base-ui/tsdown.config.ts:78-92](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/base-ui/tsdown.config.ts#L78-L92)

## Related

- [Base UI Components](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/ui-layouts/base-ui-components)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
