> ## Documentation Index
> Fetch the complete documentation index at: https://pdfn.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Styling

> Style PDF templates with Tailwind CSS, custom stylesheets, or inline styles. Covers fonts, images, custom themes, and print CSS notes.

Pdfn supports three styling approaches. Choose based on your needs:

| Approach      | Install          | Best for                           |
| ------------- | ---------------- | ---------------------------------- |
| Tailwind CSS  | `@pdfn/tailwind` | Rapid development, utility classes |
| CSS prop      | Nothing extra    | Custom stylesheets, design systems |
| Inline styles | Nothing extra    | Simple templates, quick prototypes |

***

## Tailwind CSS

Install `@pdfn/tailwind`:

```bash theme={null}
npm install @pdfn/tailwind
```

Wrap your `Page` content with the `Tailwind` component:

```tsx theme={null}
import { Document, Page } from '@pdfn/react';
import { Tailwind } from '@pdfn/tailwind';

export default function Invoice() {
  return (
    <Document title="Invoice">
      <Tailwind>
        <Page size="A4" margin="1in">
          <h1 className="text-2xl font-bold text-blue-600">Invoice #001</h1>
          <p className="text-gray-600 mt-2">Thank you for your business.</p>
          <div className="mt-8 p-4 bg-gray-100 rounded-lg">
            <p className="text-xl font-bold">Total: $148.00</p>
          </div>
        </Page>
      </Tailwind>
    </Document>
  );
}
```

<Note>
  Place `Tailwind` inside `Document` but it can wrap one or more `Page` components.
</Note>

### Custom theme

Customize your PDF theme in `pdfn-templates/styles.css`. This file is auto-detected and isolated from your app's styles — your app and PDF templates never interfere with each other.

```css pdfn-templates/styles.css theme={null}
@import "tailwindcss";

@theme {
  --font-inter: "Inter", var(--font-sans);
  --color-brand: #007bff;
}
```

Use your custom values:

```tsx theme={null}
<h1 className="font-inter text-brand">Styled with custom theme</h1>
```

### Edge runtime (Vercel Edge, Cloudflare Workers)

Edge runtimes don't have filesystem access, so Tailwind must be pre-compiled at build time.

For Next.js:

```bash theme={null}
npm install @pdfn/next
```

```ts next.config.ts theme={null}
import { withPdfn } from '@pdfn/next';

const nextConfig = { /* your existing config */ };

export default withPdfn()(nextConfig);
```

For Vite:

```bash theme={null}
npm install @pdfn/vite
```

```ts vite.config.ts theme={null}
import { defineConfig } from 'vite';
import { pdfn } from '@pdfn/vite';

export default defineConfig({
  plugins: [pdfn()]
});
```

***

## CSS prop

Add custom CSS directly via the `css` prop on `Document`. No extra packages needed.

```tsx theme={null}
import { Document, Page } from '@pdfn/react';

export default function Invoice() {
  return (
    <Document
      title="Invoice"
      css={`
        .header {
          font-size: 24px;
          font-weight: bold;
          border-bottom: 2px solid #007bff;
          padding-bottom: 16px;
        }
        .total {
          font-size: 20px;
          font-weight: bold;
          background: #f5f5f5;
          padding: 16px;
          border-radius: 8px;
        }
      `}
    >
      <Page size="A4" margin="1in">
        <h1 className="header">Invoice #001</h1>
        <p className="total">Total: $148.00</p>
      </Page>
    </Document>
  );
}
```

***

## Inline styles

Use React's `style` prop for styling without extra dependencies:

```tsx theme={null}
import { Document, Page } from '@pdfn/react';

export default function Invoice() {
  return (
    <Document title="Invoice">
      <Page size="A4" margin="1in">
        <h1 style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 16 }}>
          Invoice #001
        </h1>
        <p style={{ color: '#666', lineHeight: 1.5 }}>
          Thank you for your business.
        </p>
      </Page>
    </Document>
  );
}
```

***

## Combining approaches

You can mix all three approaches. Styles are applied in this order (later wins):

1. Base pdfn styles
2. Tailwind CSS classes
3. Document `css` prop
4. Inline `style` prop

```tsx theme={null}
<Document css={`.highlight { background: yellow; }`}>
  <Tailwind>
    <Page>
      {/* Tailwind class */}
      <h1 className="text-2xl font-bold">Title</h1>

      {/* Custom CSS class */}
      <p className="highlight">Highlighted text</p>

      {/* Inline style (highest priority) */}
      <p style={{ color: 'red' }}>Red text</p>
    </Page>
  </Tailwind>
</Document>
```

***

## Fonts

Load custom fonts via the `fonts` prop on `Document`. Pdfn supports Google Fonts and local font files.

### Google Fonts

Pass font names as strings, or configure weights and styles:

```tsx theme={null}
import { Document, Page } from '@pdfn/react';

// Simple — default weights (400, 500, 600, 700)
<Document fonts={["Inter", "Roboto Mono"]}>
  <Page size="A4">
    <h1 style={{ fontFamily: 'Inter' }}>Styled heading</h1>
    <code style={{ fontFamily: 'Roboto Mono' }}>console.log('hello')</code>
  </Page>
</Document>

// With specific weights
<Document fonts={[{ family: "Inter", weights: [400, 700] }]}>
```

| Field     | Type                   | Default                | Description                                |
| --------- | ---------------------- | ---------------------- | ------------------------------------------ |
| `family`  | `string`               | —                      | Font family name (must match Google Fonts) |
| `weights` | `number[]`             | `[400, 500, 600, 700]` | Font weights to include                    |
| `style`   | `"normal" \| "italic"` | `"normal"`             | Font style                                 |

### Local fonts

Embed custom font files directly. The font is base64-encoded into the PDF.

```tsx theme={null}
<Document fonts={[
  { family: "CustomFont", src: "./fonts/custom.woff2", weight: 400 },
  { family: "CustomFont", src: "./fonts/custom-bold.woff2", weight: 700 },
]}>
  <Page size="A4">
    <p style={{ fontFamily: 'CustomFont' }}>Custom font text</p>
  </Page>
</Document>
```

| Field    | Type                   | Default    | Description                                           |
| -------- | ---------------------- | ---------- | ----------------------------------------------------- |
| `family` | `string`               | —          | Font family name (use in CSS)                         |
| `src`    | `string`               | —          | Path to font file (`.woff2`, `.woff`, `.ttf`, `.otf`) |
| `weight` | `number`               | `400`      | Font weight                                           |
| `style`  | `"normal" \| "italic"` | `"normal"` | Font style                                            |

<Note>
  Local fonts require filesystem access and won't work on edge runtimes (Vercel Edge, Cloudflare Workers). Use Google Fonts for edge compatibility.
</Note>

***

## Images

Images must be accessible when the PDF is generated. Since pdfn Cloud renders on remote servers, local filesystem paths won't work in production.

### Next.js public folder

Put images in your `public/` folder and reference them with absolute URLs. These deploy with your app and work everywhere.

```tsx theme={null}
function Invoice() {
  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000';

  return (
    <Document title="Invoice">
      <Page size="A4">
        <img src={`${baseUrl}/logo.png`} alt="Company logo" />
      </Page>
    </Document>
  );
}
```

### CDN-hosted images

For large assets or images shared across projects, host them on a CDN (Cloudflare R2, AWS S3, Vercel Blob).

```tsx theme={null}
<img src="https://cdn.example.com/assets/logo.png" alt="Company logo" />
```

### Base64 data URLs

For small images like logos or icons (under 10KB), embed them directly.

```tsx theme={null}
const logo = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...';

function Invoice() {
  return (
    <Document title="Invoice">
      <Page size="A4">
        <img src={logo} alt="Company logo" />
      </Page>
    </Document>
  );
}
```

<Note>
  Local image paths (like `./images/logo.png`) work during development but fail in production. Always use absolute URLs or base64.
</Note>

***

## PDF-specific CSS notes

Some CSS properties behave differently in PDFs:

| Property          | Behavior                                      |
| ----------------- | --------------------------------------------- |
| Flexbox & Grid    | Fully supported                               |
| `box-shadow`      | Works, but avoid blur > 10px (slow rendering) |
| `position: fixed` | Behaves like `absolute` (no viewport in PDFs) |
| `vh` / `vw` units | Relative to page size, not browser viewport   |
| `@media print`    | Respected — use for PDF-specific styles       |

***

## Next steps

<CardGroup cols={2}>
  <Card title="Components" icon="cube" href="/components">
    Document, Page, and layout components
  </Card>

  <Card title="Next.js" icon="code" href="/nextjs">
    API routes, download buttons, and edge runtime
  </Card>
</CardGroup>
