#css #flexbox #layout-engine #algorithm #grid #pdf #web-page #inline-css #geometry

no-std cssbox-core

Standalone CSS layout engine — core algorithms

1 unstable release

new 0.1.0 Feb 13, 2026

#5 in #grid

MIT license

170KB
4K SLoC

cssbox

CI Crates.io docs.rs License: MIT

A standalone CSS layout engine in Rust. HTML/CSS in, exact coordinates out.

Built for PDF generation, document rendering, native UI, and anywhere you need CSS layout without a browser.


The Problem

If you need to lay out a document with CSS — generate a PDF from HTML, render rich text in a native app, build an e-book reader — your options are:

  • Headless Chrome/Puppeteer — works, but it's a 200MB dependency that spawns a browser process
  • WeasyPrint — Python-only, slow, flexbox/grid support is incomplete
  • Prince XML — proprietary, expensive
  • wkhtmltopdf — deprecated and unmaintained

Libraries like Yoga and Taffy are great for app-style UI (flexbox/grid), but they don't handle document-style layout — inline text flow, floats, tables, or the CSS cascade. They solve a different problem.

cssbox fills the gap: a fast, embeddable Rust library that handles the full CSS layout spec, from modern flexbox/grid to traditional document flow.

Getting Started

[dependencies]
cssbox-core = "0.1"
use cssbox_core::tree::BoxTreeBuilder;
use cssbox_core::style::ComputedStyle;
use cssbox_core::geometry::Size;
use cssbox_core::layout::{compute_layout, FixedWidthTextMeasure};
use cssbox_core::values::LengthPercentageAuto;

// Build a tree of styled nodes
let mut builder = BoxTreeBuilder::new();
let root = builder.root(ComputedStyle::block());

let mut child_style = ComputedStyle::block();
child_style.width = LengthPercentageAuto::px(200.0);
child_style.height = LengthPercentageAuto::px(100.0);
let child = builder.element(root, child_style);

let tree = builder.build();

// Compute layout against an 800x600 viewport
let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0));

// Query the result — just like getBoundingClientRect()
let rect = result.bounding_rect(child).unwrap();
assert_eq!(rect.width, 200.0);
assert_eq!(rect.height, 100.0);

From HTML/CSS

use cssbox_dom::computed::html_to_box_tree;
use cssbox_core::geometry::Size;
use cssbox_core::layout::{compute_layout, FixedWidthTextMeasure};

let tree = html_to_box_tree(r#"
    <div style="display: flex; gap: 10px">
        <div style="flex: 1; height: 100px"></div>
        <div style="flex: 2; height: 100px"></div>
    </div>
"#);

let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0));

What It Supports

cssbox implements 7 CSS layout modes — both the modern layout primitives (flexbox, grid) and the traditional document flow (block, inline, float) that document rendering requires.

Algorithm Spec What it covers
Block CSS 2.1 §9.4.1 Width/height determination, margin collapsing, box-sizing, min/max constraints, percentages
Inline CSS 2.1 §9.4.2 Line box construction, greedy line breaking, text-align, vertical-align, white-space
Float CSS 2.1 §9.5.1 Left/right placement, exclusion zones, clear, BFC containment
Positioning CSS 2.1 §9.3 relative, absolute, fixed, sticky, constraint solving, stretch
Flexbox Flex Level 1 Direction, wrapping, grow/shrink, all alignment and spacing modes
Grid Grid Level 2 Track sizing (fr, minmax(), fit-content()), auto-placement, gap
Table CSS 2.1 §17 Fixed and auto layout, border-collapse/border-spacing, captions

Landscape

Existing embeddable layout libraries are purpose-built for app UI (flexbox/grid) and intentionally skip document layout. Full browsers handle everything but aren't embeddable. cssbox sits in the middle.

Embeddable libraries

Engine Language Stars Document layout App layout
Yoga C++ 18.7k Flexbox
Taffy Rust 3k Block only Flexbox, Grid
Dropflow TS/Zig 1.4k Block, Inline, Float
cssbox Rust Block, Inline, Float, Table Flexbox, Grid

Full browsers and renderers (not embeddable as libraries)

Engine Notes
Servo Rust browser engine. Uses Taffy for flex/grid. Inline/float still incomplete (18-52% WPT).
NetSurf C browser. Strong CSS 2.1 + flexbox. No grid.
Ladybird C++ browser. Pre-alpha. Targeting full CSS.
WeasyPrint Python PDF renderer. Best document layout coverage, but flexbox/grid marked "not deeply tested".

Use Cases

  • PDF / document generation — HTML/CSS to precise coordinates, then render to PDF
  • Rich text UI — document-style layout in native apps (editors, readers, email clients)
  • Native UI — CSS layout without a webview
  • Embedded devices — small footprint, zero runtime dependencies
  • Testing tools — verify CSS layout behavior programmatically

Crate Structure

Crate Description
cssbox-core Core layout algorithms. Zero dependencies, no_std compatible.
cssbox-dom HTML/CSS parsing, selector matching, cascade, computed values.
cssbox-test-harness WPT test infrastructure (reftest + testharness.js).

Text Measurement

cssbox doesn't measure text — you provide the font metrics via a trait:

pub trait TextMeasure {
    fn measure(&self, text: &str, font_size: f32, max_width: f32) -> Size;
}

A built-in FixedWidthTextMeasure (8px/character) is included for testing. For production, plug in your font rasterizer (e.g., rusttype, fontdue, cosmic-text).

Testing

cargo test --workspace              # all 97 tests
cargo test -p cssbox-core           # core layout tests
cargo test -p cssbox-core block     # specific algorithm
cargo test -p cssbox-core flex
cargo test -p cssbox-core grid

Contributing

Contributions are welcome! The biggest impact areas:

  1. WPT pass rate — pick a failing test, fix the layout algorithm
  2. Missing CSS properties — add parsing + layout support
  3. Text shaping — improve inline layout with real text measurement
  4. Performance — layout caching, incremental relayout

License

MIT


lib.rs:

cssbox-core — A standalone CSS layout engine.

This crate implements CSS layout algorithms: block, inline, float, positioning, flexbox, grid, and table. It takes a tree of styled nodes as input and produces computed positions and sizes as output.

Usage

use cssbox_core::tree::BoxTreeBuilder;
use cssbox_core::style::ComputedStyle;
use cssbox_core::geometry::Size;
use cssbox_core::layout::{compute_layout, FixedWidthTextMeasure};

let mut builder = BoxTreeBuilder::new();
let root = builder.root(ComputedStyle::block());
// ... add children ...
let tree = builder.build();

let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0));
let root_rect = result.bounding_rect(tree.root());

No runtime deps

Features