Typography & Fonts
font management and advanced text rendering.
Takumi does not use system fonts. All fonts must be explicitly loaded to be available for rendering.
For @takumi-rs/core (napi-rs version), full axis Geist and Geist Mono are embedded by default.
For @takumi-rs/wasm, a single variable Latin font, Manrope, is embedded by default.
If you need a monospace family in WASM, provide your own font.
Font
import { } from "takumi-js/response";
import type { } from "takumi-js";
export function () {
return new (< />, {
: [
{
: "Inter",
: () => ("/path-to-inter.woff2").(() => .()),
},
],
});
}Variations & Features
Thanks to underlying engine support, you can control font axes using the font-variation-settings CSS property, or font-feature-settings for OpenType features.
For variable fonts, font-weight has the same effect as font-variation-settings: "wght" <weight>.
<div
style={{
fontFamily: "Manrope",
fontVariationSettings: "'wght' 700, 'wdth' 150",
fontFeatureSettings: "ss01",
}}
>
Variable Font Text
</div>Render Emojis
Dynamic fetching
If you are using ImageResponse API, there's a satori compatible emoji option.
import { } from "takumi-js/response";
export function () {
return new (< ="flex justify-center items-center text-3xl">Hello 👋😁</>, {
: "twemoji",
});
}Under the hood it calls extractEmojis helper function, which separates the emoji segments from the text and modifies the text node.
import { } from "takumi-js/helpers/emoji";
import { } from "takumi-js/helpers/jsx";
import { , } from "takumi-js/helpers";
import { } from "takumi-js/node";
let { } = await (< ="flex justify-center items-center text-3xl">Hello 👋😁</>);
= (, "twemoji");
const = ();
const = await ();
const = new ();
const = await .(, {
,
});COLR/Bitmap Font File
Takumi supports the COLR font format, which is commonly used for emojis like Twemoji-COLR.
The file size is much smaller than rasterized emoji fonts like Noto Color Emoji.
Typography
Overflow Ellipsis
When text-overflow is set to ellipsis, Takumi tries to match the expected line-clamp constraint or maximum container height.
Setting white-space: nowrap is not required, which enables multiline ellipsis handling.
<div
style={{
textOverflow: "ellipsis",
lineClamp: 3,
}}
>
Super Long Text
</div>RTL & Bidirectional Text
Support for Right-to-Left (RTL) languages like Arabic or Hebrew is handled automatically by the underlying Parley engine.
But currently there's no manual control over the direction of the text (see issue #330).
Wrapping
Takumi supports both balance and pretty text wrapping. The algorithm is modified from satori's implementation.
<div style={{ textWrap: "balance" }}>Super Long Text</div>Variable fonts
A single variable font file replaces a whole family. Drive its axes through font-variation-settings; the renderer passes them straight to the shaper.
import { } from "takumi-js/response";
export function () {
return new (
<
={{
: "Manrope",
: "'wght' 700, 'wdth' 110, 'opsz' 48",
: 64,
}}
>
Variable font axes
</>,
{ : 800, : 200 },
);
}font-weight: 700 is shorthand for font-variation-settings: 'wght' 700. Use the longhand when you need to set axes other than weight (width, optical size, slant, italic, or any custom axis the font ships).
Fallback chain
Takumi resolves glyphs in load order. Every font you pass to the renderer becomes a fallback candidate for every Unicode script; when the primary family is missing a glyph, the shaper walks the registered fonts until one supplies it.
Practical consequence: load your text font first, then a color emoji font, then a CJK font, then any script-specific fallback. The first font that owns the glyph wins.
const renderer = new Renderer({
fonts: [
interRegular, // primary Latin
notoColorEmoji, // emoji fallback
notoSansJP, // CJK fallback
notoSansArabic, // Arabic fallback
],
});A character with no provider anywhere in the chain renders as .notdef (the font's "tofu" box). If you see those, you're missing a font for that script.
COLR vs bitmap glyphs
Color emoji ship in two main formats:
| Format | Storage | File size | Best for |
|---|---|---|---|
| COLR (v0 / v1) | Vector layers | ~1 MB | Default. Scales cleanly. |
| CBDT / sbix | Raster bitmap | 5-20 MB | Pixel-accurate match to a target. |
Reach for COLR unless you need byte-identical output with a specific platform (Apple's sbix Apple Color Emoji, for example). Twemoji-COLR is COLR; Google's Noto Color Emoji ships primarily as CBDT/CBLC bitmaps, with separate COLR/COLRv1 builds derived from the same artwork. If you want a per-glyph image instead of a font, see Emoji.
Last updated on