Kaleidoscope logo

Rust · from scratch · no browser dependencies

HTML and CSS in,
a painted image out.

Kaleidoscope is a browser engine in Rust: it parses HTML into a DOM, parses CSS into rules, applies the cascade, lays out boxes, and paints pixels. The whole pipeline, small enough to read end to end. Edit the HTML or CSS below and watch it render, live, right here.

How it works Read the source
ready
Try:
How to use this playground

Edit the HTML in the left box and the CSS in the right box, then press Render to run the full parse, cascade, layout, and paint pipeline onto the canvas. Use Toggle box outlines to see the layout tree drawn over the render, the Try chips to load ready-made examples, and Download PNG to save the painted result.

The whole pipeline, five small stages

No browser engine borrowed, no rendering library included. Every stage below runs the same way in the Rust binary and in the JavaScript powering the demo above.

1

HTML parser

A tolerant tokenizer and tree builder turns tags, attributes, text, and comments into a DOM tree. Unclosed tags recover instead of failing.

2

CSS parser

Selectors (type, id, class, universal, descendant), declarations, lengths, and colors become a stylesheet of rules in source order.

3

The cascade

Rules are matched against every node and sorted by specificity then source order. An inline style attribute always wins, and color and font-size inherit down the tree.

4

Block layout

Each box takes its containing block's width, stacks its children vertically, and derives its own height, honoring margin, border, and padding.

5

Paint

The layout tree becomes a display list of solid rectangles, rasterized with integer alpha compositing into a pixel buffer, then written as a dependency-free PNG or PPM.

// the box model equation layout.rs solves for every box
width + padding + border + margin = containing block width

Read the source, not just the output

The CLI builds the same pipeline as this page. Point it at an HTML file and a stylesheet, and it writes a PNG or PPM image or prints the layout tree with exact pixel coordinates for every box.

kaleidoscope render page.html --css style.css --width 800 -o out.png
kaleidoscope layout page.html --css style.css --width 800

layout prints the box tree, one line per box, with the tag name and the exact pixel coordinates layout solved for it. This is the real output for the bundled example at a 800px viewport:

$ kaleidoscope layout examples/sample.html --css examples/sample.css --width 800
html x=0.0 y=0.0 width=800.0 height=240.0
  body x=0.0 y=0.0 width=800.0 height=240.0
    div x=8.0 y=8.0 width=300.0 height=40.0
      #text x=8.0 y=8.0 width=300.0 height=19.2
    div x=16.0 y=72.0 width=200.0 height=60.0
      #text x=16.0 y=72.0 width=200.0 height=19.2
    div x=16.0 y=164.0 width=200.0 height=60.0
      #text x=16.0 y=164.0 width=200.0 height=19.2

A renderer for agents, not just people

An MCP server exposes a render_html tool that turns HTML and CSS into a PNG. An AI agent can generate markup and see the result without a headless browser. Kaleidoscope boots in milliseconds and uses a couple of megabytes, where a headless Chromium needs seconds and hundreds of megabytes.

kaleidoscope snapshot --html "<div style='background:teal;height:40px'></div>" \
  --css "div{display:block}" --width 200 --height 80
# prints a base64 PNG, the same bytes the MCP tool returns

Small enough to actually read

Kaleidoscope is not trying to render the whole web. It is trying to be the one engine you can follow end to end. The comparison is about comprehensibility, not coverage.

Kaleidoscope

Modern Rust, about 2,000 lines. One render path you can read in an afternoon, with a live demo. Maintained.

Chromium

Tens of millions of lines of C++. Ships the real web, not something a person reads end to end.

Servo

Rust, research-grade and parallelized. Powerful, but hard to trace a single render path through.

Robinson

The classic teaching engine that inspired this space, now an unmaintained tutorial.