The Box Model
20 min
Every element's rendered size is layers: content, then
padding, then border, then margin (space outside the
border, not part of the element itself). The default box-sizing: content-box means a declared width only sets the CONTENT layer —
padding and border get added on top, so the element's actual footprint
grows every time you add padding. box-sizing: border-box instead
treats the declared width as the element's FINAL size, with padding and
border eating into it.
def element_dimensions(content_width, content_height, padding, border, margin, box_sizing="content-box"):
pad_h = padding[1] + padding[3]
pad_v = padding[0] + padding[2]
border_h = border[1] + border[3]
border_v = border[0] + border[2]
margin_h = margin[1] + margin[3]
margin_v = margin[0] + margin[2]
if box_sizing == "content-box":
rendered_width = content_width + pad_h + border_h
rendered_height = content_height + pad_v + border_v
else:
rendered_width = content_width
rendered_height = content_height
return (rendered_width, rendered_height, rendered_width + margin_h, rendered_height + margin_v)
A layout built assuming border-box (predictable sizes) will visibly overflow its intended space if a browser or component accidentally falls back to content-box -- this exact 24px-wider-than-expected surprise is one of the most common real CSS layout bugs, and precisely why border-box is the near-universal recommended default.
Write `element_dimensions(content_width, content_height, padding, border, margin, box_sizing='content-box')`: `padding`/`border`/`margin` are each `(top, right, bottom, left)` tuples. Under `'content-box'` (the default), the rendered box adds padding and border ON TOP of the given content size. Under `'border-box'`, the given width/height ALREADY includes padding and border. Return `(rendered_width, rendered_height, total_space_width, total_space_height)`, where the `total_space_*` values also add in the margin.
Why is `box-sizing: border-box` so commonly recommended over the CSS default (`content-box`)?
You can compute an element's rendered dimensions under both box-sizing models, and understand why border-box is the far more predictable default for layout work.