Rendering PDFs at 60fps
Tiling, workers, and the canvas tricks behind smooth scrolling.
A PDF page is a program: a list of drawing operators (fill this path, place this glyph, paint this image) that a renderer executes onto a surface. Executing that program for a complex page can take tens of milliseconds, and at 60fps you have about sixteen. The whole game of smooth PDF rendering is making sure that work never happens on the thread that’s scrolling.
Step one is getting parsing and rasterization off the main thread entirely. The parser lives in a Web Worker; the UI thread sends it a page number and a scale, and gets back pixels. The main thread’s only job is compositing bitmaps it already has, which the GPU does essentially for free.
Step two is tiling. Rendering a whole page at retina resolution wastes work on parts the user can’t see. Instead, pages are cut into tiles rendered on demand, prioritized by what’s in or near the viewport. Scroll fast and you briefly see a low-resolution preview (a cheap, blurry render of the whole page) that sharpens tile by tile as the worker catches up. That’s the same trick maps have used for twenty years, because it works.
Step three is cache discipline. Decoded page bitmaps are huge (a single A4 page at 2× device pixels is north of 30 MB raw), so an LRU cache with a hard byte budget decides what stays. Text content, by contrast, is tiny and worth keeping for every page you’ve visited: it powers instant search and selection without re-parsing.
The result feels less like ‘viewing a file’ and more like scrolling a native document, and it’s all standard web platform: workers, canvases, and transferable buffers. The browser stopped being the bottleneck years ago; most PDF software just hasn’t noticed yet.
Try it yourself. Every FernPDF tool runs in your browser. Open one and watch the network tab.
Open PDF to JPG