A minimal web rendering engine written in Rust. It takes an HTML file and a CSS file as input, runs them through a full rendering pipeline, and writes the result to a PNG image.
The engine implements the classic browser rendering pipeline in simplified form:
- HTML parsing — reads an HTML document and builds a DOM tree
- CSS parsing — reads a CSS stylesheet and builds a list of rules
- Style tree — matches CSS rules against DOM nodes and computes their properties
- Layout — calculates the position and size of every box on the page
- Painting — rasterizes the layout to a pixel buffer and saves it as a PNG
src/
├── dom.rs DOM node types (element, text, comment)
├── css/
│ └── mod.rs CSS data types (selectors, values, rules, stylesheet)
├── style/
│ ├── mod.rs re-exports and module declarations
│ ├── matching.rs selector matching against DOM nodes
│ ├── cascade.rs specificity-based cascade and specified values
│ ├── tree.rs StyledNode, Display, style tree construction
│ └── tests.rs
├── layout/
│ ├── mod.rs re-exports and module declarations
│ ├── types.rs Rectangle, EdgeSizes, Dimensions, LayoutBox, BoxType
│ ├── block.rs block layout algorithm
│ ├── inline.rs inline and anonymous block layout
│ ├── tree.rs layout tree construction
│ └── tests.rs
├── painting/
│ ├── mod.rs re-exports and module declarations
│ ├── display_list.rs display list generation (background, borders, text)
│ ├── canvas.rs pixel buffer rasterization and PNG output
│ └── tests.rs
├── parser/
│ ├── mod.rs re-exports and module declarations
│ ├── text/
│ │ ├── mod.rs low-level character-by-character parsing utilities
│ │ └── tests.rs
│ ├── css/
│ │ ├── mod.rs CSS parser, produces a stylesheet
│ │ └── tests.rs
│ └── html/
│ ├── mod.rs HTML parser, produces a DOM tree
│ └── tests.rs
├── lib.rs re-exports all modules as a public library
└── main.rs command-line entry point
examples/
├── test.html sample HTML document
└── test.css sample CSS stylesheet
You need Rust and Cargo installed. If you don't have them yet, follow the guide at https://www.rust-lang.org/learn/get-started.
Clone the repository and run it with Cargo. By default it reads examples/test.html and examples/test.css and writes output.png.
git clone https://github.com/federicobaldini/web-rendering-engine
cd web-rendering-engine
cargo runYou can point it at different files using command-line flags:
cargo run -- --html path/to/file.html --css path/to/file.css --output result.pngcargo testThis runs the unit tests (one per module).
HTML
The parser handles elements, text nodes, comments, self-closing tags (br, img, input, meta, link, hr), and attributes with single or double quotes. It recovers gracefully from common errors: boolean attributes without a value, unquoted attribute values, unclosed elements, and mismatched closing tags.
CSS
The parser handles type, id, and class selectors with specificity-based cascade ordering. Supported values are pixel lengths, hex colors (#RRGGBB), and keywords. It recovers from invalid declarations by skipping them and from invalid rules by skipping the whole block.
Layout
The engine implements the CSS block, inline, and inline-block layout algorithms from the CSS 2.1 specification, including the box model (content, padding, border, margin), automatic width distribution, vertical stacking of block children, and horizontal placement of inline and inline-block children with line wrapping.
Painting
Each element's background and borders are painted to a pixel buffer. The result is saved as a PNG using the image crate.
Text color and font size are not inherited from parent elements yet, so all text renders in black at 16px regardless of CSS. Text rendering depends on the Arial font at /System/Library/Fonts/Supplemental/Arial.ttf; on systems where that file is absent, text is silently skipped. Other missing features are tracked in TODO.md.
