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

PropTypeDefaultDescription
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.
flexnumberFlex grow factor.
flexGrownumberFlex grow factor (individual).
flexShrinknumberFlex shrink factor.
flexBasisnumber | stringInitial size before flex distribution.
gapnumberGap between flex items (in points).
rowGapnumberRow gap between flex items.
columnGapnumberColumn 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

PropTypeDefaultDescription
widthnumber | stringElement width. Numbers are in points.
heightnumber | stringElement height. Numbers are in points.
minWidthnumberMinimum width.
maxWidthnumberMaximum width.
minHeightnumberMinimum height.
maxHeightnumberMaximum height.
marginnumberShorthand margin. Use marginTop/Right/Bottom/Left for sides.
paddingnumberShorthand padding. Use paddingTop/Right/Bottom/Left for sides.
bordernumber | stringBorder width or shorthand (e.g. '1px solid red').
borderRadiusnumberBorder radius for View components.

Typography

PropTypeDefaultDescription
fontSizenumberFont size in points. Default is 12.
fontFamilystringFont family name. Options: Helvetica, Times-Roman, Courier, or custom registered fonts.
fontWeightnumber | stringFont weight. 100-900 or 'bold'.
fontStyle'normal' | 'italic'Font style.
lineHeightnumberLine height multiplier or fixed value in points.
letterSpacingnumberLetter 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.
textIndentnumberFirst-line indentation for paragraphs.
wordSpacingnumberWord spacing in points.
hyphens'none' | 'auto''auto'Controls hyphenation. Uses the hyphenation engine.
orphansnumber2Minimum lines to keep at the bottom of a page.
widowsnumber2Minimum lines to keep at the top of a page.

Colors & Backgrounds

PropTypeDefaultDescription
colorstringText color. Supports hex, rgb(), rgba(), and named CSS colors.
backgroundColorstringBackground color of the element.
opacitynumberOpacity 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

PropTypeDefaultDescription
min-widthnumberMatches when the page is at least this wide.
max-widthnumberMatches when the page is at most this wide.
min-heightnumberMatches when the page is at least this tall.
max-heightnumberMatches 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.