# Paged.js browser pagination and PDF-oriented layout

> Paged.js brings paged media layout to HTML documents by polyfilling CSS modules and breaking overflowing content into pages. It fits engineers and publishers who need browser previews or print-oriented book layouts, but its version remains marked beta and PDF generation is delegated to a separate CLI.

**pagedjs/pagedjs** — Display paginated content in the browser and generate print books using web technology

- Repository: https://github.com/pagedjs/pagedjs
- Website: https://pagedjs.org
- Stars: 1,540 · Forks: 167
- Language: HTML
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/pagedjs-pagedjs

## Paged.js target content and browser workflow

Paged.js addresses a specific gap between ordinary browser layout and paged publication layout. A browser normally places content in one continuous document flow, while a book, report, or fixed-layout HTML document often needs named pages, page counters, generated content, controlled breaks, and print classes. The library targets authors and engineers who already work with HTML and CSS but need pagination to happen in the browser.

The project describes itself as an open-source library for displaying paginated content in the browser and generating print books with web technology. Its examples include processing the first 50 pages of Moby Dick, uploading and chunking an EPUB with Epub.js, testing print styles, and applying the polyfill to an HTML document. That range indicates two related use cases. One is an editorial preview in which authors inspect page boundaries while editing HTML. The other is document processing in which code invokes the paginator and obtains a completed flow.

Paged.js is not a general-purpose word processor or a replacement for browser printing. It is a layout library for web documents. The README does not document import from DOCX, a graphical page editor, or a publishing workflow for formats other than HTML and the EPUB example. PDF creation is possible through a companion project, but the library itself directs users to the separate pagedjs-cli repository for command-line rendering with Puppeteer.

## Chunker, Polisher, Previewer, and the layout pipeline

The repository separates publication layout into named components. Chunker turns a document into paginated media flows and applies print classes. Polisher converts `@page` CSS into classes, then applies counters and generated content. Previewer provides the application-facing interface that initiates preview processing. Custom behavior enters through handlers rather than by replacing the complete rendering pipeline.

The documented call path starts with `Chunker.flow()` and proceeds through `Chunker.render()`. That loop handles page overflow and creates additional pages. Each page invokes `Page.layout()`, which creates a `Layout` and waits for a `Breaktoken`. `Layout.renderTo()` walks the nodes being placed on the page, while `Layout.findBreakToken()` tries to detect overflow and a legal break. This is a browser layout engine driven by DOM measurement rather than a standalone text layout engine.

Polisher operates on CSS syntax before or during that rendering work. Its hooks include `beforeTreeParse`, `afterTreeWalk`, `onAtPage`, `onRule`, `onDeclaration`, and `onContent`. This separation allows Paged.js to interpret page rules while Chunker resolves fragmented content across page boundaries. Handler methods may return a Promise or be declared with `async`, in which case the documented behavior is to wait for that task before continuing with other handlers registered for the same hook.

This architecture offers useful extension points, especially for a product with custom page behavior. It also means that CSS support is constrained by what the handlers implement. The README directs readers to the supported-properties cheatsheet on pagedjs.org rather than claiming unrestricted support for CSS Paged Media.

## Installing Paged.js and rendering a first preview

The README gives npm as the direct installation path for application projects. The following command installs the `pagedjs` package from npm:

```bash
$ npm install pagedjs
```

For an ES module application, create a `Previewer`, select source content and stylesheets, and pass the destination element. The `.then()` callback receives a flow whose `total` property is the page count used in the README example:

```js
import { Previewer } from 'pagedjs';

let paged = new Previewer();
let flow = paged.preview(
  DOMContent,
  ["path/to/css/file.css"],
  document.body
).then((flow) => {
  console.log("Rendered", flow.total, "pages.")
})
```

A browser-only project can instead load the polyfill bundle. By default, it runs when the DOM is ready and applies the Paged Media styles to the page:

```html
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
```

If assets are not ready when the document initializes, the README shows how to delay execution with `window.PagedConfig.before`. The returned Promise postpones the preview until its `resolve()` call:

```html
<script>
  window.PagedConfig = {
    before: () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => { resolve() }, 1000);
      })
    },
    after: (flow) => { console.log("after", flow) },
  };
</script>
```

For explicit control, set `auto` to `false`, then call `window.PagedPolyfill.preview()`. The README uses a timer only to make the timing visible:

```html
<script>
  window.PagedConfig = {
    auto: false,
    after: (flow) => { console.log("after", flow) },
  };

  setTimeout(() => {
    window.PagedPolyfill.preview();
  }, 1000);
</script>
```

The printed line should show the rendered page total. The `after` callback receives the resulting flow, which is also the point at which an application can inspect completed pagination.

## Custom handlers for application-specific pagination

Paged.js exposes lifecycle hooks for both module parsing and page rendering. In a polyfill page, custom code extends `Paged.Handler`, passes the `chunker`, `polisher`, and `caller` to the base constructor, and registers the class with `Paged.registerHandlers`:

```html
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<script>
  class MyHandler extends Paged.Handler {
    constructor(chunker, polisher, caller) {
      super(chunker, polisher, caller);
    }

    afterPageLayout(pageFragment, page) {
      console.log(pageFragment);
    }
  }
  Paged.registerHandlers(MyHandler);
</script>
```

The documented hooks cover previewing, parsing, page layout, overflow, break detection, tree walking, CSS rules, counters, and generated content. This is more targeted than adding an arbitrary post-processing step. For example, `onBreakToken` can participate in the point at which layout detects a candidate page break, while `afterPageLayout` observes the page fragment and page after layout has completed.

That flexibility creates a maintenance responsibility. An application handler may become tied to undocumented internal behavior, CSS support, or library lifecycle changes. The package version in `package.json` is `0.5.0-beta.2`, so extension authors should account for beta status during upgrades. The repository is not archived, and its last push was on 2026-10-06, but recent repository activity does not by itself promise stable interfaces.

## Testing, builds, and development dependencies

Repository development uses npm scripts rather than a globally installed CLI. After checking out the repository, `npm install` installs the locked project dependencies. `npm start` runs the Rollup watch configuration and serves the local development site at `http://localhost:9090/` with livereload and automatic compilation. Distribution bundles are produced with `npm run build`, while `npm run compile` produces the `lib` output.

The basic test command runs linting before Jest:

```bash
npm test
```

Specification tests use Puppeteer in Chrome to compare behavior against CSS specifications. Their PDF comparison path depends on Ghostscript and `ghostscript4js`. The README recommends running those specs in Docker through the project image. A native macOS setup installs Ghostscript with Homebrew, while the Debian instructions install `ghostscript` and `libgs-dev`:

```bash
sudo apt-get install ghostscript
sudo apt-get install libgs-dev
```

On Linux, the README documents locating the native Ghostscript installation through `GS4JS_HOME`:

```bash
GS4JS_HOME="/usr/lib/$(gcc -dumpmachine)" npm install ghostscript4js
```

This test stack is a real adoption cost. Even if an application only needs browser preview, the project’s specification suite may require Chrome, Puppeteer, Ghostscript, image comparison data, and the Docker environment. The repository includes `Dockerfile`, `docker-font.conf`, font packages, and configuration for several scripts, but the README excerpt does not document a production deployment pattern for an application built with the library.

## MIT licensing and the boundary against standalone PDF export

The repository declares the MIT license in both the README and `package.json`. That permits use, modification, and redistribution under the license’s stated conditions, including preservation of its copyright and permission notice. This is a factual statement about the declared license, not legal advice about a particular product or distribution.

Paged.js is the wrong choice when the deliverable is a PDF and no browser-side pagination preview is needed. The core README points to pagedjs-cli for PDF rendering of HTML files with Puppeteer. That is a different component with its own installation and usage requirements. Paged.js handles pagination and print-oriented page styling, while the companion CLI owns file-driven PDF output. Treat them as two parts of a possible pipeline rather than assuming that installing `pagedjs` produces a PDF file.

It is also a poor fit for teams that require native editing, binary document formats, or an editing interface. The repository presents a JavaScript library, HTML examples, handler hooks, and automated tests. It does not describe an authoring UI. Teams needing those capabilities should select software centered on those file formats and interactions. A real alternative for PDF generation is to use the companion pagedjs-cli directly when Paged.js layout is not required. The practical difference is that the CLI owns HTML-to-PDF execution, while Paged.js exposes browser pagination, CSS transformation, and extensible layout hooks.

## Conclusion

Adopt Paged.js when the document is already authored in HTML and browser-based page preview is the primary requirement. Do not treat it as a standalone PDF renderer or expect beta-level package naming to remove compatibility work. Before adoption, verify the supported CSS properties, pagination behavior, and final PDF output for representative content, because the documentation links support information to an external cheatsheet and does not claim complete CSS Paged Media conformance.

## FAQ

### How do I install Paged.js for use in an npm project?

The README gives `npm install pagedjs` as the installation command. Application code can then import `Previewer` from the `pagedjs` package.

### How does Paged.js create pages in the browser?

Chunker processes content into paged media flows, measures overflow, creates additional pages, and uses break tokens while laying out nodes. The README describes the flow as a loop through `Chunker.render()`, `Page.layout()`, `Layout.renderTo()`, and `Layout.findBreakToken()`.

### Does Paged.js itself include a command-line PDF renderer?

No. The README directs users to the separate pagedjs-cli repository for rendering HTML files to PDF with Puppeteer. Paged.js provides the pagination library and browser rendering components.

### Can I delay automatic execution of the Paged.js polyfill?

Yes. The README documents a Promise-returning `before` function in `window.PagedConfig`, or an `auto` value of `false` followed by a call to `window.PagedPolyfill.preview()`.

## Sources

- [Issues](https://github.com/pagedjs/pagedjs/issues)
- [License: MIT](https://github.com/pagedjs/pagedjs/blob/main/LICENSE)
- [pagedjs/pagedjs on GitHub](https://github.com/pagedjs/pagedjs)
- [Project website](https://pagedjs.org)
- [README](https://github.com/pagedjs/pagedjs/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pagedjs-pagedjs
