Core Concepts
Styling
vue-pdf uses a CSS-like styling API based on the react-pdf style system. Styles are defined as JavaScript objects using camelCase property names.
Basic Styling
Pass a style object to the style prop of any component:
vue
<template>
<Document>
<Page size="A4">
<View :style="{ padding: 40, backgroundColor: '#f5f5f5' }">
<Text :style="{ fontSize: 24, color: '#333', fontWeight: 'bold' }">
Styled Text
</Text>
</View>
</Page>
</Document>
</template>Flexbox Layout
Every <View> is a flex container by default (with flex-direction: column). vue-pdf uses Yoga Layout — the same engine as React Native — for precise flexbox calculations.
Supported Flex Properties
| Prop | Type | Default | Description |
|---|---|---|---|
display | 'flex' | 'none' | 'flex' | Set display mode. |
flexDirection | 'row' | 'column' | 'row-reverse' | 'column-reverse' | 'column' | Main axis direction. |
flexWrap | 'wrap' | 'nowrap' | 'wrap-reverse' | 'nowrap' | Whether items can wrap. |
justifyContent | 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly' | — | Alignment along main axis. |
alignItems | 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline' | — | Alignment along cross axis. |
alignSelf | 'auto' | 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline' | — | Override align-items for a single child. |
flex | number | — | Flex grow factor. |
flexGrow | number | — | Flex grow factor (individual). |
flexShrink | number | — | Flex shrink factor. |
flexBasis | number | string | — | Initial size before flex distribution. |
gap | number | — | Gap between flex items (in points). |
rowGap | number | — | Row gap between flex items. |
columnGap | number | — | Column gap between flex items. |
Flex Example
vue
<template>
<Document>
<Page size="A4">
<!-- Row layout -->
<View :style="{ flexDirection: 'row', gap: 20, padding: 40 }">
<View :style="{ flex: 1, padding: 20, backgroundColor: '#e8f5e9' }">
<Text>Column 1</Text>
</View>
<View :style="{ flex: 2, padding: 20, backgroundColor: '#fff3e0' }">
<Text>Column 2 (wider)</Text>
</View>
</View>
</Page>
</Document>
</template>Box Model & Dimensions
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | string | — | Element width. Numbers are in points. |
height | number | string | — | Element height. Numbers are in points. |
minWidth | number | — | Minimum width. |
maxWidth | number | — | Maximum width. |
minHeight | number | — | Minimum height. |
maxHeight | number | — | Maximum height. |
margin | number | — | Shorthand margin. Use marginTop/Right/Bottom/Left for sides. |
padding | number | — | Shorthand padding. Use paddingTop/Right/Bottom/Left for sides. |
border | number | string | — | Border width or shorthand (e.g. '1px solid red'). |
borderRadius | number | — | Border radius for View components. |
Typography
| Prop | Type | Default | Description |
|---|---|---|---|
fontSize | number | — | Font size in points. Default is 12. |
fontFamily | string | — | Font family name. Options: Helvetica, Times-Roman, Courier, or custom registered fonts. |
fontWeight | number | string | — | Font weight. 100-900 or 'bold'. |
fontStyle | 'normal' | 'italic' | — | Font style. |
lineHeight | number | — | Line height multiplier or fixed value in points. |
letterSpacing | number | — | Letter spacing in points. |
textAlign | 'left' | 'center' | 'right' | 'justify' | — | Text alignment. |
textDecoration | 'underline' | 'line-through' | 'underline line-through' | — | Text decoration lines. |
textTransform | 'uppercase' | 'lowercase' | 'capitalize' | — | Text transformation. |
textIndent | number | — | First-line indentation for paragraphs. |
wordSpacing | number | — | Word spacing in points. |
hyphens | 'none' | 'auto' | 'auto' | Controls hyphenation. Uses the hyphenation engine. |
orphans | number | 2 | Minimum lines to keep at the bottom of a page. |
widows | number | 2 | Minimum lines to keep at the top of a page. |
Colors & Backgrounds
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | — | Text color. Supports hex, rgb(), rgba(), and named CSS colors. |
backgroundColor | string | — | Background color of the element. |
opacity | number | — | Opacity from 0 to 1. |
Positioning
Use absolute positioning within a parent with position: 'relative':
vue
<template>
<Document>
<Page size="A4">
<View :style="{ position: 'relative', height: 200 }">
<View :style="{
position: 'absolute',
top: 10,
right: 10,
width: 100,
height: 100,
backgroundColor: '#ff0000'
}">
<Text>Absolute</Text>
</View>
</View>
</Page>
</Document>
</template> Absolute positioning in PDF layouts works differently than in browser CSS. The parent must have a defined
height and position: 'relative'. Media Queries
Styles can adapt to the page they render on. A key beginning with @media is matched against the page's dimensions and orientation, and its properties are merged in when it matches:
vue
<script setup lang="ts">
import { StyleSheet } from '@vuepdf/renderer'
const styles = StyleSheet.create({
container: {
padding: 40,
flexDirection: 'row',
// Applied when the page is narrower than 400pt
'@media max-width: 400': {
padding: 16,
flexDirection: 'column',
},
// Applied on landscape pages
'@media orientation: landscape': {
padding: 60,
},
},
})
</script>
<template>
<Document>
<!-- Same styles, different result per page size -->
<Page size="A4" :style="styles.container">
<Text>Roomy</Text>
</Page>
<Page :size="[300, 500]" :style="styles.container">
<Text>Compact</Text>
</Page>
</Document>
</template>Supported Features
| Prop | Type | Default | Description |
|---|---|---|---|
min-width | number | — | Matches when the page is at least this wide. |
max-width | number | — | Matches when the page is at most this wide. |
min-height | number | — | Matches when the page is at least this tall. |
max-height | number | — | Matches when the page is at most this tall. |
orientation | 'portrait' | 'landscape' | — | Matches the page orientation. |
Queries resolve against the page, not the viewport or the parent element — there is no container-query equivalent. Values are in points, and the syntax is
'@media <feature>: <value>' without parentheses. Combine features by separating them with and.