> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/oven-sh/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# CSS Bundling

> Bun's built-in CSS bundler supports modern CSS features, syntax lowering for browser compatibility, and CSS Modules — no PostCSS or separate build tool required.

Bun has a built-in CSS bundler that handles `@import` statements, `url()` references, modern syntax lowering, vendor prefixing, and CSS Modules. It is a direct Rust→Zig port of [LightningCSS](https://lightningcss.dev/), with a bundling approach inspired by esbuild.

## Importing CSS

Import CSS files from JavaScript or TypeScript:

```typescript app.tsx theme={null}
import "./reset.css";
import "./styles.css";
```

During bundling, all imported CSS is combined into a single `.css` file in `outdir`. The `@import` statements and `url()` references in your CSS are processed and rebased automatically.

CSS can also be imported from HTML files (via `<link rel="stylesheet">`), which is the most common pattern when using the [fullstack dev server](/bundler/fullstack).

## Default browser targets

Bun's CSS bundler targets the following browsers by default:

* Chrome 87+
* Firefox 78+
* Safari 14+
* Edge 88+

Modern CSS that isn't supported in these targets is automatically lowered to compatible equivalents.

## Syntax lowering

### Nesting

CSS nesting is automatically flattened for browser compatibility:

<CodeGroup>
  ```css input (styles.css) theme={null}
  .card {
    background: white;
    border-radius: 4px;

    .title {
      font-size: 1.2rem;
      font-weight: bold;
    }

    @media (min-width: 768px) {
      display: flex;
    }
  }
  ```

  ```css output theme={null}
  .card {
    background: white;
    border-radius: 4px;
  }

  .card .title {
    font-size: 1.2rem;
    font-weight: bold;
  }

  @media (min-width: 768px) {
    .card {
      display: flex;
    }
  }
  ```
</CodeGroup>

### Custom properties (CSS variables)

CSS variables work as-is — no special configuration needed. Bun's bundler does not transform them, since they are widely supported and their runtime behavior cannot be replicated at build time.

```css theme={null}
:root {
  --primary: #2563eb;
  --spacing-md: 1rem;
}

.button {
  background-color: var(--primary);
  padding: var(--spacing-md);
}
```

### Modern color functions

Bun evaluates `color-mix()`, relative color syntax, LAB/LCH/OKLAB/OKLCH, and HWB colors at build time when all values are constants, and generates browser-compatible fallbacks.

<CodeGroup>
  ```css input theme={null}
  .button {
    background-color: color-mix(in srgb, blue 30%, red);
    color: lab(55% 78 35);
  }

  .theme {
    --accent: oklch(from purple calc(l + 15%) c h);
  }
  ```

  ```css output theme={null}
  .button {
    background-color: #b31a1a;
    color: #ff0f52;
    color: color(display-p3 1 0.12 0.37);
    color: lab(55% 78 35);
  }

  .theme {
    --accent: lch(69.32% 58.34 328.37);
  }
  ```
</CodeGroup>

### `light-dark()` function

The `light-dark()` function is automatically lowered to a `@media (prefers-color-scheme)` equivalent:

<CodeGroup>
  ```css input theme={null}
  :root {
    color-scheme: light dark;
  }

  .card {
    background-color: light-dark(#ffffff, #121212);
    color: light-dark(#333333, #eeeeee);
  }
  ```

  ```css output theme={null}
  :root {
    --lightningcss-light: initial;
    --lightningcss-dark: ;
    color-scheme: light dark;
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --lightningcss-light: ;
      --lightningcss-dark: initial;
    }
  }

  .card {
    background-color: var(--lightningcss-light, #ffffff) var(--lightningcss-dark, #121212);
    color: var(--lightningcss-light, #333333) var(--lightningcss-dark, #eeeeee);
  }
  ```
</CodeGroup>

### Media query ranges

Range syntax in media queries is converted to `min-width`/`max-width` equivalents:

<CodeGroup>
  ```css input theme={null}
  @media (width >= 768px) {
    .container { max-width: 720px; }
  }

  @media (768px <= width <= 1199px) {
    .sidebar { display: flex; }
  }
  ```

  ```css output theme={null}
  @media (min-width: 768px) {
    .container { max-width: 720px; }
  }

  @media (min-width: 768px) and (max-width: 1199px) {
    .sidebar { display: flex; }
  }
  ```
</CodeGroup>

### Logical properties

Logical CSS properties are compiled to their physical equivalents with directional fallbacks:

```css theme={null}
/* Input */
.component {
  margin-inline-start: 1rem;
  padding-block: 1rem 2rem;
  inline-size: 80%;
}

/* Output */
.component:dir(ltr) {
  margin-left: 1rem;
  padding-top: 1rem;
  padding-bottom: 2rem;
  width: 80%;
}

.component:dir(rtl) {
  margin-right: 1rem;
  padding-top: 1rem;
  padding-bottom: 2rem;
  width: 80%;
}
```

### Math functions

CSS math functions like `round()`, `mod()`, `sin()`, `cos()`, `pow()`, and `sqrt()` are evaluated at build time when all operands are constants:

```css theme={null}
/* Input */
.element {
  padding: round(14.8px, 5px);
  transform: rotate(calc(sin(45deg) * 50deg));
}

/* Output */
.element {
  padding: 15px;
  transform: rotate(35.36deg);
}
```

### Modern shorthand properties

CSS shorthands like `place-items`, `place-content`, `overflow: hidden auto`, and `display: inline flex` are expanded to longhands for older browsers:

```css theme={null}
/* Input */
.container {
  place-items: center start;
  overflow: hidden auto;
}

/* Output */
.container {
  align-items: center;
  justify-items: start;
  overflow-x: hidden;
  overflow-y: auto;
}
```

### `system-ui` font

`system-ui` is expanded to a comprehensive cross-platform font stack:

```css theme={null}
/* Input */
body { font-family: system-ui, sans-serif; }

/* Output */
body {
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
```

## CSS Modules

CSS Modules scope class names to the file to prevent collisions.

Create a file with the `.module.css` extension:

```css styles.module.css theme={null}
.button {
  color: red;
}

.container {
  padding: 1rem;
}
```

Import it in TypeScript/TSX:

```tsx app.tsx theme={null}
import styles from "./styles.module.css";

export function App() {
  return (
    <div className={styles.container}>
      <button className={styles.button}>Click me</button>
    </div>
  );
}
```

The imported `styles` object maps original class names to scoped unique identifiers:

```typescript theme={null}
console.log(styles.button);    // => "button_abc123"
console.log(styles.container); // => "container_abc123"
```

### Composition

CSS Modules support `composes` to reuse styles across classes:

```css styles.module.css theme={null}
.background {
  background-color: blue;
}

.button {
  composes: background;
  color: red;
}
```

You can also compose from a separate CSS module file:

```css button.module.css theme={null}
.button {
  composes: background from "./background.module.css";
  color: red;
}
```

<Info>
  Composition rules: the `composes` property must come before any regular CSS properties, and can only be used on simple class selectors.
</Info>

<Warning>
  When composing from separate files, avoid conflicting properties between the composed classes — the CSS Modules spec leaves the order of conflicting properties undefined.
</Warning>

## PostCSS not required

Bun's CSS bundler handles the features most commonly added via PostCSS plugins:

| Feature            | PostCSS plugin         | Bun      |
| ------------------ | ---------------------- | -------- |
| Vendor prefixes    | `autoprefixer`         | Built-in |
| CSS nesting        | `postcss-nesting`      | Built-in |
| Modern colors      | `postcss-color-*`      | Built-in |
| Media query ranges | `postcss-media-minmax` | Built-in |
| Logical properties | `postcss-logical`      | Built-in |
| CSS Modules        | `postcss-modules`      | Built-in |

<Note>
  PostCSS is not run by Bun's bundler. If you rely on PostCSS plugins not covered by Bun's built-in transforms, you can add a plugin via the bundler plugin API or use TailwindCSS's `bun-plugin-tailwind`.
</Note>

## TailwindCSS

Use TailwindCSS with the official Bun plugin:

```bash theme={null}
bun add tailwindcss bun-plugin-tailwind
```

```toml bunfig.toml theme={null}
[serve.static]
plugins = ["bun-plugin-tailwind"]
```

```html index.html theme={null}
<link rel="stylesheet" href="tailwindcss" />
```

Or import it in CSS:

```css styles.css theme={null}
@import "tailwindcss";

.custom {
  @apply bg-blue-500 text-white;
}
```
