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:
- Setting the crop box (visible area) for each page
- Calculating margin offsets from page dimensions
- Supporting different crop presets (A4, Letter, custom)
- 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>
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)
2. Unit conversion
Convert between points and other units:
const pointsToInches = (points: number) => points / 72
const inchesToPoints = (inches: number) => inches * 72
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
}
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
}
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:
- Loading the PDF with pdf-lib
- Calculating crop box dimensions
- Setting the crop box for each page
- Saving and downloading the cropped PDF
Try it at en.sotool.top/crop-pdf.
Top comments (0)