DEV Community

sunshey
sunshey

Posted on

How to Crop PDF Margins in the Browser with Vue 3 and pdf-lib

Cropping PDF margins in the browser requires careful handling of page dimensions and crop boxes. Here's how to build a browser-based PDF crop tool with Vue 3 and pdf-lib.

The challenge: Managing crop boxes

PDF cropping involves:

  1. Setting the crop box (visible area) for each page
  2. Calculating margin offsets from page dimensions
  3. Supporting different crop presets (A4, Letter, custom)
  4. Preserving content while removing white space

The stack

  • Vue 3 with Composition API
  • pdf-lib for PDF manipulation
  • Vite for bundling

The core implementation

<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument, PDFFont, rgb, StandardFonts } from 'pdf-lib'

type CropMode = 'uniform' | 'custom' | 'preset'

const file = ref<File | null>(null)
const cropMode = ref<CropMode>('uniform')
const margins = ref({ top: 50, bottom: 50, left: 50, right: 50 })
const preset = ref<'a4' | 'letter' | 'custom'>('a4')
const cropping = ref(false)
const result = ref<Uint8Array | null>(null)

async function cropPdf() {
  if (!file.value) return
  cropping.value = true

  const arrayBuffer = await file.value.arrayBuffer()
  const pdf = await PDFDocument.load(arrayBuffer)
  const pages = pdf.getPages()

  for (const page of pages) {
    const width = page.getWidth()
    const height = page.getHeight()

    // Calculate crop box
    const cropX = margins.value.left
    const cropY = height - margins.value.top
    const cropWidth = width - margins.value.left - margins.value.right
    const cropHeight = height - margins.value.top - margins.value.bottom

    page.setCropBox(cropX, cropY, cropWidth, cropHeight)
  }

  result.value = await pdf.save()
  cropping.value = false
}
</script>
Enter fullscreen mode Exit fullscreen mode

Key implementation details

1. Crop box calculation

The crop box defines the visible area of each page:

const cropX = margins.left
const cropY = height - margins.top
const cropWidth = width - margins.left - margins.right
const cropHeight = height - margins.top - margins.bottom

page.setCropBox(cropX, cropY, cropWidth, cropHeight)
Enter fullscreen mode Exit fullscreen mode

2. Unit conversion

Convert between points and other units:

const pointsToInches = (points: number) => points / 72
const inchesToPoints = (inches: number) => inches * 72
Enter fullscreen mode Exit fullscreen mode

3. Preset margins

Common paper size presets:

const presets: Record<string, { top: number; bottom: number; left: number; right: number }> = {
  a4: { top: 72, bottom: 72, left: 72, right: 72 },  // 1 inch
  letter: { top: 72, bottom: 72, left: 72, right: 72 },
  narrow: { top: 36, bottom: 36, left: 36, right: 36 },  // 0.5 inch
}
Enter fullscreen mode Exit fullscreen mode

4. Preview generation

Generate a thumbnail preview of the cropped result:

function generatePreview(): string {
  // Use canvas to render a preview
  // This requires pdf.js for rendering
}
Enter fullscreen mode Exit fullscreen mode

Limitations

No real-time preview

pdf-lib doesn't support real-time preview without rendering.

Solution: Generate static previews or use pdf.js for rendering.

Crop box vs. media box

Changing the crop box doesn't remove content; it just changes the visible area.

Solution: Use pdf-lib's trim or crop methods for actual content removal.

Large files

Very large PDFs may cause memory issues.

Solution: Process in smaller batches or use Web Workers.

Summary

Building a browser-based PDF crop tool involves:

  1. Loading the PDF with pdf-lib
  2. Calculating crop box dimensions
  3. Setting the crop box for each page
  4. Saving and downloading the cropped PDF

Try it at en.sotool.top/crop-pdf.

Top comments (0)