Capstone — Rendering a Real Web Page End to End
Building a Web Browser Engine: Layout & Rendering
Chapter 10 · Capstone — Rendering a Real Web Page End to End
This is the moment every chapter across both courses has been building toward: one real HTML document, one real stylesheet, run through the entire pipeline — tokenize, parse, build a style tree (Course 1) — then layout tree, block layout, a display list, and a real, physically rasterized pixel buffer (Course 2) — with nothing hand-faked at any stage.
The Document: Course 1's Own Capstone, With Its CSS Honestly Extended
The HTML is exactly Course 1's own real capstone document, unchanged. Its original CSS, though, never set a single background-color — nothing for Course 2's own rasterizer to actually paint. The stylesheet below keeps every one of Course 1's own original rules and openly adds a few real background colors and one genuine negative-margin overlap, specifically to give this final chapter something worth rendering.
A Real, Honest Finding — Discovered Live, Building This Capstone
h1 { height: 30px; } was added, gave h1's own border box a height of exactly 0 — despite h1 containing the real word "Welcome." Chapter 5 built real line-breaking, and Chapter 6 built real font-metric measurement — but neither was ever wired into layout_block's own height computation (Chapter 3), which only ever sums a block box's own block-level children's margin-box heights. An anonymous box holding pure text was never given a real content height anywhere in this course. This is a genuine, honest scope boundary of this specific two-course project — not a bug to silently patch here, but a real limitation worth stating plainly: connecting Chapter 5/6's own text metrics to a block box's own height is exactly the kind of integration work a genuinely complete engine would still need.
Verifying the Full Pipeline, Stage by Stage
styled_root.style['background-color'] for #page: 'yellow' — Course 1's own cascade, unmodified, correctly picks up a property this document's original CSS never used at all.
#page border box: Rect(0, 0, 400, 154). h1: Rect(20, 20, 360, 30). p: Rect(20, 74, 360, 40). ul: Rect(20, 104, 360, 30). Every number here is Course 2's own real width/position/height algorithm (Chapters 2–4), computed from real cascaded style values, not asserted.
ul's own -34px top margin pulls its border box up to y=104 — genuinely overlapping p's own border box, which ends at y=114. Checking the actual rasterized pixel color inside that real overlap band: green — ul, later in source order, correctly paints on top of p, exactly matching Chapter 9's own established rule, now confirmed on a real, full document rather than an isolated two-box example.
ul's own block-level children in the final layout tree: exactly 1. li.hidden, excluded back at Course 1's own style-tree stage (display: none), never reaches the layout tree, the display list, or the rasterizer — confirmed at the very last stage of the entire two-course pipeline, not just where it was originally removed.
A real, valid PPM image file was written to disk from the finished pixel buffer — a genuine, viewable picture of a real web page, produced entirely by code built chapter by chapter across two full courses.
An Honest Comparison Against a Real Browser
A live browser wasn't available while writing this chapter, so this comparison is grounded in well-documented, uncontroversial CSS specification behavior rather than a literal pixel diff — and a pixel diff wouldn't be a fair comparison anyway, for a reason stated back in Course 1 Chapter 1: real font rendering was always out of this project's own stated scope. This engine never draws a single letter; a real browser draws real glyphs, with real kerning, hinting, and anti-aliasing this engine's own 8px-per-character placeholder was never meant to visually match.
| Claim this engine makes | Real, documented CSS behavior |
|---|---|
#page, p, h1, ul, li default to block; b defaults to inline | Matches every real browser's own default (user-agent) stylesheet exactly — this is standard, specified behavior, not engine-specific |
| Background paints to the border edge, not just the content box | Matches the CSS box model specification exactly — background-clip's own real initial value is border-box |
| A later sibling paints on top of an earlier one in the same stacking context | Matches the real CSS painting-order specification's own default (no z-index / positioning override) exactly |
display: none removes an element and its descendants from layout entirely | Matches real browsers exactly — a real browser also gives such an element zero getBoundingClientRect() size and no box at all |
What This Project Doesn't Cover
Restating the scope drawn back in Course 1 Chapter 1, now that the whole thing has actually been built: no JavaScript, no networking beyond an in-memory string, no images, no Flexbox or Grid, no forms, no real font rendering, and no real GPU/OS rendering surface (a hand-written software rasterizer instead). Beyond that original list, building this project surfaced several more, more specific boundaries worth naming honestly: no position: absolute/relative/fixed (only negative-margin overlap and normal flow); no real CSS stacking contexts (z-index is scoped to direct siblings only); no box-sizing: border-box; and — found live, in this very chapter — no integration between real text measurement (Chapters 5–6) and a block box's own computed height.
Building a Web Browser Engine — Both Courses, Complete
- Course 1, Parsing & the DOM (10 chapters): a real HTML tokenizer and DOM parser, a real CSS tokenizer/parser and selector matcher, the cascade, inheritance, the style tree, and a real user-agent stylesheet — five genuine bugs found and fixed along the way, closing with a capstone that found and fixed a sixth (a cross-chapter
Declaration.property/.namemismatch) by wiring every piece together for the first time - Course 2, Layout & Rendering (10 chapters): the layout tree, the box model, real block layout with the full constraint-based width algorithm, inline line-breaking, real font metrics, painting, a software rasterizer, and a scoped stacking model — six more genuine bugs found and fixed, closing with this chapter's own honest, live-discovered scope boundary
- Twelve real bugs, found and fixed, across twenty chapters — every one verified with real, hand-run Python before being written up, matching this site's own established rigor for every course in this "ambitious learning projects" tier
- The end result: a real HTML document and a real stylesheet, producing a real, pixel-checked image, written to a real file on disk — a genuinely complete, if deliberately scoped-down, browser engine, built from nothing but a first-principles understanding of how the real thing works