Skip to content

HTML Layout ParserWebAssembly-powered HTML/CSS Layout Engine

Extract character-level layout data for Canvas text rendering with multi-font support

About This Project

Design Purpose

This WASM-based solution is designed to provide cross-platform capabilities and Web Worker support that complement existing approaches like SVG foreignObject. It's particularly useful for scenarios requiring:

  • Rendering in Web Workers (where DOM is unavailable)
  • Node.js server-side rendering
  • Precise control over text layout and rendering
  • High zoom levels with pixel-perfect accuracy

For main thread browser environments, SVG foreignObject remains a simpler and more convenient option as it can directly access system fonts without manual loading. Additionally, the WASM solution introduces extra memory overhead beyond the font files themselves. This library is not intended to replace browser-standard SVG solutions, but rather to provide a complementary option for specific scenarios where WASM's unique capabilities are needed.

Quick Example

Direct Import (Recommended)

Now supports direct import from npm package without manual file copying:

bash
npm install html-layout-parser

Vite users need configuration:

typescript
// vite.config.ts
export default defineConfig({
  optimizeDeps: {
    exclude: ['html-layout-parser']
  }
})

Font File Path Recommendation

Place font files in the public directory (not in src) to prevent build tools from renaming them, which would cause WASM to fail loading fonts.

Good: /public/fonts/arial.ttffetch('/fonts/arial.ttf')
Bad: /src/assets/fonts/arial.ttf (may be renamed to arial.abc123.ttf)

typescript
// Direct import from npm package (web environment)
import { HtmlLayoutParser } from 'html-layout-parser/web';

const parser = new HtmlLayoutParser();
await parser.init(); // Uses globally loaded WASM

// Load font from public directory
const fontData = await fetch('/fonts/arial.ttf').then(r => r.arrayBuffer());
const fontId = parser.loadFont(new Uint8Array(fontData), 'Arial');
parser.setDefaultFont(fontId);

// Parse HTML with CSS
const layouts = parser.parse('<div class="title">Hello World</div>', {
  viewportWidth: 800,
  css: '.title { color: blue; font-size: 24px; }'
});

// Render to Canvas
const ctx = canvas.getContext('2d');
for (const char of layouts) {
  ctx.font = `${char.fontSize}px ${char.fontFamily}`;
  ctx.fillStyle = char.color;
  ctx.fillText(char.character, char.x, char.baseline);
}

parser.destroy();

Performance

MetricResult
Parse Speed9,442 - 129,121 chars/sec
Memory UsagePer font ≈ font file size
WASM Size2.25MB
Startup Time~7ms (warm), ~17ms (cold)
Cache Hit Rate91.2%

Released under the MIT License.