Inline Layout & Line Boxes
Building a Web Browser Engine: Layout & Rendering
Chapter 5 · Inline Layout & Line Boxes
Every anonymous box built back in Chapter 1 has sat empty ever since — a real, correctly-shaped wrapper with genuine inline content inside it, but nothing that ever gave that content an actual size. This chapter is where text and inline elements finally get laid out: flattened into a flat sequence, then broken into real line boxes that fit an available width.
8px, regardless of what it actually is. The line-breaking algorithm this chapter builds is real and correct; only the width numbers it's fed are a stand-in.
Flattening Nested Inline Content Into a Flat Word List
"This is " + <b>"bold"</b> + " and normal text." — flattens via collect_words() to exactly ['This', 'is', 'bold', 'and', 'normal', 'text.']. A text box contributes its own words directly; an inline element box like <b> contributes nothing of its own, but the recursion still walks into its children, correctly picking up the text nested one level deeper.
Line-Breaking: A Real Bug in the "Does It Fit" Check
"The quick brown fox jumps over the lazy dog", broken at a 100px available width. The naive algorithm places "jumps", "over", and "the" on one line — their word widths alone sum to 96, which passes the naive 96 <= 100 check. But the real rendered width of that line — three words plus the two real spaces that have to sit between them — is 96 + 16 = 112. A genuine 12px overflow the naive check never even measured, because it only ever tracked word widths, never the spaces the words are actually going to need once they sit next to each other on a real line.
[['The','quick'], ['brown','fox'], ['jumps','over'], ['the','lazy','dog']] — four real lines, each one's true rendered width (words plus every real inter-word space) individually checked and confirmed at or under 100px: 72, 72, 80, and 96.
Where This Connects
| This chapter's finding | What it connects to |
|---|---|
collect_words() walking through nested inline elements | Chapter 1's own anonymous-box grouping — this chapter is the first to actually consume the content those anonymous boxes were built to hold, confirming the grouping mechanism produces something genuinely usable |
| A real, honest placeholder character-width model | Chapter 6's own real font-metric measurement — the exact same break_into_lines() algorithm this chapter built stays unchanged; only measure_word()'s own implementation gets replaced with something accurate |
| Space-width accounted for BEFORE the overflow check, not after | Chapter 3's own real "auto" width overflow bug — the same shape of mistake (checking against a quantity that was measured too narrowly) showing up a second time, in a genuinely different part of this course's own layout engine |
Hands-On Exercises
Run this chapter's own real nine-word sentence through break_into_lines() with a generous 400px available width. Confirm it all fits on a single line, and confirm that single line's own real rendered width (via the chapter's own width-plus-spaces formula) is still verified within the 400px budget rather than just assumed.
Call break_into_lines(['The'], 10) — a single word, in an available width narrower than the word itself. Confirm the word still ends up on its own line rather than being dropped or raising an error, and explain exactly which part of the algorithm guarantees a lone word can never be rejected outright, no matter how narrow the available width is.
Reproduce this chapter's own overflow bug directly: run the real nine-word sentence through both break_into_lines_naive() and break_into_lines() at the same 100px width. For every line in the naive result, compute its real rendered width and confirm exactly one line overflows. Identify the specific variable in break_into_lines_naive that never gets incremented by SPACE_WIDTH_PX, and where the fixed version adds it instead.
Chapter 5 Quick Reference
- collect_words(): flattens an anonymous box's own inline content — plain text and nested inline elements alike — into one flat, ordered word list
- Placeholder measurement: a fixed 8px per character and per space, honestly flagged for replacement by Chapter 6's own real font metrics
- Real bug found and fixed: naive line-breaking accumulates only word widths, never the space that has to sit between them — verified overflowing a real 100px line by 12px on a real nine-word sentence
- The fix: account for one
SPACE_WIDTH_PXbefore every word except the first on a line, as part of the overflow check itself, not as an afterthought - Verified: a lone word too wide for the available space still gets placed on its own line — never dropped, never crashes, matching how real browsers render an unbreakable overflowing word
- Next chapter: Text Measurement & Font Metrics — replacing this chapter's own placeholder width model with something a real browser would actually trust