Skip to content
All insights

Frontend

Rendering a Book in a Browser Without Fighting the Browser

By Vishnu · 23 September 2025 · 5 min read

Photograph by Perfecto Capucine on Unsplash

Most web front-end work involves short content in a long-lived application shell: a dashboard, a form, a feed. A reading application inverts that. The shell is trivial and the content is enormous — a single book can be more text than an entire conventional web application will ever render.

We built the web and mobile platform for an e-book library giving readers access to a personal collection. The interesting engineering was almost all in the reader, and very little of it resembled ordinary component work.

Pagination is a layout question with no correct answer

A printed book has fixed pages. A digital book does not: page boundaries depend on the viewport, the font, the size the reader chose, the line height, and whether they rotated the device. Change any of those and every boundary moves.

Which forces an early decision. Continuous scrolling avoids the problem entirely and is what the web does natively — cheap to build, and familiar. Paginated reading requires computing where text breaks and is what many readers strongly prefer, particularly for long-form fiction, because a page is a unit of progress and a scroll position is not.

If pagination is required, the honest way to do it is to let the browser do the layout and then measure it, rather than trying to predict where text will break. Predicting means reimplementing line-breaking, hyphenation and font metrics in application code, which is a large amount of work to arrive at a slightly wrong answer. Measuring means rendering into a container, asking the browser where things actually ended up, and deriving boundaries from that.

CSS multi-column layout does a surprising amount of this work, since the browser will flow text into columns of a given width and the column count tells you the page count. It has limitations — controlling breaks around images and headings is awkward, and behaviour across engines is not identical — but it starts from the browser's own layout engine rather than competing with it, which is the right side of that trade.

A chapter in the DOM is a performance decision

The naive implementation puts the whole book in the document. It works for a short one and collapses for a long one: layout cost scales with content, memory grows, and on a mid-range phone the reader becomes unusable at exactly the length where reading applications matter.

So content is rendered in windows — the current section plus a little on either side — and the rest is not in the document. This is virtual scrolling, familiar from long lists, and harder here because the items are not uniform and their heights are not known until they are laid out.

It also breaks two things readers expect. Find-in-page only searches the DOM, so searching has to be implemented against the source text rather than delegated to the browser. And accessibility tooling reads the document, so a screen reader must be given a coherent reading experience even though most of the book is not present — which requires deliberate work with live regions and focus management rather than hoping the default behaviour is adequate.

Position has to survive everything

The single most important piece of state is where the reader is, and it is the easiest to get wrong.

A scroll offset in pixels is worthless: change the font size and it points at the wrong place. A page number is worse, because pages are not stable. What is stable is a position in the source text — a character or element offset within a chapter, which survives font changes, viewport changes, rotation, and moving between a laptop and a phone.

Getting this right is what makes cross-device reading work, and it is why position should be expressed in terms of the content rather than the presentation. Annotations have the same requirement and a harder version of it: a highlight spans a range, the range must survive reflow, and a highlight rendered a paragraph away from where the reader put it is a data-loss bug from their point of view even though nothing was lost.

Smoothness is the whole experience

Readers are unusually sensitive to jank. A dropped frame while scrolling a dashboard goes unnoticed. A dropped frame while turning a page is felt immediately, because the gesture is physical and repeated hundreds of times in a session.

This means the expensive work — measuring layout, computing pagination, preparing the next section — cannot happen on the main thread during an interaction. It has to be done ahead of time, while the reader is reading, so that the next turn is already prepared. Where the work is genuinely heavy, a worker keeps it off the thread that draws frames, though anything requiring layout measurement has to happen in the document and therefore has to be scheduled rather than offloaded.

Turn animation is where this is most visible. An animation that runs on transform and opacity is composited and stays smooth. One that animates a property triggering layout — width, height, position — will not, no matter how much effort goes into the easing curve.

Typography is the product

In a reading application the type is not styling. It is the thing being used.

Which means line length has to be constrained to something readable rather than filling the viewport — a wide desktop window at full width produces lines nobody can comfortably track. It means the reader's control over size, spacing and theme is a core feature rather than a preferences afterthought. It means fonts must be self-hosted and loaded so text never reflows visibly after paint, because a book that jumps as a font swaps in is worse than one in a system font. And it means honouring the reader's own accessibility settings, including a text size far larger than any design mock, without the layout falling apart.

Dark mode deserves particular care here, and not as a colour inversion. Pure white on pure black produces halation that makes extended reading uncomfortable; slightly softened values on both sides are what people actually read by for an hour.

The general point

Almost every performance instinct from application front-end work transfers. Almost every layout instinct does not. The content is longer than the page model expects, the presentation is user-controlled to a degree most applications never allow, and the quality bar for smoothness is set by a physical gesture rather than by a click.

It is one of the few places on the web where the right move is repeatedly to ask the browser what it did and build on the answer, instead of deciding in advance and imposing it.


iLeaf builds reading, publishing and content platforms across web and mobile. See the work or tell us about your project.

Thinking about this for your own business?

We have been building and running enterprise systems since 2011. Talk to a solutions lead about where agents pay off first.

Talk to a solutions lead