Exercise 3: Reproducing the Overflow Bug Directly — Possible Solution ==================================================================== THE TEST ------------------------------ viewport = Dimensions(Rect(0, 0, 300, 0), zero, zero, zero) # 300px containing block a_naive = block({'padding': '10px'}) calculate_block_width_naive(a_naive, viewport) a_naive.dimensions.border_box().width a_fixed = block({'padding': '10px'}) calculate_block_width(a_fixed, viewport) a_fixed.dimensions.border_box().width RESULT ------------------------------ naive border_box().width -> 320 (WRONG -- overflows the 300px container) fixed border_box().width -> 300 (correct -- flush with the container) THE EXACT LINE THAT DIFFERS ------------------------------ Both functions are identical except for one branch: Naive: if width_str == 'auto': content_width = containing_block.content.width Fixed: if width_str == 'auto': content_width = (containing_block.content.width - margin.left - margin.right - border.left - border.right - padding.left - padding.right) The naive version's single line, `content_width = containing_block.content.width`, assigns the box's own CONTENT width directly from the container's width with no adjustment at all. The fixed version's multi-line expression starts from that same containing_block.content.width, but then SUBTRACTS this box's own six edge measurements (both margin sides, both border sides, both padding sides) before assigning the result. WORKING THROUGH WHY THIS PRODUCES A 20px OVERFLOW ------------------------------ With padding: 10px and everything else at its default zero: Naive: content_width = 300 (unchanged) border_box().width = content_width + padding.left + padding.right = 300 + 10 + 10 = 320 Fixed: content_width = 300 - 0 - 0 - 0 - 0 - 10 - 10 = 280 border_box().width = content_width + padding.left + padding.right = 280 + 10 + 10 = 300 border_box() itself is identical in both cases -- it's still just expand_rect_by(padding_box(), border), applied to whatever content width the box ended up with. The bug isn't in border_box() at all; the bug is that the naive version fed border_box() a content width that was never actually adjusted to make room for the padding that border_box() was always going to add back on top. WHY THIS WORKS AS AN ANSWER ------------------------------ This confirms the fix isn't about changing what happens AFTER content width is computed (padding_box()/border_box()/margin_box() are untouched, identical code in both versions) -- it's entirely about computing a DIFFERENT content width in the first place, one that already accounts for the fact that padding (and border, and margin) are going to be added back on afterward. Getting 'auto' width right means working backward from "what should the OUTER edge equal" to "what must the content width be," not forward from "the container's width" directly to "the content width," which is exactly the mistake the naive version makes.