Takumi

Headers & footers

Add repeating headers, footers, and page numbers.

Pass JSX, HTML, or a node tree to header or footer. Each repeats in the page margin. Automatic margins make room for their content.

import {  } from "takumi-pdf";
import { ,  } from "takumi-pdf/primitives";

const  = await (, {
  : (
    < ="flex w-full justify-center text-[10px] text-gray-500">
      Page < /> of < />
    </>
  ),
});

Sizing the margin

margin defaults to "auto". It measures the header and footer at full page width and reserves space above and below the document.

For ordinary page sizes, each automatic top or bottom margin is the larger of 37.8px and the header or footer height plus a 20px inset. Set a numeric margin to override it. Omitted sides remain automatic:

const margin = { top: 96 };

Automatic left and right margins are 37.8px on ordinary page sizes. A numeric margin that is too small can let the header or footer overlap the body.

To calculate a numeric margin, call measure() with the same page size and fonts as the render. It measures at full page width with three-digit page counters. Add the 20px inset to the returned height.

import {  } from "takumi-pdf";

const {  } = await (, { : "a4" });

Passing viewport instead of a page size measures the tree as-is. Counter hooks stay empty.

Page counters

<PageNumber /> is the current page, counting from 1. <TotalPages /> is the number of pages in the document. Both take a format prop for a counter style, and pass className, style, and tw through.

The primitives render class hooks. A node classed pageNumber or totalPages receives the counter text, replacing what it holds, so an empty <span /> is enough. Chromium's print templates use the same two names, and HTML input uses them directly:

Page <span class="pageNumber"></span> of <span class="totalPages"></span>

A node carrying both classes gets the page number.

Counters outside a band

Counters also work in document content. Inside a position: fixed box, they update on every page:

<div style={{ position: "fixed", bottom: 24, left: 24, right: 24 }}>
  Page <PageNumber /> of <TotalPages />
</div>

A fixed box draws over the content rather than in the margin, so leave it room. margin sizes itself to the header and footer alone.

In ordinary flow, <PageNumber /> shows the page containing the counter and <TotalPages /> shows the document length. These counters require another layout pass because their values depend on pagination. Inline counters use the enclosing box and preceding rendered flow to determine their page.

Counter styles

The format prop names a CSS @counter-style and formats the number. On a class hook, add the style name next to the hook class. The first supported name wins. Unsupported names are ignored, and a counter without one counts in decimal.

import {  } from "takumi-pdf";
import { ,  } from "takumi-pdf/primitives";

const  = await (, {
  : (
    < ={{ : 12 }}>
      第 < ="trad-chinese-informal" /> 頁,共{" "}
      < ="trad-chinese-informal" /> 頁
    </>
  ),
});

Numbers and numerals

StylePage 7Page 12
decimal (default)712
decimal-leading-zero0712
lower-romanviixii
upper-romanVIIXII
cjk-decimal一二
trad-chinese-informal十二
cjk-ideographic十二

Blink defines cjk-ideographic as an extension of trad-chinese-informal, and this renderer follows it. Both read out numbers up to 9999. Past that they fall back to cjk-decimal, so page 10000 formats as 一零零零零.

Alphabets

These styles count the way a spreadsheet names its columns. The letter after z is aa.

StylePage 12
lower-alpha, lower-latinl
upper-alpha, upper-latinL
lower-greekμ
hiragana
katakana

Other digits

These styles write the decimal number in another script's digits.

StylePage 12StylePage 12
arabic-indic١٢mongolian᠑᠒
bengali১২myanmar၁၂
cambodian១២oriya୧୨
devanagari१२persian۱۲
gujarati૧૨tamil௧௨
gurmukhi੧੨telugu౧౨
kannada೧೨thai๑๒
khmer១២tibetan༡༢
lao໑໒urdu۱۲
malayalam൧൨

khmer and cambodian share their digits, as do persian and urdu.

A registered font has to cover the digits of the style you pick. Latin fonts rarely carry Thai or Tibetan numerals, so pair a script style with a font that has the glyphs.

Band height

The renderer recalculates header and footer height with the actual page count, up to three passes. Automatic margins use that height across the document. Leave enough width for counters to avoid wrapping when the page count grows.

Last updated on

On this page