|
| 1 | +--- |
| 2 | +title: 'Tailwind' |
| 3 | +--- |
| 4 | + |
| 5 | +The `@react-pdf/tailwind` package converts a compatible subset of the Tailwind CSS class syntax into style objects that react-pdf understands. |
| 6 | + |
| 7 | +## Installation |
| 8 | + |
| 9 | +```bash |
| 10 | +npm install @react-pdf/tailwind |
| 11 | +``` |
| 12 | + |
| 13 | +## Usage |
| 14 | + |
| 15 | +```jsx |
| 16 | +import { Document, Page, Text, View } from '@react-pdf/renderer'; |
| 17 | +import { createTw } from '@react-pdf/tailwind'; |
| 18 | + |
| 19 | +// Apply your own styles on top of Tailwind defaults |
| 20 | +const tw = createTw({ |
| 21 | + fontFamily: { |
| 22 | + sans: ['Papyrus'], |
| 23 | + }, |
| 24 | + colors: { |
| 25 | + custom: '#bada55', |
| 26 | + }, |
| 27 | +}); |
| 28 | + |
| 29 | +const MyDocument = () => ( |
| 30 | + <Document> |
| 31 | + <Page size="A4" style={tw('p-12 font-sans')}> |
| 32 | + <View style={tw('p-20 bg-gray-100')}> |
| 33 | + <Text style={tw('text-custom text-3xl')}>Section #1</Text> |
| 34 | + </View> |
| 35 | + <View style={tw('mt-12 px-8 rotate-2')}> |
| 36 | + <Text style={tw('text-amber-600 text-2xl')}>Section #2</Text> |
| 37 | + </View> |
| 38 | + </Page> |
| 39 | + </Document> |
| 40 | +); |
| 41 | +``` |
| 42 | + |
| 43 | +<Example name="tailwind" /> |
| 44 | + |
| 45 | +The returned `tw` function takes a space-separated class string and returns a react-pdf `Style` object. Unknown classes are skipped with a console warning, emitted once per distinct class. |
| 46 | + |
| 47 | +## createTw |
| 48 | + |
| 49 | +`createTw(config, options)` builds the `tw` function. `config` is a theme object merged into Tailwind's `defaultTheme`, following the Tailwind v4 theme shape — see [Tailwind's default theme](https://github.com/tailwindlabs/tailwindcss/blob/main/packages/tailwindcss/src/compat/default-theme.ts) for reference. |
| 50 | + |
| 51 | +```js |
| 52 | +const tw = createTw( |
| 53 | + { |
| 54 | + fontFamily: { |
| 55 | + sans: ['Papyrus'], |
| 56 | + }, |
| 57 | + spacing: { |
| 58 | + verybig: '999rem', |
| 59 | + }, |
| 60 | + colors: { |
| 61 | + custom: '#bada55', |
| 62 | + }, |
| 63 | + }, |
| 64 | + { |
| 65 | + // Base font size in points. Defaults to 12. |
| 66 | + ptPerRem: 12, |
| 67 | + }, |
| 68 | +); |
| 69 | +``` |
| 70 | + |
| 71 | +Scales merge one level deep, so overriding a single key keeps the rest of the default scale — `spacing: { 4: '2rem' }` changes `p-4` while leaving `p-8` alone, and `colors: { gray: { 500: '#fff' } }` leaves the other grays intact. Replace a whole scale by overriding it with a non-object value. |
| 72 | + |
| 73 | +`fontFamily` is the exception: it comes from your config alone, neither merging with Tailwind's defaults nor falling back to them. react-pdf can only draw [fonts you have registered](/docs/v4/fonts), and Tailwind's stacks name web families like `-apple-system`, so resolving `font-sans` against them would throw at render time. Register a font, map it in the config, and `font-<key>` works; without a config, `font-sans` / `font-serif` / `font-mono` warn as unsupported while `font-bold` and friends still resolve. |
| 74 | + |
| 75 | +## Color opacity |
| 76 | + |
| 77 | +`bg-red-500/50` and friends work anywhere a color does — `bg-`, `text-`, `border-`, `decoration-` — including black, white, custom and arbitrary colors: |
| 78 | + |
| 79 | +```js |
| 80 | +tw('bg-red-500/50'); // { backgroundColor: '#ef444480' } |
| 81 | +tw('text-black/25'); // { color: '#00000040' } |
| 82 | +tw('bg-[#bada55]/60'); // { backgroundColor: '#bada5599' } |
| 83 | +``` |
| 84 | + |
| 85 | +A bare suffix is a percentage; a bracketed one is `0`–`1` unless it carries a `%`, so `/[0.55]` and `/[55%]` agree. `transparent`, `currentColor` and `inherit` name no channel to modulate and reject the suffix. |
| 86 | + |
| 87 | +## Variants |
| 88 | + |
| 89 | +Breakpoint and orientation variants become react-pdf media queries, which resolve against the **page box** rather than a viewport: |
| 90 | + |
| 91 | +```js |
| 92 | +tw('p-2 lg:p-4 landscape:p-6'); |
| 93 | +// { |
| 94 | +// padding: 6, |
| 95 | +// '@media min-width: 768': { padding: 12 }, |
| 96 | +// '@media orientation: landscape': { padding: 18 }, |
| 97 | +// } |
| 98 | +``` |
| 99 | + |
| 100 | +| Variant | Becomes | |
| 101 | +| ------------------------------ | ----------------------- | |
| 102 | +| `sm:` `md:` `lg:` `xl:` `2xl:` | `@media min-width: N` | |
| 103 | +| `max-sm:` … `max-2xl:` | `@media max-width: N` | |
| 104 | +| `min-[600px]:` `max-[40rem]:` | the width you give it | |
| 105 | +| `portrait:` `landscape:` | `@media orientation: …` | |
| 106 | +| stacked, e.g. `lg:portrait:` | both, joined with `and` | |
| 107 | + |
| 108 | +Tailwind v4 states its breakpoints in rem, so at the default `1rem = 12pt` they land at page scale: `sm` is 480pt, `md` 576pt, `lg` 768pt, `xl` 960pt. An A4 page is 595pt wide upright and 842pt on its side, so `md` matches portrait and `lg` matches landscape. Set `screens` in the config to choose your own. |
| 109 | + |
| 110 | +State variants — `hover:`, `focus:`, `dark:`, `group-*`, `peer-*` — describe something a printed page never enters, and are reported as unsupported rather than applied. Applying them would bake the hover style into the output. |
| 111 | + |
| 112 | +## Notes |
| 113 | + |
| 114 | +- Supports the CSS properties that make sense in a PDF context and are supported by react-pdf — see [valid CSS properties](/docs/v4/styling#valid-css-properties). |
| 115 | +- Uses `pt` as the internal unit ([valid units](/docs/v4/styling#valid-units)), with `1rem = 12pt` by default. Change it with `ptPerRem`. |
| 116 | +- react-pdf uses [Yoga](https://yogalayout.dev/) for layout, so some defaults differ from the web — `flex-direction` defaults to `column`, for example. Add `flex-row` where you need it. |
| 117 | +- Line heights are emitted unitless, since react-pdf only supports unitless `lineHeight`. |
| 118 | +- `aspect-auto` and `line-clamp-none` warn as unsupported. react-pdf has no style value meaning "no aspect ratio" or "no clamp" — leaving the utility off is the reset. |
| 119 | +- Intrinsic sizing (`w-fit`, `h-min`, `max-w-max`, …), `max-w-none` / `max-h-none`, and lengths in units react-pdf can't parse (`max-w-prose` is `65ch`) warn as unsupported. Yoga has no equivalent, and passing the value through would throw while laying out the document. |
| 120 | +- `float-*` and `clear-*` map to react-pdf's [float support](/docs/v4/floats), which is newer and has rough edges: setting `lineHeight` on floated content breaks text wrap, and parents don't grow to contain their floats. |
0 commit comments