Chapter 8 — Box Model, Margin and Padding
Section 1 — Every element is a box
Every element on a web page is a box. That single idea is the foundation of all CSS layout, and it is worth stating plainly before any detail: when the browser renders a page, it does not deal in loose text and pictures floating on a canvas, but in rectangular boxes, nested inside each other like boxes within boxes. A paragraph is a box, a heading is a box, a link is a box, an image is a box, and the page itself is a box containing all the others. Understanding layout means understanding those boxes: how big they are, what is inside them, how far apart they sit, and how they are arranged relative to each other.
The box model is the name for the structure of each of those boxes. From the inside out, a box has four layers: the content, which is the element's actual text, images, or child elements; the padding, which is space inside the box, around the content; the border, which is a line around the padding; and the margin, which is space outside the border, separating the box from its neighbours. Every element has all four layers, even if some of them are zero — an element with no padding still has a padding layer of zero width, and an element with no border still has a border layer of zero width. The layers are always there conceptually, which is why the model is so reliable for reasoning about layout.
Why does this matter so much? Because most layout confusion is box-model confusion. When an element is wider than expected, it is usually because padding or border was added to its width. When two elements are further apart than expected, or closer together than expected, it is usually margin behaving in a way the author did not anticipate — collapsing, as Sections 12 to 14 explain, or being absorbed by a parent. When a background colour stops short of where you expected, it is usually because backgrounds paint the padding area but not the margin, a distinction covered in Sections 30 and 31. Learning the box model does not just teach you four new words; it gives you a mental picture that explains a large share of everything you will ever see go wrong in layout.
The rest of this chapter works through the model layer by layer, then through the interactions between layers, and finally through the practical decisions — padding or margin, border or outline, fixed or flexible sizing — that you will make on every page. By the end, you should be able to look at any element, picture its four layers, and predict how changing any one of them will affect the element and its neighbours. That picture is the single most valuable mental model in CSS layout, and it is the foundation on which the layout chapters that follow — on flow, flexbox, and grid — are built.
Check: Name the four layers of the box model, from inside out.
Section 2 — The content area
The content area is the innermost layer of the box: the space occupied by the element's actual content, whether that is text, an image, or child elements. Its size is controlled by the width and height properties, together with the box-sizing property, which determines whether those properties measure the content alone or the content plus padding and border — a distinction that is important enough to deserve its own sections later in this chapter. For now, think of the content area as the box's working space: the region where the element's meaning lives, and around which all the other layers are arranged.
For text elements, the content area's width determines how long each line is, and its height grows with the number of lines, unless a fixed height constrains it. That growth is automatic: a paragraph with no explicit height expands vertically to fit its text, wrapping lines as needed, and its box grows with it, pushing subsequent content down the page. That automatic growth is the default behaviour of block-level elements, and it is what makes web pages flexible: content of any length can be accommodated, because boxes grow to fit it, rather than requiring the author to predict every height in advance. Fixed heights, covered in Section 6, are the exception, used when a box must be a particular size regardless of its content.
For replaced elements like images, the content area is the image itself, at its natural size unless width or height overrides it. An image with no sizing rules displays at its intrinsic dimensions — the pixel dimensions of the image file — and its box is exactly that size, plus any padding, border, and margin. That is why an oversized image can overflow its container and break a layout: its content area is larger than the space available, and nothing in the box model automatically shrinks it. The remedy, covered in Section 33, is to constrain the image's width, usually with a maximum width, so that its content area adapts to its container.
The content area is also where backgrounds begin: an element's background colour or image paints the content and padding areas, but not the border or margin, a point that becomes important when you reason about why a coloured area ends where it does. And it is the area that padding protects: padding exists to keep content from touching the border, giving text and images breathing room inside the box. Understanding the content area as a distinct layer, separate from the padding that surrounds it, is the first step in seeing a box as a structured object rather than as an undifferentiated rectangle — and that structured view is what the rest of this chapter builds on.
Check: What sits in the content area of a paragraph's box?
Section 3 — Padding
Padding is the space inside an element's border, around its content. It pushes the content inward, away from the edges of the box, and it is part of the element's own area: a background colour extends across the padding, and a border sits outside it. Padding is best understood as breathing room that belongs to the element itself. When a button's text feels cramped against its edges, padding is the remedy: adding padding inside the button enlarges the button's coloured area and gives the text room, without moving neighbouring elements, because the space is inside the button's own box. When a card's text touches its border, padding is again the remedy, for the same reason.
Padding is set with the padding property, which can take one value for all four sides, or separate values for each side, using the shorthand forms covered in Section 9. It can be given in pixels, ems, rems, or percentages, with percentages measured against the containing block's width — a quirk covered in Section 11 that surprises many developers. Padding cannot be negative: there is no such thing as negative breathing room inside a box, and a negative padding value is invalid and ignored. That constraint makes sense when you picture the model: padding separates content from border, and a negative separation would mean content overlapping the border, which is not a meaningful layout state.
The visual effect of padding depends on the element's background and border. On an element with no background and no border, padding is invisible — it simply pushes the content away from neighbouring content, which can look identical to margin, and beginners often confuse the two in that situation. On an element with a background colour, padding is clearly visible as the coloured area around the content, because the background paints the padding. On an element with a border, padding is the gap between the content and the border line. That is why padding is the right tool for "space inside the coloured or bordered area" and margin is the right tool for "space between separate areas": the distinction is visible exactly when backgrounds and borders are present, and it is worth testing with a background colour when you are unsure which one you need.
Padding also affects the element's total size, unless box-sizing: border-box is in effect, as Sections 7 and 8 explain. By default, padding is added to the content width, so a box with a content width of 200 pixels and 20 pixels of padding on each side is 240 pixels wide in total. That addition is the source of many "why is this wider than I set?" puzzles, and it is the reason the border-box model, which includes padding in the declared width, is so widely preferred. For now, the key idea is simple: padding is inside space, it belongs to the element, it carries the element's background, and it grows the box unless border-box says otherwise.
Check: Is padding inside or outside an element's border?
Section 4 — The border
The border is a line around the padding and content, marking the edge of the element's box. It has three aspects — style, width, and colour — each controlled by its own property, or all three together by the border shorthand, covered in Section 19. A border is optional: most elements have no visible border by default, and adding one is a deliberate design choice, used to delineate a card, to outline a button, to separate a section, or to draw attention to a form field. When a border is present, it sits between the padding and the margin, and it is the visible boundary of the element's box.
Border style is what makes a border visible at all. The default style is none, which means no border is drawn, regardless of width or colour — a common beginner puzzle is setting a border width and colour but forgetting the style, and seeing nothing, because without a style there is no line to draw. The most common styles are solid, a continuous line; dashed, a series of short dashes; and dotted, a series of dots. Other styles — double, groove, ridge, inset, outset — create three-dimensional or double-line effects, but they are used less often in modern flat design, and their appearance varies between browsers. For most work, solid is the default choice, with dashed and dotted for special cases like draft boundaries or decorative dividers.
Border width is the thickness of the line, usually given in pixels, and border colour is the line's colour, given in any colour format from Chapter 7. Both default to sensible values — a medium width and the element's text colour, via currentColor — but they are normally set explicitly, because the defaults rarely match a design. Like padding, border width is added to the element's total size by default, so a 200-pixel box with a 2-pixel border on each side is 204 pixels wide, unless border-box sizing includes it. That addition is small for thin borders, but it matters for precise layouts, and it is another reason border-box is preferred.
Borders also interact with border-radius, covered in Section 20, which rounds the corners of the border, and with the box model generally, because the border is the boundary that backgrounds stop at and margins start from. A background paints up to the border's inner edge, not beyond it, and the margin begins at the border's outer edge. The border is therefore the element's edge in every sense: visually, it is the line you see; structurally, it is the dividing line between the element's own area (content plus padding) and the space around it (margin). Seeing the border that way — as the box's edge, not just as a decorative line — clarifies why it sits where it does in the model, and why it matters even when it is invisible.
Check: Which three aspects define a border?
Section 5 — Margin
Margin is the space outside an element's border, separating the box from its neighbours. It is transparent — it has no background of its own — and it pushes other elements away, rather than enlarging the element itself. If padding is breathing room inside the box, margin is breathing room between boxes, and that distinction is the most important idea in this chapter. When you want two buttons further apart, you add margin, because the gap should be between them, not inside either of them. When you want a button's coloured area to grow, you add padding, because the growth should be inside the button. Choosing correctly between them is a decision you will make constantly, and Section 48 returns to it as a decision guide.
Margin is set with the margin property, which, like padding, can take one value for all sides or separate values per side, using the shorthand forms covered in Section 10. Unlike padding, margin can be negative, which pulls neighbouring elements closer, even overlapping them — a technique covered in Section 15 that is powerful but should be used deliberately. Margin can also be given in pixels, ems, rems, or percentages, with percentages again measured against the containing block's width, even for top and bottom margins, which is a quirk worth remembering from Section 11. And margin can be auto, which has a special centring behaviour for horizontal margins, covered in Section 16.
The transparency of margin is a key property. Because margin has no background, the parent's background shows through it, which is why a card with a margin on a grey page appears to float on grey, with the grey visible in the gap. That is different from padding, where the element's own background fills the space. It also means that margin cannot be used to create a coloured gap: if you want a coloured band between two elements, that band must be padding on one of them, or a separate element with its own background, because margin itself will always show whatever lies behind the element. Beginners sometimes set a margin expecting a coloured gap and are puzzled when the parent's colour shows instead; the explanation is always the same — margin is empty space, not coloured space.
Margin also has a unique behaviour that no other layer shares: vertical margins collapse, as Sections 12 to 14 explain in detail. When two vertical margins meet, they do not add together, as you might expect, but combine into a single margin equal to the larger of the two. That behaviour is the source of more layout surprises than any other single feature of the box model, and it is the reason this chapter devotes three sections to it. For now, hold the basic picture: margin is outside space, it is transparent, it separates boxes, and it follows rules of its own that you must learn before you can predict spacing reliably.
Check: Does margin enlarge an element's coloured area, or push neighbours away?
Section 6 — Width and height
width and height set the size of an element's box, but what exactly they measure depends on box-sizing, covered in the next two sections. By default, they measure the content area only, with padding and border added on top. That default — called content-box sizing — is the historical behaviour of CSS, and it is the source of the most common sizing surprise: an element declared at 200 pixels wide, with 20 pixels of padding on each side, is actually 240 pixels wide on screen, because the padding is added to the declared width. Understanding that addition, and the alternative that avoids it, is essential to controlling layout.
Width is more commonly set than height, and for good reason. Block-level elements naturally fill the available width of their container, so setting a width is usually about constraining that natural behaviour — making a column narrower than the full page, for instance, or giving a card a fixed width. Height, by contrast, is usually left automatic, so that the box grows with its content, whatever its length. Setting a fixed height is riskier, because content can exceed it: text can be longer than expected, a translation can be wordier, a font can render larger, and a box with a fixed height will then overflow, clipping its content or spilling it over neighbouring elements, unless overflow is handled, as Sections 23 and 24 explain. The professional default is therefore: set widths deliberately, let heights be automatic, and set a fixed height only when the design genuinely requires a box of a particular size regardless of content.
Widths and heights can be given in absolute units like pixels, in relative units like ems, rems, and percentages, or in viewport units that relate to the browser window. Percentages for width are relative to the containing block's width, which makes them the natural unit for fluid layouts: a sidebar at 25% and a main column at 75% adapt to any screen width, because they are proportions, not fixed sizes. Percentages for height, however, are relative to the containing block's height, and they only work if that height is itself determined — a percentage height inside a container whose height is automatic resolves to automatic as well, which is a frequent source of "my percentage height does nothing" puzzles, covered in Section 42.
There is also the distinction between the declared size and the rendered size. The declared size is what you write in the stylesheet; the rendered size is what the browser actually paints, after padding, border, and box-sizing have been applied, and after constraints like minimum and maximum sizes, covered in Section 25, have been considered. A width of 200 pixels with 20 pixels of padding is rendered at 240 pixels under content-box sizing, but at 200 pixels under border-box sizing, because border-box includes the padding in the declared width. That difference is not a minor detail; it determines whether a layout adds up. A row of four cards at 25% width each, with padding, fits perfectly under border-box, because each card is exactly 25% including its padding, but overflows under content-box, because each card is 25% plus its padding. That arithmetic is why border-box is now the standard, and why the next two sections matter so much.
Check: Under default sizing, what is the total width of a 200px box with 20px padding on each side?
Section 7 — Box-sizing: content-box
box-sizing: content-box is the default sizing model, in which width and height measure only the content area, and padding and border are added on top. It is called content-box because the box that width and height describe is the content box — the innermost layer. Under this model, the total width of an element is the declared width, plus left and right padding, plus left and right border widths. The total height is calculated the same way, with top and bottom padding and borders added to the declared height. Margin is never included in either total, under either model, because margin is outside the box, not part of it.
Content-box sizing is logical if you think of width as "how much room for content", which was the original intention: an author who sets a paragraph to 400 pixels wide is saying "I want 400 pixels of text per line", and the padding and border are additional, surrounding that text. For text-heavy layout, that reading makes sense, because line length — the width of the text itself — is the readability factor that matters, as Chapter 7, Section 35 explained, and padding should not reduce it. If padding were included in the width, then adding padding would narrow the text, changing line length in a way the author did not intend. Content-box preserves the text width, at the cost of making the total width harder to predict.
That cost is significant in practice. Every time you add padding or a border to a sized element, you must recalculate its total size, and every time you change the padding, the total changes. For a grid of cards, a row of columns, or any layout where elements must add up to a precise total — four quarters, three thirds, a sidebar plus a main column — content-box arithmetic becomes a burden, because the padding must be subtracted from the declared width by hand, and any later change to padding breaks the arithmetic. That burden is why content-box, despite being the default, is rarely what developers actually want for layout, and why the alternative in the next section is so widely adopted.
Content-box remains the default for historical reasons: it was the model in the earliest CSS specifications, and changing the default would have broken existing pages that depended on it. Browsers therefore keep it as the initial value, and developers who want the alternative must opt into it explicitly, usually with a global rule that applies border-box to every element, as Section 38 explains. Knowing content-box matters, even if you rarely use it directly, because it is what you get when no box-sizing rule applies, because it explains the behaviour of older code, and because it clarifies what border-box changes: not the layers themselves, but which layer the width and height measure. The layers are the same in both models; only the measuring point differs, and that difference changes everything about layout arithmetic.
Check: Under content-box, is padding included in the declared width?
Section 8 — Box-sizing: border-box
box-sizing: border-box changes the measuring point so that width and height include the content, padding, and border together. A box declared at 200 pixels wide is 200 pixels wide in total, whatever its padding and border, with the content area shrinking to fit inside. That single change removes the arithmetic burden of content-box sizing, and it matches how most people intuitively think about size: when you say a card is 200 pixels wide, you mean the whole card, including its padding and border, not just its text area. The content area becomes whatever remains after padding and border are subtracted from the declared size, rather than the declared size itself.
The practical benefit is most visible in grids and columns. Four cards at 25% width each, with 16 pixels of padding and a 1-pixel border, fit exactly into a row under border-box, because each card's total is exactly 25%, and the padding lives inside that 25%. Under content-box, the same cards would each be 25% plus 34 pixels, overflowing the row and wrapping the last card onto a new line — a classic layout bug that has frustrated countless beginners, and that border-box eliminates entirely. The same logic applies to a sidebar and main column, to form inputs that must fill their container, and to any element whose total size must be predictable. Border-box makes declared sizes mean total sizes, which is what layout arithmetic needs.
Adopting border-box is normally done globally, with a rule that applies it to every element, including pseudo-elements, because a mixture of models in one page reintroduces the very unpredictability border-box is meant to remove. The standard rule is *, *::before, *::after { box-sizing: border-box; }, placed at the top of the stylesheet, so that every box on the page follows the same measuring convention. The inclusion of pseudo-elements matters, because ::before and ::after create boxes too, and they should follow the same rule as ordinary elements. Once that global rule is in place, you can largely stop thinking about box-sizing: declared widths mean total widths, padding and borders live inside them, and layout arithmetic becomes addition of declared sizes, which is straightforward.
There is one adjustment to make when switching to border-box thinking: content width is no longer directly controlled. If you need a specific text width — a line length of 60 characters, for instance — you must account for padding, because the text area is the declared width minus padding. In practice, that adjustment is rarely a problem, because padding is usually modest relative to width, and because line length can be controlled with a maximum width on a text container that has no padding, or with the ch unit, rather than by precise content-box arithmetic. The trade-off overwhelmingly favours border-box: a small loss of direct control over content width, in exchange for total widths that mean what they say. That is why border-box is the professional default, and why this chapter, and the layout chapters that follow, assume it unless stated otherwise.
Check: Under border-box, what does a declared width of 200px include?
Section 9 — Padding shorthand
Padding can be set for all sides at once, or per side, using shorthand values: one value sets all four sides, two values set vertical then horizontal, three values set top, horizontal, then bottom, and four values set top, right, bottom, then left, clockwise from the top. The shorthand is a compact way to express what would otherwise be four separate declarations, and its value-count rules are worth memorising, because they apply identically to margin, border-width, and several other properties — learning them once covers a whole family of shorthands.
With one value, as in padding: 16px;, all four sides get that padding. That is the most common form, used when a box needs even breathing room on all sides, such as a card or a button. With two values, as in padding: 16px 24px;, the first is the vertical padding — top and bottom — and the second is the horizontal padding — left and right. That form suits elements that need more horizontal than vertical room, like buttons, whose text needs more side room than top room, or less, depending on the design. With three values, as in padding: 16px 24px 8px;, the values are top, horizontal (left and right together), and bottom — the missing fourth value, the left, is copied from the right, because opposite sides mirror each other when only one of the pair is given. With four values, as in padding: 16px 24px 8px 4px;, the values are top, right, bottom, and left, in clockwise order starting from the top — a sequence often remembered as "top, right, bottom, left", or by the mnemonic that it goes around the clock.
The mirroring rule — that a missing value is copied from its opposite — is the key to the shorthand's logic, and it is consistent across all the two- and three-value forms. In the two-value form, the missing bottom is copied from the top, and the missing left from the right. In the three-value form, only the left is missing, and it is copied from the right. That rule means you never need to repeat a value unnecessarily: if left and right are equal, you write the value once, as the second value, and the shorthand supplies it for both sides. It also means that reading a shorthand requires counting values first, because the same number can mean different sides depending on how many values there are — padding: 16px 24px; is vertical then horizontal, not top then right, a distinction that trips up beginners who assume the values always start at the top and proceed clockwise regardless of count.
Individual sides can also be set with longhand properties — padding-top, padding-right, padding-bottom, padding-left — which are useful when only one side needs changing, or when overriding a shorthand for a single side in a more specific rule. A common pattern is a shorthand for the general case, followed by a longhand override for an exception, as in padding: 16px; padding-top: 8px;, which gives all sides 16 pixels except the top, which gets 8. That pattern works because the longhand, appearing later and targeting the same property aspect, overrides the shorthand's value for that side only.
Check: In padding: 10px 20px;, which sides get 10px and which get 20px?
Section 10 — Margin shorthand
Margin shorthand follows the same value-count rules as padding: one value for all sides, two for vertical then horizontal, three for top, horizontal, then bottom, and four for top, right, bottom, then left, clockwise. The rules are identical because margin and padding are parallel layers of the box model, and CSS reuses the same shorthand logic for both, as well as for border-width and other four-sided properties. Learning the pattern once, in the previous section, therefore covers margin as well, and the value of this section is less in repeating the pattern than in noting the differences between margin and padding shorthand in practice — differences that arise from margin's unique behaviours, not from its syntax.
The most important practical difference is that margin shorthand is where margin collapsing, covered in the next sections, is most often encountered. When you write margin: 16px 0; on a series of paragraphs, you are setting 16 pixels of top and bottom margin on each, but the rendered gap between two paragraphs is not 32 pixels, as simple addition would suggest, but 16 pixels, because the adjacent vertical margins collapse into one. That behaviour is independent of whether the margin was set by shorthand or longhand — the shorthand is only a way of writing the values, and collapsing applies to the values themselves — but it is most often discovered through shorthand, because shorthand is how vertical margins are usually set. Understanding that shorthand does not change collapsing, and that collapsing is a property of margins themselves, prevents the mistaken belief that writing margins differently will avoid it.
Another practical difference is the auto value, which is meaningful for margins but not for padding. A horizontal margin set to auto absorbs available space, which is the mechanism behind centred blocks, covered in Section 16. Shorthand can express that: margin: 0 auto; sets top and bottom margins to zero and left and right margins to auto, centring a fixed-width block horizontally — one of the most commonly written declarations in all of CSS. Padding has no equivalent, because padding cannot be auto; there is no "available space" inside a box for padding to absorb, since padding is defined by the author, not by the layout. The presence of auto in margin shorthand is therefore a distinctive and frequently used pattern, worth recognising on sight.
Negative margins, covered in Section 15, also appear in shorthand, as in margin: -8px 0;, which pulls the element's top and bottom neighbours closer by 8 pixels each. Like auto, negative values have no padding equivalent, because padding cannot be negative. And individual sides can be overridden with longhand properties — margin-top, margin-right, and so on — following the same general-then-exception pattern as padding: a shorthand for the general case, a longhand for the side that differs. The symmetry between margin and padding shorthand is deliberate and helpful: once you can read one, you can read the other, and the differences between them are the differences between the layers themselves — margin's collapsing, its auto behaviour, and its ability to be negative — not differences in syntax.
Check: In margin: 0 auto;, which margins are zero and which are auto?
Section 11 — Padding percentages
Percentage padding is measured against the width of the containing block, even for top and bottom padding. That single sentence contains one of the most surprising facts in CSS layout, and it deserves careful unpacking, because it contradicts the intuitive expectation that vertical percentages would relate to height. If a container is 400 pixels wide and 800 pixels tall, and a child inside it has padding-top: 10%;, that top padding is 40 pixels — 10% of the container's width — not 80 pixels, which would be 10% of its height. The rule applies to all four sides: left, right, top, and bottom percentages all resolve against the containing block's width.
The reason for this rule is historical and practical. In the early web, a container's height was often undetermined — it depended on its content, which depended on the padding, which would depend on the height, creating a circular dependency that browsers could not resolve. Width, by contrast, is usually determined before content is laid out, because block elements fill their container's width by default, so width is a stable basis for percentages. Basing all percentage padding on width avoids the circularity, and it has a useful side effect that modern developers exploit: an element with percentage padding maintains a consistent aspect ratio as its width changes, because its vertical padding scales with its width. A box with padding-top: 56.25%; inside a fluid container maintains a 16:9 ratio, because 56.25% is 9 divided by 16 — a technique once widely used for responsive video embeds, before the aspect-ratio property provided a more direct solution.
That aspect-ratio technique is worth understanding, even now that aspect-ratio exists, because it illustrates how a quirk can become a tool. A container with no content and a top padding of 56.25% of its own width will have a height equal to 56.25% of its width, whatever the width, because the padding creates the height. An absolutely positioned child can then fill that padded area, producing a box that scales proportionally at any screen size. The technique is a workaround, and aspect-ratio is now the cleaner way to achieve the same result, but the underlying principle — vertical percentages tied to width — is still the rule for padding, and it still surprises developers who expect vertical percentages to follow height.
For ordinary padding, the practical advice is to avoid percentage padding unless you specifically want the width-based behaviour. Pixel, em, and rem padding are predictable in both directions: 16 pixels of top padding is 16 pixels, regardless of the container's width, which is usually what an author intends when they write padding for breathing room. Percentage padding is for the cases where width-relative scaling is desired — aspect ratios, fluid gutters that scale with the container, or spacing that should grow with the layout rather than staying fixed. When you do use it, remember the rule explicitly: all sides, width basis, always. Writing that rule on a comment beside a percentage padding declaration is a kindness to the next developer, who will otherwise assume, reasonably but wrongly, that top and bottom percentages relate to height.
Check: A container is 400px wide. How many pixels is a child's padding-top: 10%?
Section 12 — Margin collapsing: the basics
When two vertical margins meet, they do not add together — they collapse into a single margin equal to the larger of the two. That is margin collapsing, and it is the box model's most surprising behaviour. If a paragraph with a bottom margin of 20 pixels is followed by a paragraph with a top margin of 30 pixels, the gap between them is 30 pixels, not 50. The two margins overlap, like two shadows falling on the same spot, and only the larger is visible. That is not a bug or a browser inconsistency; it is specified behaviour, designed for a specific purpose, and understanding that purpose makes the behaviour feel less arbitrary.
The purpose relates to the typographic tradition that CSS inherited. In print, the space between paragraphs, and between a heading and the paragraph that follows it, is a single, deliberate gap, not the sum of two separate gaps. If each paragraph contributed its own margin, then the space between paragraphs would be double the space that the designer intended for a paragraph break, and the space between a heading and its first paragraph would be the heading's bottom margin plus the paragraph's top margin, producing an inconsistent rhythm. Collapsing ensures that the gap between two blocks is the larger of the two blocks' desired gaps, which preserves the designer's intent: each block declares how much space it wants around itself, and the actual gap is the maximum of the neighbouring declarations, not their sum. That produces a consistent vertical rhythm, where the spacing between blocks is determined by the block that wants the most space, rather than by adding everyone's wishes together.
Collapsing applies only to vertical margins — top and bottom — never to horizontal margins, which always add. Two side-by-side elements with left and right margins of 20 pixels each are separated by 40 pixels, because horizontal margins do not collapse. That asymmetry reflects the different roles of the two directions: vertical spacing in a document is about rhythm between successive blocks, where a single gap makes sense, while horizontal spacing in a row is about separation between distinct items, where addition makes sense. It also means that collapsing surprises are always vertical: if a horizontal gap is wrong, collapsing is not the explanation, and the cause lies elsewhere.
Collapsing also applies only to margins that are actually adjacent — that is, margins with nothing between them: no border, no padding, no content, and no clearance. If a border or padding intervenes, the margins are separated and do not collapse, which is why adding a border or padding to a parent can "fix" a collapsing problem, as the next sections explain. And collapsing involves only margins themselves, not padding or borders, which never collapse. Those conditions — vertical, adjacent, margins only — define exactly when collapsing happens, and checking them is the way to predict whether a given gap will collapse or add. The next two sections cover the two main situations where collapsing occurs: between siblings, and between a parent and its first or last child.
Check: Two paragraphs have bottom and top margins of 20px and 30px. What is the gap between them?
Section 13 — Collapsing between siblings and parents
Adjacent siblings collapse their touching margins, and a parent's margin can collapse with its first or last child's margin when nothing separates them. The sibling case: two paragraphs in sequence, each with vertical margins, produce a single gap equal to the larger margin. The parent-child case is less intuitive and more often the source of bugs. Consider a container with a top margin of 20 pixels, containing a paragraph with a top margin of 30 pixels, and with no border, no padding, and no content before the paragraph. The container's top margin and the paragraph's top margin are adjacent — there is nothing between them — so they collapse into a single margin of 30 pixels, the larger of the two. The visual result is that the paragraph appears to push the container itself down from whatever precedes it, rather than pushing itself down inside the container, which is what most authors expect.
That parent-child collapse is confusing because it violates the mental model of a container as a boundary. Authors expect a container to contain its children's margins, so that a child's top margin creates space inside the container, between the container's edge and the child. But by default, a container does not contain its children's margins: if nothing separates the child's margin from the container's own margin, the two collapse and the resulting margin acts outside the container, moving the whole container rather than spacing the child inside it. The same applies at the bottom: a last child's bottom margin can collapse through the container's bottom edge, moving what follows the container rather than spacing the child inside it. The container's edge, in the absence of a border or padding, is not a barrier to margins; it is transparent to them.
The conditions for parent-child collapsing are precise, and they point to the remedies. Collapsing happens only if there is nothing between the margins: no border on the parent's relevant edge, no padding on that edge, and no content before the first child or after the last child. Adding any of those — a 1-pixel border, a single pixel of padding, or even a piece of content — separates the margins and prevents collapse. That is why the common advice for a "margin escaping its container" bug is to add a border or padding to the parent, or to give the parent overflow: hidden or another property that establishes a new formatting context, which also prevents collapse. Each remedy works by the same mechanism: it puts something between the margins, or it changes the container's layout context so that collapsing no longer applies.
Understanding parent-child collapse also clarifies a related puzzle: a container with a background colour, whose first child has a top margin, may show the background starting lower than expected, or the child's margin may appear to create space above the container rather than inside it, exposing the parent's background in an unexpected place. The explanation is always collapse: the child's margin has combined with the parent's and acted outside. The fix is not to remove the child's margin, but to separate the margins, by giving the parent padding, a border, or a formatting context, so that the child's margin stays inside where it belongs.
Check: Why does a child's top margin sometimes move its parent instead of spacing inside it?
Section 14 — Preventing unwanted collapsing
You can prevent collapsing by putting something between the margins — a border, padding, or a new formatting context — or by using padding or a gap instead of margin for that spacing. Prevention is usually preferable to fighting collapse after the fact, because collapse is specified behaviour, not a bug to be worked around with hacks. The cleanest prevention is to design spacing so that collapse does not arise in the first place, or to separate margins deliberately where it would. That requires knowing the separating mechanisms and choosing the one that fits the situation.
The simplest separator is padding. A single pixel of top padding on a parent separates its top margin from its first child's top margin, because padding is content between the margins, and margins only collapse when nothing lies between them. That pixel of padding also has a visual effect — it adds a pixel of space inside the container — but that effect is usually negligible, and it can be accounted for in the design. A border works the same way: a 1-pixel border on the parent's edge separates the margins, with the additional benefit of being visible, which may or may not be desired. If neither padding nor border is acceptable visually, a transparent border — a border with a transparent colour — separates the margins invisibly, reserving the space without showing a line, a technique similar to the transparent border trick from Chapter 7.
A more structural prevention is to establish a new block formatting context on the parent, which is a layout concept that, among other effects, contains its children's margins so they cannot collapse through its edges. Several properties establish such a context, including overflow set to anything other than visible — most commonly hidden or auto — and display: flow-root, which exists specifically for this purpose and has no other visual side effects. display: flow-root on a parent is the cleanest modern solution to parent-child collapse: it says "this element establishes its own layout context", and as a consequence, its children's margins stay inside it. It is worth learning by name, because it solves the problem without adding visible padding or borders, and without the clipping side effects that overflow: hidden can have.
An alternative approach is to avoid relying on margins for the spacing in question at all. Inside a component, padding on the container often expresses the intent more accurately than margins on the children: a card with padding has even space inside it regardless of its children's margins, and that space cannot collapse, because padding never collapses. Similarly, in flexbox and grid layouts, the gap property provides spacing between items that does not collapse and does not require margins, which is one reason those layout systems feel more predictable for spacing than traditional block layout. The general lesson is to choose the spacing mechanism that matches the intent: margins for spacing between separate blocks in a document flow, where collapsing is part of the typographic rhythm, and padding or gap for spacing inside a component or between layout items, where collapse would be a surprise. That choice, made deliberately, prevents most collapsing problems before they occur.
Check: Name two ways to stop a child's margin collapsing through its parent.
Section 15 — Negative margins
Negative margins pull neighbouring elements closer, even overlapping them. They are powerful but should be used deliberately, because they break the normal expectation that margins separate. A negative margin is a margin with a value below zero, such as margin-top: -20px;, which moves the element 20 pixels upward, towards the preceding element, reducing or eliminating the gap between them, and potentially overlapping them if the negative value exceeds the existing gap. Negative margins are valid for all four sides, and they interact with collapsing in specific ways: when a negative margin collapses with a positive one, the result is the sum of the two, so a 30-pixel positive margin collapsing with a -10-pixel negative margin produces a 20-pixel gap, not 30 or -10. That arithmetic is consistent with the idea of collapse as combination, but it requires care to predict.
The legitimate uses of negative margins are specific and worth knowing. One is pulling an element outside its container by a controlled amount, such as a full-bleed image inside a padded article that should extend to the container's edges: a negative left and right margin equal to the container's padding pulls the image outward by exactly that amount, aligning it with the container's outer edge while the text remains padded. Another is overlapping elements deliberately, such as a card overlapping a hero image by a few pixels, or a badge overlapping the corner of a card — effects that are difficult to achieve with normal flow alone, and that negative margins express directly. A third is compensating for unwanted spacing, such as removing the extra margin from the first or last item in a row, though modern gap properties have largely replaced that use.
The risks are also specific. Negative margins can cause overlapping that hides content, especially if the content's size changes — a translation, a larger font, a longer word — and the overlap that looked deliberate becomes a collision that obscures text. They can pull elements outside their containers in ways that cause overflow, horizontal scrolling, or clipped content, particularly on narrow screens where the negative amount was calculated for a wider layout. And they can interact with collapsing in ways that are hard to predict without careful calculation, especially when several negative and positive margins meet. For those reasons, negative margins should be used sparingly, for effects that cannot be achieved more directly, and tested at multiple screen widths and content lengths.
A useful discipline is to treat a negative margin as a deliberate exception that deserves a comment, explaining what it is compensating for or overlapping, so that a future maintainer does not "fix" it by removing it. Like !important in Chapter 6, a negative margin is a powerful tool whose power is preserved by using it rarely and documenting it when used. In most spacing situations, a positive margin, padding, or gap expresses the intent more clearly and more robustly. Negative margins are for the cases where the normal flow puts something in the wrong place by a known amount, and you need to move it back by exactly that amount — a precise, intentional correction, not a general spacing strategy.
Check: What does a negative top margin do to an element's position?
Section 16 — Auto margins and centring
Setting left and right margins to auto on a block with a fixed width centres it horizontally, because the browser splits the leftover space equally between the two auto margins. This is the classic CSS centring technique, and it is worth understanding mechanically, because it explains both why it works and when it does not. A block-level element normally fills the full width of its container, leaving no leftover space, so auto margins compute to zero and nothing is centred. But when the block has a declared width narrower than its container — say, 600 pixels inside an 800-pixel container — there are 200 pixels of leftover space, and the browser distributes that space to the auto margins. With both left and right set to auto, each gets half, 100 pixels, and the block sits centred, with equal space on both sides.
The shorthand for this is margin: 0 auto;, which sets top and bottom margins to zero and left and right to auto, and it is one of the most frequently written declarations in CSS. Its variants are also common: margin: 24px auto; centres the block while giving it 24 pixels of vertical margin, and margin: 0 auto 48px; centres it with no top margin and a 48-pixel bottom margin. In each case, the horizontal auto margins do the centring, and the vertical values do whatever vertical spacing is needed. The technique requires a width: without a declared width, or with a width of 100%, there is no leftover space to distribute, and auto margins compute to zero. That requirement is the most common reason centring "does not work" — the author set auto margins but forgot, or did not realise they needed, a width narrower than the container.
Auto margins do not centre vertically, in normal block layout. Setting top and bottom margins to auto on a block in a container with extra height computes them to zero, not to an equal split, because vertical auto margins in block layout have no leftover-space distribution rule. Vertical centring requires other techniques — flexbox or grid alignment, or absolute positioning with transforms — which later chapters cover. The asymmetry is a consequence of how block layout works: width is constrained by the container, creating leftover space to distribute, while height is determined by content, so there is normally no leftover vertical space to distribute. Knowing that horizontal auto margins centre and vertical auto margins do not, in block layout, prevents a frustrating class of attempts to centre things vertically with a technique that was never designed for it.
Auto margins have a second use that is less well known: pushing an element to one side. If only the left margin is auto, it absorbs all the leftover space, pushing the element to the right edge; if only the right margin is auto, it pushes the element to the left edge. That is useful for aligning a single item to the far side of a container, such as a "next" button at the right end of a toolbar, without using floats or positioning. For block layout, the rule to remember is simple: a fixed width plus auto side margins equals centring, and a single auto margin equals pushing to the opposite side.
Check: Why does margin: 0 auto; centre a block only if it has a fixed width?
Section 17 — Border styles
Border styles determine what kind of line is drawn: solid is a continuous line, dashed is a series of dashes, dotted is a series of dots, and other styles create double or three-dimensional effects. The style is the property that makes a border visible at all, because without a style, no line is drawn, whatever the width and colour. That is why the border shorthand normally includes a style — border: 1px solid #ccc; — and why a declaration that sets only width and colour, like border-width: 2px; border-color: red;, produces no visible border until a style is added. The style is not an optional decoration on top of a border; it is the border's existence.
The most used styles are solid, dashed, and dotted, and each has a character and typical uses. Solid is the default choice for delineating boxes, cards, and form fields, because it is clear, neutral, and unambiguous. Dashed suggests a boundary that is provisional, incomplete, or cuttable — it is used for drag-and-drop zones, draft outlines, coupon borders, and dividers that should feel lighter than a solid line. Dotted suggests a subtle, decorative, or minimal boundary, used for fine dividers, dotted underlines, or delicate frames where a solid line would feel too heavy. The choice between them is a design decision about how strong the boundary should feel, and it should be consistent: a page that mixes solid, dashed, and dotted borders without a system looks haphazard, while a page that uses each for a distinct purpose — solid for boxes, dashed for drop zones, dotted for dividers — reads clearly.
The remaining styles — double, groove, ridge, inset, and outset — are less common in modern design, but they are worth knowing because they appear in older code and in browser defaults. double draws two parallel lines, which requires a border width of at least 3 pixels to be visible, since the two lines and the gap between them must fit within the width. groove and ridge create a carved or raised effect using two colours derived from the border colour, one light and one dark, to simulate a three-dimensional groove or ridge. inset and outset similarly simulate a box pressed into or raised from the page, using light and dark edges. Those three-dimensional styles were popular in the early web, when interfaces mimicked physical objects, but flat design has largely replaced them with solid lines and shadows, which give more control over the effect.
A practical note: border styles can be set per side, using border-top-style, border-right-style, and so on, or with the border-style shorthand, which follows the same one-to-four value rules as padding and margin. That allows a box with a solid border on three sides and no border on the fourth, or a top border that is dashed while the others are solid — a common pattern for section dividers, where only the top edge needs a line. And border styles interact with border-radius: a dashed or dotted border follows the rounded corner, with dashes or dots arranged along the curve, which can look uneven at small radii but is generally handled gracefully by browsers. The style, in short, is where a border's character lives, and choosing it deliberately is part of designing the box, not an afterthought.
Check: Why does a border with width and colour but no style remain invisible?
Section 18 — Border width and colour
Border width sets how thick the border line is, and border colour sets its colour, using any colour format from Chapter 7. Both are normally set explicitly, because their defaults — a medium width and the element's text colour — rarely match a design. Border width is most commonly given in pixels, because borders are usually hairlines or thin lines whose thickness should be exact, not proportional to text size. A 1-pixel border is the standard hairline, crisp on most screens; a 2-pixel border is noticeably stronger, used for emphasis or for elements that need a clear boundary; and widths above 3 or 4 pixels become a design feature in themselves, such as a thick accent border on one side of a card. Widths can also be given as keywords — thin, medium, thick — but those map to browser-defined pixel values that vary, so pixels are preferred for consistency.
Border colour follows the same formats as any colour: named, hex, rgb, or hsl, plus currentColor, which is the default and means "the element's text colour". That default is occasionally useful — a border that should always match the text, such as an underline effect or an alert box's border, can rely on currentColor without repeating the colour — but it is usually overridden with an explicit colour, because borders are often a muted neutral, like a light grey, that differs from the text colour. A card's border, for example, is typically a light grey that delineates the card without drawing attention, while its text is dark, so the border colour must be set separately. The habit of setting border colour explicitly, even when the default would be acceptable, makes the design's intentions clear and prevents surprises when the text colour changes later.
Border width and colour can be set for all sides at once, with border-width and border-color, each following the one-to-four value shorthand rules, or per side, with properties like border-top-width and border-left-color. Per-side control is essential for common patterns: a card with a thick coloured left border as an accent, and thin neutral borders elsewhere; a section with only a top border as a divider; a button with a bottom border that darkens on hover to simulate depth. Those patterns all rely on setting one side differently from the others, and they are among the most frequent uses of border properties in real designs. The shorthand border sets all three aspects — width, style, and colour — for all sides at once, but per-side longhands are what allow a border to be asymmetric, which is often where its design value lies.
Finally, border width contributes to the box's total size under content-box sizing, and is included in the declared size under border-box sizing, as Sections 7 and 8 explained. That means changing a border's width changes the box's total size under content-box, which can shift a layout by a pixel or two — a subtle effect that becomes visible when a hover rule adds or thickens a border, causing the element to grow and push its neighbours. The standard remedy, as with padding, is either border-box sizing, which keeps the total constant, or a transparent border in the normal state, which reserves the space, as Chapter 7, Section 43 explained.
Check: What units are most commonly used for border width, and why?
Section 19 — Border shorthand
The border shorthand sets width, style, and colour together, as in border: 1px solid #ccc;, and it applies to all four sides unless a per-side shorthand is used. Shorthand properties in CSS are conveniences that set several related properties in one declaration, and border is one of the most used, because borders are almost always specified as a combination of those three aspects, and writing them separately — border-width: 1px; border-style: solid; border-color: #ccc; — is verbose for such a common pattern. The shorthand's order is conventionally width, style, colour, though the specification allows any order, because the values are distinguishable by type: a length is a width, a keyword like solid is a style, and a colour is a colour. In practice, width-style-colour is the order everyone writes, and following it makes your code instantly recognisable.
The shorthand sets all four sides, which is what you want for a uniform border around a box, such as a card or a form field. For per-side borders, there are per-side shorthands: border-top, border-right, border-bottom, and border-left, each taking width, style, and colour for that side alone. Those are the workhorses of accent borders and dividers: border-left: 4px solid #0066cc; gives a card a thick blue accent on its left edge, while leaving the other edges borderless, and border-top: 1px solid #eee; gives a section a hairline divider above it. Combining a general border with a per-side override is also common: border: 1px solid #ccc; border-left: 4px solid #0066cc; gives a box a uniform thin border with a thick blue left edge, because the later per-side declaration overrides the general one for that side only.
Like the font shorthand from Chapter 7, border resets any aspects it does not mention. A declaration like border: solid; sets the style to solid and resets width and colour to their initial values — medium width and currentColor — discarding any width or colour set by earlier rules. That reset behaviour is why shorthand should be used deliberately: if you intend to change only the border's colour on hover, for example, you should write border-color: #0066cc;, not border: #0066cc;, because the latter would reset the width and style as well, potentially removing the border entirely if the style resets to none in some contexts, or at least changing its width unexpectedly. The rule is the same as for all shorthands: use shorthand when you intend to set the whole group, and use longhands when you intend to change one aspect.
Border shorthand also interacts with the box model in the way Section 18 described: the width it sets contributes to the box's size, and under border-box sizing it is included in the declared size. That interaction is usually invisible when borders are thin and border-box is in effect, but it becomes visible when a border appears or thickens on hover, and the box grows or shifts. The remedies — border-box sizing, or a transparent border in the normal state — apply here too, and they are worth applying proactively for any element whose border changes on interaction. A border that changes without moving anything is a polished detail; a border that pushes the layout around is a bug, and the difference is usually whether the space was reserved in advance.
Check: What does border: 1px solid #ccc; set, and for which sides?
Section 20 — Border radius
border-radius rounds the corners of an element's box, turning sharp corners into curves. A small radius, like 4 or 8 pixels, softens a card or button slightly; a large radius, like 50%, turns a square into a circle, provided the element is square. Border radius is a purely visual effect: it does not change the box model — the box's content, padding, border, and margin remain rectangles for layout purposes — but it changes how the box is painted, clipping the background and border to the rounded shape. That distinction matters, because a rounded element still occupies a rectangular space in the layout, and neighbouring elements are positioned as if its corners were square, even though they appear curved.
The value of border-radius can be a length, like 8px, or a percentage, like 50%. A length gives an absolute curve radius, independent of the element's size, which is the common choice for cards and buttons, where a consistent 8-pixel curve looks right at any size. A percentage is relative to the element's dimensions — the horizontal radius is a percentage of the width, and the vertical radius a percentage of the height — so 50% on a square produces a circle, because the radius is half the width and half the height, while 50% on a rectangle produces an ellipse, because the horizontal and vertical radii differ. That percentage behaviour is what makes circular avatars and pill-shaped buttons easy: a square image with border-radius: 50%; is a circle, and a button with a large radius relative to its height is a pill, whatever its width.
Individual corners can be rounded differently, using properties like border-top-left-radius, or the shorthand with up to four values, following the same clockwise order as other shorthands: top-left, top-right, bottom-right, bottom-left. That allows designs with only the top corners rounded, like a card whose header has rounded tops and square bottoms, or with one corner emphasised. Two values can also be given per corner, separated by a slash, to create elliptical corners — a horizontal radius and a vertical radius that differ — as in border-radius: 16px / 8px;, which produces a wider, flatter curve than a circular radius would. Those elliptical forms are less common, but they are useful for subtle, custom curves.
Radius also affects how content is clipped. A background colour or image is clipped to the rounded shape, so it does not poke out beyond the curve, but child content is not automatically clipped: a child element that extends to the box's square corners will overflow the rounded corner visually, unless the parent also has overflow: hidden, which clips children to the parent's rounded shape, as Section 46 explains. That interaction — radius clipping backgrounds but not children, unless overflow is set — is a frequent source of "my rounded card has square corners poking out" bugs, and the fix is almost always overflow: hidden on the rounded parent. With that understood, border-radius is a simple, powerful tool for softening a design, and it is one of the most visible ways that the box model meets aesthetics.
Check: What radius value turns a square element into a circle?
Section 21 — Outline versus border
An outline is a line drawn outside an element's border, which does not affect layout: it does not take up space, does not change the box's size, and does not push neighbours. That non-layout property is the defining difference between outline and border, and it determines when each should be used. A border is part of the box model — it sits between padding and margin, it contributes to the box's size, and adding or thickening it moves things around unless space was reserved. An outline sits outside the border, in the margin area, but it does not consume margin space: it is drawn over whatever lies there, without displacing anything. That makes outlines ideal for temporary, state-based lines, and borders ideal for permanent, structural lines.
The classic use of outline is focus indication, from Chapter 6, Section 15. When a user tabs to a link or button, the browser draws an outline around it to show focus, and that outline must not shift the layout — if focusing an element moved its neighbours, the page would jump with every Tab press, which would be disorienting. Because outlines do not affect layout, they can appear and disappear without any movement, which is exactly what a focus indicator needs. For the same reason, outlines are used for accessibility highlights, selection indicators, and debugging: a developer can outline every element on a page to see its boxes, without the outlines themselves changing the layout being inspected, which would defeat the purpose.
Outlines have their own properties, parallel to borders: outline-style, outline-width, outline-color, and the outline shorthand, which sets all three, as in outline: 2px solid blue;. They also have outline-offset, covered in Section 44, which moves the outline away from the border by a given amount, creating a gap between the border and the outline — a useful effect for focus rings that should stand clear of the element. Outlines follow the element's shape, including border-radius in modern browsers, so a rounded button's focus outline is rounded too, which looks polished. But outlines are always rectangular or rounded-rectangular in outline; they cannot be set per side, unlike borders, which can differ on each edge. An outline is an all-or-nothing line around the whole box, not a set of four independent edges.
The practical guideline follows from the difference: use borders for permanent boundaries that are part of the design — card edges, dividers, button outlines that are always present — because borders are structural and their space is accounted for in the layout. Use outlines for temporary or state-based lines — focus rings, hover highlights, error indicators that appear and disappear — because outlines do not disturb the layout when they appear. And never remove an outline without replacing it, as Chapter 6 warned: an outline removed for aesthetic reasons, with no replacement focus style, leaves keyboard users without a visible focus indicator, which is an accessibility failure. Outlines and borders look similar, but they play different roles, and choosing between them is a matter of asking whether the line should affect layout and whether it is permanent or temporary.
Check: Why is an outline better than a border for a focus indicator?
Section 22 — Box shadow
box-shadow adds a shadow behind an element's box, creating an illusion of depth, without affecting layout: the shadow does not change the box's size and does not push neighbours. Like text-shadow from Chapter 7, box-shadow is a purely visual effect, painted outside the box, and it is one of the most used decorative properties in modern design, because it is how flat rectangles are made to look like cards, panels, and floating elements. A subtle shadow lifts an element off the page, signalling that it is a distinct surface, while a stronger shadow signals that it floats higher, as in a modal dialog over a page. That depth language — subtle for cards, stronger for dialogs — is a consistent system that readers understand intuitively.
The values of box-shadow, in order, are: horizontal offset, vertical offset, blur radius, spread radius, and colour. The horizontal offset moves the shadow right (positive) or left (negative); the vertical offset moves it down (positive) or up (negative). The blur radius softens the shadow's edge, with zero producing a sharp copy of the box and larger values producing a more diffused, realistic shadow. The spread radius expands or contracts the shadow's size relative to the box, with positive values making it larger and negative values making it smaller. And the colour, usually a black with alpha, like rgba(0, 0, 0, 0.2), determines how dark and how translucent the shadow is. A typical card shadow is box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); — no horizontal offset, a small downward offset, a moderate blur, no spread, and a soft black — which reads as a gentle lift without drama.
Multiple shadows can be listed, separated by commas, to build layered effects, such as a small, sharp shadow close to the box plus a larger, softer shadow further out, which together mimic how real objects cast both a direct shadow and an ambient shadow. An inset keyword at the start of a shadow makes it an inner shadow, drawn inside the box rather than outside, which can simulate a pressed-in or recessed effect, such as an input field's inner edge. Those combinations allow sophisticated depth effects, but they should be used with restraint: a page where every element has a strong shadow looks cluttered and heavy, while a page where shadows are reserved for cards and floating elements, with consistent values across all of them, looks clean and intentional. Consistency matters more than creativity here: a shadow system with two or three standard values, reused everywhere, looks designed, while a different shadow on every element looks accidental.
Because shadows do not affect layout, they can overflow their container without pushing anything, which is usually desirable — a card's shadow should extend beyond the card without moving the next card — but it can also cause clipping if an ancestor has overflow: hidden, which clips shadows along with content, as Section 23 explains. And shadows, like other visual effects, should be tested on real backgrounds: a shadow that is visible on white may vanish on grey, and a shadow that looks subtle on a monitor may look heavy on a phone.
Check: Does a box-shadow change an element's size or push its neighbours?
Section 23 — Overflow: visible and hidden
Overflow is what happens when content is larger than its box, and the overflow property controls it. The default, visible, lets overflowing content spill out of the box and show over neighbouring content, without affecting layout. The alternative, hidden, clips the overflowing content at the box's edge, hiding whatever does not fit. Overflow arises whenever a box has a fixed size — a set height, a set width, or both — and its content exceeds that size: a paragraph too long for a fixed-height box, an image wider than its container, a long word that cannot wrap. It can also arise from other causes, such as a child with a negative margin pulling it outside its parent, or a positioned element placed beyond its container's edge.
Visible overflow is the browser's default, and it is forgiving: content is never hidden by default, so a box that is too small for its content does not lose information, it merely displays that information outside its boundaries, overlapping whatever lies beyond. That forgiveness is useful during development, because it makes sizing mistakes visible — you can see the overflowing content and realise the box is too small — but it is rarely the desired behaviour in a finished design, because overlapping content looks broken and can obscure neighbouring elements or become unreadable where it overlaps them. Visible overflow is therefore a default to be aware of, not a behaviour to rely on, except in specific cases where spilling out is intended, such as a dropdown menu that should extend beyond its container.
Hidden overflow is the deliberate alternative: the box becomes a window, and only the content that fits inside the window is shown, with the rest clipped invisibly at the edge. That is useful for image containers that must show a cropped image, for rounded corners that must clip their children, as Section 20 noted, and for any box where overflowing content would break the design and hiding it is preferable to showing it. But hidden overflow has a cost: the hidden content is inaccessible to sighted readers, who cannot scroll to it, because hidden does not provide a scrollbar. If the hidden content matters — text that a reader needs, a button they must click — then hiding it is a failure, not a fix, and the box should be enlarged, or scrolling should be provided, as the next section explains.
Hidden overflow also has a layout side effect that is often exploited deliberately: it establishes a new block formatting context, which contains floats and prevents margin collapsing, as Section 14 mentioned. That side effect means overflow: hidden is sometimes used not for clipping at all, but as a layout tool, to contain a parent's children or margins. That use is legitimate, but it should be understood for what it is: a side effect being relied upon, which also clips any content that genuinely overflows, including shadows and dropdowns that should spill out. The cleaner modern alternative for establishing a formatting context without clipping is display: flow-root, which contains without hiding. Knowing both, and choosing flow-root when you want containment without clipping, and hidden when you genuinely want clipping, is the professional distinction.
Check: What is the difference between overflow: visible and overflow: hidden?
Section 24 — Overflow: scroll and auto
overflow: scroll always shows scrollbars, and overflow: auto shows them only when content overflows. Both allow readers to reach content that does not fit, unlike hidden, which clips it inaccessibly. Scrolling overflow is the solution when a box must be a fixed size but its content may exceed that size, and the excess content matters and must remain reachable. A chat message list, a code block, a long table inside a fixed-height panel, or a terms-and-conditions box are all cases where the container's size is constrained by the layout, but the content's length is variable and important, so scrolling is the honest compromise: the box stays its size, and the reader can scroll within it to see everything.
The difference between scroll and auto is about when scrollbars appear. scroll always displays scrollbars, even when content fits, which reserves space and keeps the layout stable — the box's content area does not change size when content grows past the threshold, because the scrollbar was already there. That stability can be valuable in interfaces where a scrollbar appearing and disappearing would shift content, but it comes at the cost of showing disabled, greyed-out scrollbars on boxes that do not need them, which looks cluttered and can confuse readers into thinking there is more content when there is not. auto shows scrollbars only when needed, which is cleaner for most cases: a box that fits its content looks like an ordinary box, and a box that overflows gains a scrollbar exactly when it needs one.
Scrollbars themselves are a design consideration. Their appearance varies by browser and operating system — some are always visible, some appear only on hover or while scrolling, some are thin overlays that do not take up layout space, while others occupy space inside the box and reduce the content area. That variation means a scrolling box will look and behave slightly differently across devices, and testing on real devices matters, particularly for touch screens, where scrolling is by gesture rather than by scrollbar, and a box that relies on a visible scrollbar for discoverability may be less discoverable on touch. A common refinement is to ensure that scrolling regions are obviously scrollable — by showing a partial line of content at the edge, or by providing a visual cue — so that readers know there is more to see, rather than assuming the visible content is all there is.
Overflow can also be set independently for each axis, with overflow-x and overflow-y, which is useful when a box should scroll in one direction but not the other — a table that scrolls horizontally on a narrow screen, for example, while its height remains automatic. But setting one axis to a non-visible value causes the other axis to compute to auto if it was visible, a specification rule that surprises many developers: you cannot have one axis visible and the other scrolling without the visible axis becoming auto. That rule exists because a visible overflow in one direction is incompatible with scrolling in the other, and knowing it prevents a puzzling class of "why did my vertical overflow change?" bugs. For most cases, overflow: auto on the relevant axis, with the other axis left to its default, is the simplest and most robust choice.
Check: When does overflow: auto show a scrollbar, and when does it not?
Section 25 — Minimum and maximum sizes
min-width, max-width, min-height, and max-height set limits on a box's size, overriding width and height when they would exceed those limits. They are constraints, not sizes themselves: a max-width does not make an element that wide, it prevents it from becoming wider; a min-width does not make an element that wide, it prevents it from becoming narrower. That distinction is crucial, because it means these properties work together with width, height, and content size, rather than replacing them. An element with width: 100%; max-width: 800px; fills its container up to 800 pixels, and then stops growing, however wide the container becomes — the classic pattern for a readable text column on a wide screen, from Chapter 7, Section 35.
Maximum width is the most used of the four, because it solves the wide-screen problem elegantly. A page that stretches to the full width of a large monitor produces unreadably long lines, as Chapter 7 explained, but a page fixed at a narrow width wastes space on smaller screens and looks cramped on a phone. A fluid width with a maximum — width: 100%; max-width: 65ch; or max-width: 800px; — gives the best of both: the column fills a phone screen, adapts to a tablet, and stops at a readable width on a desktop, centred with auto margins if desired. That single pattern is the foundation of responsive text layout, and it appears in almost every well-designed site, because it adapts to any screen without media queries or complex logic.
Minimum sizes solve the opposite problem: preventing a box from becoming too small to be usable. A button with min-width remains tappable even if its label is short; a card with min-height keeps a consistent height in a row even if its content is brief; a sidebar with min-width does not collapse to an unusable sliver on a narrow screen. Minimums are also a defence against unexpected content: a container with a minimum height will not collapse to zero when its content is temporarily empty, such as while data is loading, which prevents layout shift — the jarring movement of content when a box suddenly grows. Setting sensible minimums is therefore a robustness practice, not just a design choice.
Maximum and minimum heights are less commonly used than widths, because height is usually automatic, but they have their roles: a max-height with overflow: auto creates a scrolling region of bounded height, such as a dropdown list that should not grow beyond the viewport; a min-height on a hero section ensures it fills a pleasing proportion of the screen even with little content. When both a size and a limit apply, the limit wins: a width of 1000 pixels with a max-width of 800 renders at 800, and a width of 100 pixels with a min-width of 200 renders at 200. That precedence — limits override sizes — is the rule to remember, and it makes these properties reliable tools for bounding a layout against the extremes of screen size and content length.
Check: What does width: 100%; max-width: 800px; do on a 1200px-wide screen?
Section 26 — Display: block boxes
Block-level elements generate block boxes: they start on a new line, stretch to fill their container's width, and stack vertically, one after another. Headings, paragraphs, lists, and divs are all block-level by default, and their behaviour defines the normal flow of a document: a sequence of blocks, each on its own line, each as wide as its container allows, each as tall as its content requires. That flow is the foundation of page layout, before any flexbox or grid is introduced, and understanding it is essential, because even pages built with modern layout systems still contain block boxes inside their flex and grid items.
The width behaviour of block boxes deserves precision. A block box does not have a width of 100% in the sense of a declared value; rather, it automatically fills the available width of its containing block, after accounting for its own margins, borders, and padding. That automatic filling is why a paragraph with no width declaration stretches across its container, and why a paragraph with left and right margins still fills the remaining space, rather than overflowing: the width is calculated as whatever remains, not as a fixed 100% that would then overflow when margins are added. If you do declare a width on a block box, that automatic filling stops, and the box becomes exactly that wide, with leftover space distributed to auto margins, as Section 16 explained, or left as empty space if margins are fixed.
The height behaviour is the mirror image: a block box's height is normally automatic, growing to fit its content, whatever its length. That growth is what makes documents flexible: a paragraph of any length produces a box of the right height, without the author predicting it. A fixed height overrides that growth, with overflow consequences covered in Sections 23 and 24, but the default — height by content — is the behaviour you want for almost all text content. And block boxes stack vertically with margin collapsing between them, as Sections 12 to 14 explained, so the spacing between successive blocks is the collapsed margin, not the sum, which gives documents their characteristic rhythm.
Block boxes can contain other boxes, both block and inline, and they establish the containing block for their descendants' percentage widths and for absolutely positioned children, a topic for later chapters. They also respect width, height, padding, border, and margin in full: all four box-model layers apply to block boxes exactly as the model describes, with no exceptions or partial application. That completeness is part of why block layout feels predictable once the box model is understood: a block box is the box model in its purest form, with every layer behaving as described, and with flow — stacking, filling, growing — providing the arrangement. Later layout systems add new arrangement rules, but they do not replace the box model; they arrange boxes that still have content, padding, border, and margin, exactly as this chapter describes.
Check: How do block boxes arrange themselves on a page?
Section 27 — Display: inline boxes
Inline elements generate inline boxes: they do not start a new line, they do not fill their container's width, and they flow within a line of text, wrapping to the next line when necessary. Links, emphasized text, spans, and images (in their default display) are inline by default, and their behaviour is fundamentally different from block boxes: an inline box is sized by its content, not by its container, and it participates in the line's layout rather than creating its own block. A paragraph containing several links and emphasized phrases is a block box containing many inline boxes, flowing together as text, breaking across lines as the container narrows.
The box-model application to inline boxes is partial, and that partiality is a frequent source of confusion. Horizontal padding, border, and margin on an inline element do apply, and they affect the line's layout: horizontal padding on a link pushes neighbouring text away, and a border around a link is visible and occupies space. Vertical padding, border, and margin, however, do not affect the line's height or the spacing between lines: vertical padding on an inline element is painted — it extends the background and border above and below the line — but it does not push neighbouring lines apart, so it can overlap the lines above and below. Vertical margin on an inline element has no effect at all. And width and height properties are ignored entirely for non-replaced inline elements: you cannot set a link to a particular width or height, because its size is determined by its content and the line it sits in.
That partial application makes sense when you picture a line of text as a single, flexible unit. The line's height is determined by its font and line height, not by the individual boxes within it, so allowing an inline element's vertical padding to change the line height would make lines uneven and unpredictable. Horizontal spacing, by contrast, is part of the line's flow: words and inline elements sit side by side, and their horizontal padding and margins are simply part of the sequence, like spaces between words. The model is therefore consistent, once you see the line as the unit: inline boxes contribute horizontally to the line, but vertically they are contained by it, except for their painted background and border, which may overflow the line visually without affecting its layout.
The practical consequence is that inline elements are for text-level styling — colour, font, background highlights, small borders — not for layout. When you need an element to have a controlled width, height, or vertical spacing, it must be a block or inline-block box, as the next section explains, not a pure inline box. Trying to give a link a fixed height, or a span a vertical margin, and finding that nothing happens, is not a bug; it is the inline model working as specified, and the remedy is to change the display type, not to fight the model. Recognising that distinction — inline for text flow, block for layout — is a foundational judgement in CSS.
Check: Does vertical margin affect the layout of an inline element?
Section 28 — Display: inline-block boxes
Inline-block elements flow like inline elements — they sit within a line and do not start a new line — but they behave like block boxes inside: width, height, vertical padding, and vertical margin all apply and affect layout. Inline-block is the hybrid that combines the best of both models for certain uses, and it was, before flexbox, the standard technique for arranging boxes side by side, such as navigation items, buttons in a row, or small cards in a line. An inline-block box is sized by its width and height declarations, or by its content if none are given, and it sits on the line like a word, with other inline-block boxes and text alongside it, wrapping to the next line if the row overflows.
The full box model applies to inline-block boxes, which is the key difference from pure inline boxes. A button set to display: inline-block can have a width, a height, vertical padding that pushes neighbouring lines apart, and vertical margins that create space — all of which would be ignored or only painted on a pure inline element. That completeness makes inline-block suitable for components that need box-model control but should sit in a line: buttons, badges, tags, pagination links, and small cards. A row of buttons, each inline-block with padding and margins, behaves predictably, because each button is a complete box, arranged horizontally like words in a sentence.
Inline-block has quirks that are worth knowing, because they explain why flexbox largely replaced it for row layouts. The first is whitespace: because inline-block boxes sit in a line like words, the spaces, tabs, and line breaks between them in the HTML source are rendered as spaces between the boxes, just as spaces between words are rendered. A row of inline-block elements written one per line in the source will have small gaps between them, caused by the line breaks, which can break a precise layout — four elements at 25% width each, plus whitespace gaps, overflow their row. Remedies include removing the whitespace in the source, setting the parent's font size to zero and restoring it on the children, or using comments to bridge the gaps, but all of them are hacks, and flexbox's gap property solves the problem cleanly, which is one reason flexbox superseded inline-block for rows.
The second quirk is vertical alignment. Inline-block boxes align to the baseline of the line by default, like text, which means boxes of different heights sit with their baselines aligned, not their tops or middles, producing uneven-looking rows when the boxes differ in height. The vertical-align property controls this, with values like top, middle, and bottom, but it is an additional detail to manage, and it is easy to overlook. Despite these quirks, inline-block remains useful for simple cases — a button, a badge, a single row of items where whitespace gaps are acceptable or controlled — and understanding it completes the picture of the three basic display types: block for stacking, inline for text flow, and inline-block for boxes in a line.
Check: What does inline-block allow that pure inline does not?
Section 29 — Boxes in normal flow
In normal flow, block boxes stack vertically and inline boxes flow horizontally within lines, and that flow is the default arrangement that all other layout systems modify or replace. Normal flow is not a layout technique you choose; it is what happens when you choose nothing — when no flexbox, grid, float, or positioning is applied, the browser arranges boxes by the flow rules, and those rules are simple enough to predict once the box model is understood. Block boxes, as Section 26 explained, fill their container's width, grow to fit their content's height, and stack one below another, with collapsed margins between them. Inline boxes, as Section 27 explained, flow within the lines established by their containing block, wrapping as needed, with line breaks occurring at spaces and after certain characters.
Flow is a bottom-up process in the sense that each box's position depends on the boxes before it: a block's top edge sits below the previous block's bottom edge, adjusted for collapsed margins, and an inline box's position within a line depends on the inline boxes before it on that line. That sequential dependence is why flow feels natural for documents — it mirrors how text flows on a page, one block after another, one line after another — and why it is less suited to complex, two-dimensional layouts, where an element's position should depend on a grid or a flex container rather than on its predecessors. Modern layout systems do not abolish flow; they establish new formatting contexts within which boxes are arranged by different rules, but inside those contexts, and for the page as a whole, flow remains the baseline.
The interaction between flow and the box model is where most layout reasoning happens. A block's height in flow is determined by its content, plus its padding and border, so adding padding to a block in flow pushes subsequent blocks down, because the block grows taller. A block's width in flow is determined by its container, minus its margins, borders, and padding, so adding a horizontal margin narrows the block, rather than overflowing it, because the width is calculated as the remainder. An inline box's position in flow is determined by the preceding inline content and by its own horizontal margins and padding, but not by its vertical margins, which are ignored, as Section 27 explained. Each of those behaviours follows directly from combining the box model with the flow rules, and none of them requires a separate explanation once both are understood.
Flow also has limits that motivate the later layout chapters. It cannot easily centre an element vertically, arrange items in a row with equal heights, distribute space between items, or create a grid with aligned rows and columns — all of which require flexbox, grid, or positioning. Recognising those limits is part of learning flow: it is the right tool for documents — articles, forms, simple pages where content flows top to bottom — and the wrong tool for application-like interfaces with complex, two-dimensional arrangements. But even in those interfaces, flow is present inside components: a card's content flows vertically, a paragraph's text flows in lines, and understanding flow is therefore never wasted. It is the ground on which all other layout is built.
Check: In normal flow, how are block boxes and inline boxes arranged differently?
Section 30 — Padding and backgrounds
An element's background paints its content and padding areas, but not its border or margin. That rule determines where a coloured area ends, and it is the reason padding is visible as coloured space while margin is visible as transparent space. When you set a background colour on a card and give the card padding, the colour fills the padding as well as the content, producing a coloured area larger than the text, with the text inset from the coloured edge by the padding amount. That is the standard card look, and it works because the background's painting area — technically called the background painting area, which by default extends to the border's inner edge, covering content and padding — includes the padding. If backgrounds did not paint padding, a card's padding would be transparent, and the card's colour would hug the text tightly, defeating the purpose of padding as breathing room inside the coloured area.
The border is the boundary of the background painting area by default, though a property called background-clip can change that: setting it to padding-box clips the background at the padding's outer edge, so it does not extend beneath a transparent or semi-transparent border, while content-box clips it at the content's edge, so padding shows the parent's background instead of the element's. Those variations are occasionally useful — for example, when a semi-transparent border should reveal the parent's background rather than the element's own background beneath it — but the default, border-box, which paints beneath the border as well, is the common case, and it means that a solid border hides the background beneath it, while a transparent border reveals the background beneath it, because the background is painted underneath the border line. That layering — background first, then border on top — is the painting order, and it explains why a transparent border shows the element's background, not the parent's, unless background-clip is changed.
Margin, by contrast, is never painted by the element's background, because margin is outside the box, not part of it. The background painting area ends at the border, and beyond that lies margin, which is transparent and shows the parent's background. That is why two cards with margins between them show the page background in the gap, not the cards' backgrounds: the gap is margin, and margin belongs to neither card's painted area. If you want a coloured gap, you must use padding on one of the elements, or a separate element with its own background, because margin cannot carry colour. That distinction — padding carries the element's background, margin carries the parent's — is the visual test that distinguishes the two: give an element a background colour, add padding, and the coloured area grows; add margin, and the coloured area stays the same size while the gap around it grows, showing the parent behind it.
For this chapter, the essential point is the pairing: padding and background go together, because padding is inside space that the background fills, while margin and background do not go together, because margin is outside space that the background never reaches. That pairing is the reason the padding-versus-margin decision, in Section 48, is often decided by asking "should this space be coloured or transparent?"
Check: Does a background colour paint an element's padding, its margin, or both?
Section 31 — Margins are transparent
Margins are transparent and show the parent's background, never the element's own. That is the counterpart to the previous section's point about padding, and it is worth stating separately, because it is the source of a specific, recurring confusion: an author sets a margin expecting a coloured gap, or sets a background expecting it to fill the margin, and is puzzled when the parent's colour appears instead. The explanation is always the same, and it follows from the box model's structure: the margin is outside the element's box, beyond its border, and the element's background painting area ends at the border. Beyond that boundary, there is nothing of the element left to paint — only empty space, through which the parent's background, or whatever lies behind the element, is visible.
That transparency has practical consequences for design. A row of cards on a grey page, each with a white background and a margin between them, shows grey in the gaps, because the gaps are margins, and margins show the page's grey. That is usually the desired effect: the grey gaps separate the white cards, making each card distinct, and the page background functions as the gutter colour. If the design instead wanted white gaps — cards separated by white space on a white page, for instance — then the page background would need to be white, or the gaps would need to be padding on a white container, because margins cannot be white on their own; they can only show what lies behind them. The gutter colour in a margin-based layout is always the parent's background, by definition, and designing with that in mind avoids surprises.
Transparency also means that margins cannot be used to create coloured bands or separators. A coloured band between two sections must be an element with its own background, or padding on one of the sections, because a margin, however large, will always show the parent behind it. Similarly, a margin cannot have a border or a shadow of its own — those belong to the element's box, inside the margin — so a "border around the margin" is a contradiction in terms. When a design calls for a visible separation that is not the parent's colour, the separation must be created by something other than margin: a border on one of the elements, a background on a wrapper, or a dedicated divider element with its own height and background.
There is one more subtlety: because margins are transparent, they also do not intercept pointer events or clicks in the way a padded area does. Clicking in a button's padding area clicks the button, because the padding is part of the button's box; clicking in a button's margin area does not click the button, because the margin is outside the box, and the click lands on whatever lies behind it — usually the parent. That distinction matters for interactive elements: a button's clickable area includes its padding but not its margin, so enlarging a button's clickable area requires padding, not margin. The same applies to hover effects: hovering over padding triggers the element's hover state, while hovering over margin does not.
Check: If a white card has a margin on a grey page, what colour shows in the margin area?
Section 32 — Seeing boxes in developer tools
Developer tools show each element's box model as a diagram, with content, padding, border, and margin labelled and measured. That diagram is the fastest way to understand any layout problem, because it makes the invisible visible: margins that are transparent on the page become coloured regions in the diagram, padding becomes a distinct band, and the exact pixel values of each layer are displayed. To see it, open developer tools, select an element in the Elements panel, and look for the box-model diagram, usually in the Styles or Computed panel, or in a dedicated Layout panel. Hovering over the diagram highlights the corresponding region on the page, and hovering over the element on the page highlights its box, with each layer in a different colour.
The diagram is also interactive in a useful way: the values for content size, padding, border, and margin can often be edited directly in the diagram, and the page updates live to reflect the change, without editing the stylesheet. That live editing is the fastest way to experiment with spacing: increase a margin and watch the element move, increase padding and watch the box grow, change the box-sizing and watch the total size change. It is also the fastest way to diagnose a problem: if an element is wider than expected, the diagram shows whether the extra width is content, padding, or border, and by how much, removing the guesswork. A layout bug that might take dozens of stylesheet edits to diagnose by trial and error can often be diagnosed in seconds by reading the diagram.
Beyond the diagram, developer tools offer a box-model overlay on the page itself, where each element's layers are outlined in different colours as you hover over elements in the Elements tree. That overlay is invaluable for understanding nesting and spacing: you can see at a glance whether a gap is margin or padding, whether a box is larger than its content, and whether elements overlap. It is particularly useful for margin collapsing, because the overlay shows the collapsed margin as a single region, rather than as two overlapping regions, making the collapse visible in a way that the page alone does not. And it is useful for inline elements, where the overlay shows the partial box-model application — horizontal padding visible, vertical padding painted but not affecting layout — that Section 27 described.
Making developer tools a habit for box-model work is one of the highest-return habits in front-end development. Instead of reasoning abstractly about why a layout is wrong, inspect the element, read its box diagram, and let the browser tell you the sizes. Instead of guessing whether a gap is margin or padding, hover over the gap and see which layer it belongs to. Instead of calculating total sizes by hand, read them from the diagram, which accounts for box-sizing, padding, and border automatically. The box model is a precise, measurable system, and developer tools are its measuring instrument. Use them, and the model stops being a diagram in a book and becomes something you can see and touch on every page you build.
Check: What does the box-model diagram in developer tools show you?
Section 33 — Sizing images with the box model
Images are boxes too, and their content area is the image itself, at its natural size unless width or height overrides it. An image that is wider than its container overflows it, because nothing in the box model automatically shrinks an image to fit. That overflow is a common layout bug, especially on phones, where a large desktop-sized image in a narrow container spills off the screen and causes horizontal scrolling. The remedy is a single, widely used declaration: img { max-width: 100%; height: auto; }, which constrains the image's width to its container's width, while preserving its aspect ratio by letting the height adjust automatically. That rule belongs in almost every stylesheet's base layer, because it prevents the most common image overflow bug in one line.
Understanding why that rule works requires the box model. An image's natural size — its intrinsic dimensions, from the image file — determines its content area by default, and its box is that content area plus any padding, border, and margin. If the content area is 1200 pixels wide and its container is 320 pixels wide, the image's box is 1200 pixels wide, and it overflows the container by 880 pixels, because block containers do not shrink their children to fit; they allow overflow, as Section 23 explained. Setting max-width: 100% caps the content area at 100% of the container's width, so the image can be no wider than its container, and it shrinks proportionally when the container is narrower than the image. Setting height: auto ensures that the height scales in proportion to the width, preserving the aspect ratio, rather than staying at the natural height, which would distort the image into a squashed or stretched shape.
Padding and border on images follow the same rules as on any element, with one caution: under content-box sizing, padding and border are added to the image's width, so an image at max-width: 100% with padding can still overflow, because its total exceeds 100%. Under border-box sizing, the padding and border are included in the 100%, so the image fits exactly, which is another reason border-box is the standard. That interaction is easy to overlook, because images are often thought of as exceptions to the box model, when in fact they follow it exactly like any other element, including the box-sizing rules. An image with a border and padding, under border-box, is a framed picture whose total size is predictable; under content-box, it is a picture plus a frame that may overflow.
Images also have an aspect ratio — the ratio of width to height — that the browser knows from the image file, and modern CSS can preserve that ratio even before the image loads, using the aspect-ratio property or the image's intrinsic dimensions, to prevent layout shift when the image arrives. That is an advanced refinement, but it rests on the same box-model foundation: the image is a box, its content area has a ratio, and constraining one dimension while letting the other adjust preserves that ratio. The essential habit, however, is the base rule: maximum width 100%, height auto, on all images, from the start of every project, so that images never break a layout by overflowing their container.
Check: Why does img { max-width: 100%; height: auto; } prevent overflow?
Section 34 — Percentage widths and the box model
Percentage widths are relative to the containing block's width, and under content-box sizing, padding and border are added on top, so a row of percentage-width boxes with padding can overflow. Under border-box sizing, they fit exactly. This section revisits a point from Sections 7 and 8, because percentage widths are where the box-sizing difference is most consequential in practice, and because it is the context in which most developers first encounter the problem. A layout of columns — two halves, three thirds, four quarters — is naturally expressed in percentages, because percentages adapt to any container width, but the addition of padding under content-box breaks the arithmetic that percentages promise.
Consider four cards in a row, each intended to be a quarter of the row. Under content-box, each card declared at 25% width, with 16 pixels of padding on each side and a 1-pixel border, has a total width of 25% plus 34 pixels, so four cards total 100% plus 136 pixels, overflowing the row by 136 pixels and wrapping the last card to a new line. The author intended quarters, but the browser produced quarters plus padding, and the layout broke. The traditional workaround was to subtract the padding by hand, using a calculation like width: calc(25% - 34px);, which works but is fragile: any change to padding requires recalculating the width, and the calculation must be repeated for every column count. That fragility is a maintenance burden, and it is why the calc workaround, though valid, is rarely the best solution today.
Under border-box, the same four cards, each declared at 25%, have a total width of exactly 25% each, because the padding and border live inside the declared width, and the content area shrinks to accommodate them. Four cards total exactly 100%, the row fits, and changing the padding does not break the row, because the total remains 25% regardless of padding. That robustness is the reason border-box is the standard for percentage layouts, and why the global border-box rule from Section 8 is placed at the top of almost every modern stylesheet: it makes percentage arithmetic work as authors expect, without manual calculations. The lesson generalises: whenever sizes are expressed as percentages that must add up — columns, grids, split layouts — border-box is not an optional refinement but a prerequisite for the arithmetic to hold.
There is a related point about percentage widths and margins. Margins are outside the box under both models, so a percentage-width box with a margin still overflows if the widths plus margins exceed 100%. Four cards at 25% with a 16-pixel margin between them total more than 100%, even under border-box, because margins are not included in the declared width. That is why modern layouts use gap in flexbox and grid for spacing between items, rather than margins: gap is space between items that is accounted for by the layout system, not added on top of item widths, so items at 25% with a gap still fit, because the layout system subtracts the gaps before assigning widths. For block layout without gap, the workaround is to put margins inside a wrapper, or to use padding on a container, rather than margins on the percentage boxes themselves.
Check: Why do four 25% cards with padding overflow a row under content-box?
Section 35 — Centring a fixed-width block
A fixed-width block is centred with auto side margins, as Section 16 explained, and that technique is the standard way to centre a page's main column. It deserves a section of its own, because it combines several box-model ideas — width, margin, containing block, and leftover space — into the single most common layout pattern on the web: a content column, narrower than the viewport, centred horizontally, with empty space on both sides on wide screens. That pattern appears on blogs, documentation sites, news sites, and countless other pages, because it solves the line-length problem from Chapter 7 while using the full screen on narrow devices.
The pattern has two parts, which are often written together: a width constraint, and auto margins. The width constraint is usually a maximum width, not a fixed width, so that the column adapts to narrow screens: max-width: 800px; margin: 0 auto; on a main container makes the container fill narrow screens, because its width is automatic up to the maximum, and centre itself on wide screens, because once it reaches 800 pixels, the leftover space is distributed equally to its auto side margins. A fixed width, like width: 800px; margin: 0 auto;, also centres, but it does not adapt: on a 320-pixel phone screen, an 800-pixel container overflows, causing horizontal scrolling. The maximum-width version is therefore almost always preferable, because it centres when there is space to centre in, and fills when there is not.
The containing block matters too. Auto margins distribute the leftover space within the containing block, which for a top-level main container is the viewport, or more precisely, the body, whose width is the viewport's width. If the main container is nested inside another container with its own width and padding, the centring is relative to that container, not to the viewport, which may or may not be intended. And padding on the centred container itself interacts with the width: under border-box, padding lives inside the maximum width, so the total remains 800 pixels; under content-box, padding is added on top, so the total exceeds 800 pixels and the centring is slightly off, with the container wider than intended. Border-box, again, makes the pattern work as expected, which is one more reason it is the default in modern practice.
Centring a block is sometimes confused with centring text, which is a different operation: text-align: center; centres inline content within its block, while auto margins centre the block itself within its container. A centred column usually contains left-aligned text, because left-aligned body text is more readable, as Chapter 7 explained, so the pattern is auto margins on the container, with text alignment left inside it. Confusing the two — centring text when you meant to centre the column, or vice versa — produces a page that looks wrong in a way that is hard to diagnose until the distinction is clear. The rule is: auto margins centre boxes, text-align centres text within boxes, and a well-designed page usually needs both, for different elements, at different levels.
Check: Why is max-width with auto margins better than a fixed width for centring a main column?
Section 36 — Vertical percentage margins
Percentage margins, like percentage padding, are measured against the containing block's width, even for top and bottom margins. That rule, first stated for padding in Section 11, applies identically to margins, and it is equally surprising for the same reason: a top margin of 10% inside a container 400 pixels wide and 800 pixels tall is 40 pixels, not 80, because the percentage resolves against width, not height. The rule exists for the same historical reason — width is determined before layout, while height depends on content, creating a circular dependency if vertical percentages followed height — and it has the same practical consequence: vertical percentage spacing scales with the container's width, not its height, so it grows on wide screens and shrinks on narrow ones, even though it is vertical space.
That width-based scaling can be useful or confusing, depending on intent. If you want vertical spacing that scales with the layout's width — for example, a hero section whose top margin should be proportional to the page width, maintaining a consistent visual rhythm across screen sizes — then a percentage top margin does exactly that, and it is a legitimate technique. But if you want vertical spacing that is a fixed amount, or that scales with the content's height, then a percentage margin is the wrong tool, because it will change when the width changes, for reasons unrelated to the vertical design. A top margin that looks right on a desktop may become too large or too small on a phone, not because the vertical design changed, but because the width changed, and the margin followed the width.
The practical advice mirrors that for padding: use fixed units — pixels, ems, rems — for ordinary vertical spacing, where the intent is a specific gap, and reserve percentages for the cases where width-relative scaling is genuinely desired. That advice also applies to the common pattern of using percentage margins for aspect-ratio-like effects, which is less common for margins than for padding, because margins are outside the box and their percentage behaviour is less often exploited deliberately. When you do encounter a percentage margin in existing code, check whether the author intended width-relative behaviour or mistakenly assumed height-relative behaviour, because the latter is a real bug that produces spacing that changes unexpectedly with screen width, and the fix is usually to change the unit to a fixed one.
A final note: the width basis applies to all percentage margins and paddings, in all directions, without exception, and it applies to the containing block's width, not the element's own width. That last point matters for nested elements: a child's percentage margin is relative to its parent's width, not its own, so two elements of different widths inside the same parent, both with 10% top margins, get the same pixel margin, because they share the same containing block width. That shared basis can be a useful consistency property, or a surprise, depending on whether you expected each element's margin to scale with its own size. Either way, the rule is uniform and predictable once known: percentages for margin and padding always mean "percentage of the containing block's width", in every direction, for every element.
Check: A container is 400px wide and 800px tall. How many pixels is a child's margin-top: 10%?
Section 37 — Padding in buttons and controls
Padding is what makes buttons feel like buttons: it creates the clickable area around the label, gives the label breathing room, and makes the button's size feel intentional rather than cramped. A button with no padding is just text with a background, hugging the label tightly, with a small clickable area that is hard to tap accurately, especially on a phone. A button with generous padding — typically more horizontal than vertical, such as padding: 10px 20px; — feels like a distinct, tappable object, with a comfortable target size and a clear separation from neighbouring elements. That feel is not cosmetic; it is usability, because tap targets that are too small cause errors, frustration, and accessibility failures for users with limited motor control.
The horizontal-versus-vertical distinction in button padding is a design convention worth noting. Buttons usually have more horizontal padding than vertical, because text is wider than it is tall, and a button needs more side room to feel balanced than top room. A button with equal padding on all sides can look tall and narrow, while a button with, say, 10 pixels vertical and 20 pixels horizontal looks proportioned, with the label centred in a comfortably wide target. That convention is not a rule, and some designs use equal padding or even more vertical padding for large, prominent buttons, but the horizontal-dominant pattern is the default to start from, and deviations from it should be deliberate.
Padding also determines a button's clickable area, as Section 31 noted for margins: the padding is part of the button's box, so clicking or tapping within the padding activates the button, while clicking in the button's margin does not. That means padding is the correct tool for enlarging a tap target, not margin: adding margin around a button moves it away from its neighbours but does not make it easier to tap, while adding padding enlarges the target itself. Accessibility guidance recommends a minimum tap target size, often around 44 pixels in each dimension, and padding is how small labels reach that size without increasing the font size: a 16-pixel label with 14 pixels of vertical padding is 44 pixels tall, meeting the target, while remaining visually proportionate.
Form controls follow the same principle. Text inputs need padding so that typed text does not touch the input's border, which would look cramped and make the text hard to read at the edges. Select menus and text areas need padding for the same reason. And in all controls, padding interacts with box-sizing: under border-box, padding lives inside a declared width, so an input at 100% width with padding still fits its container, while under content-box, the same input overflows, because its total exceeds 100%. That is why the global border-box rule and the input-width pattern — inputs at 100% width, with padding, under border-box — are almost always used together in form design. Padding in controls is not decoration; it is the space that makes controls usable, readable, and correctly sized.
Check: Why does padding, rather than margin, enlarge a button's clickable area?
Section 38 — The global border-box reset
The global border-box rule, *, *::before, *::after { box-sizing: border-box; }, applies border-box sizing to every element and pseudo-element on the page. It is the standard way to adopt border-box sizing, and it belongs at the top of almost every stylesheet. The rule uses the universal selector, covered in Chapter 6, Section 6, to match every element, and it explicitly includes pseudo-elements, because * alone does not match ::before and ::after, which create boxes of their own and should follow the same sizing convention as everything else. Without the pseudo-element part, a component that uses generated content for decoration could have its decorative boxes sized differently from its real boxes, producing subtle inconsistencies.
Placing the rule at the top of the stylesheet matters, because box-sizing is inherited in a specific way that makes the global rule robust. Actually, box-sizing is not inherited by default, but the universal selector rule sets it directly on every element, so inheritance is not needed: each element receives the value from the rule itself, regardless of its parent. That direct application is more reliable than setting box-sizing on body and relying on inheritance, because a third-party component or a later rule could override inheritance, while the universal rule applies to every element independently. Some modern variations set box-sizing on html and inherit it everywhere, using *, *::before, *::after { box-sizing: inherit; }, which allows a component to opt out by setting a different box-sizing on its root, with the change propagating to its descendants through inheritance. That variation is elegant, but the simple universal rule is more common and easier to understand, and either achieves the goal of consistent sizing.
The benefit of the global rule is consistency: every box on the page follows the same measuring convention, so declared widths mean total widths everywhere, percentage layouts add up, and padding and border changes do not break rows or columns. Without it, a page mixes models — some elements content-box, because that is the default, and others border-box, because a component set it — and the author must remember which model each element follows when calculating sizes, which is error-prone and fragile. With it, the author can forget about box-sizing for most work, because the convention is uniform, and only the rare case where content-box is specifically needed requires a deliberate override.
That rare case deserves a note: there are situations where content-box is the right model, such as when a specific text width must be preserved regardless of padding, as Section 7 discussed. In those cases, a targeted override — box-sizing: content-box; on the specific element — restores the default for that element alone, without affecting the rest of the page. The global rule does not prevent such overrides; it merely changes the default from which overrides depart. That is the right relationship: a sensible global default, with local exceptions where justified, rather than a per-element decision that must be made fresh every time. Adopting the global border-box rule early in a project, and keeping it there, is one of the simplest decisions that most improves layout predictability.
Check: Why does the global border-box rule include pseudo-elements?
Section 39 — Common box-model mistakes
The most common box-model mistakes are: forgetting that padding and border add to size under content-box, expecting vertical margins to add instead of collapse, using margin where padding is needed (or vice versa), and setting a fixed height that clips content. Each of these has been covered in its own section, but gathering them here as a checklist is useful, because they are the mistakes that recur most often in practice, and recognising them as a set makes them easier to spot in your own work and in others'. A checklist is also a debugging tool: when a layout is wrong, running through these four mistakes often identifies the cause faster than random experimentation.
The first mistake — forgetting that padding and border add to size — manifests as an element wider or taller than declared, a row that wraps unexpectedly, or a container that overflows by exactly the amount of its padding and border. The diagnosis is to check box-sizing: if it is content-box, either switch to border-box, globally or for the element, or subtract the padding and border from the declared size by hand. The fix is usually the global border-box rule, which prevents the mistake from recurring, rather than a one-off calculation that must be repeated for every sized element. That is why the global rule is recommended so strongly: it does not just fix one instance, it removes the entire class of mistake.
The second mistake — expecting margins to add — manifests as a gap smaller than expected, usually by exactly the smaller margin's amount, because the margins collapsed to the larger one. The diagnosis is to check whether the margins are vertical and adjacent, with nothing between them, and the fix depends on intent: if the collapsed gap is actually the desired rhythm, accept it and adjust the margins to produce it; if the gap should be the sum, separate the margins with padding, a border, or a formatting context, or use padding or gap for the spacing instead, as Section 14 advised. The mistake is not in the browser's behaviour, which is specified, but in the author's expectation, which assumed addition where the specification says collapse.
The third mistake — confusing margin and padding — manifests in two forms: a gap that shows the wrong colour, because margin was used where a coloured gap was wanted, or a clickable area that is too small, because margin was used where padding would have enlarged the target. The diagnosis is to ask "should this space be part of the element, with its background and its click area, or outside it, transparent and non-interactive?" If part of the element, it is padding; if outside, it is margin. That single question resolves most margin-versus-padding confusion, and Section 48 expands it into a fuller decision guide. The fourth mistake — a fixed height clipping content — manifests as text cut off, overlapping, or hidden, and the diagnosis is to check whether a height is set, whether it is necessary, and whether overflow is handled. The fix is usually to remove the fixed height and let the box grow, or to add scrolling if a fixed height is genuinely required.
Check: Name the four common box-model mistakes listed in this section.
Section 40 — Inline padding and margin limits
Inline elements accept horizontal padding, border, and margin fully, but vertical padding is painted without affecting layout, and vertical margin has no effect. That partial application, introduced in Section 27, deserves its own section, because it is the box-model rule that most often surprises developers who expect all elements to behave like blocks. The reason for the partial application lies in how lines are laid out: a line's height is determined by its font and line height, and by the tallest inline box within it, but not by the vertical padding or margins of individual inline boxes, which would make line heights unpredictable if they were allowed to affect layout. The browser therefore paints vertical padding and borders on inline elements — so they are visible — but does not let them change the line's height or the spacing between lines.
The visual consequence is overlap. An inline element with large vertical padding, such as a link with a background colour and 10 pixels of top and bottom padding, will show its background extending above and below the line, overlapping the lines above and below it, while the lines themselves remain at their normal spacing. That overlap can obscure neighbouring text, especially if the background is opaque, and it looks like a bug, though it is specified behaviour. The remedy depends on intent: if the element needs vertical padding that affects layout, it should be inline-block, not inline, because inline-block boxes respect vertical padding in layout, as Section 28 explained. If the element should remain inline, its vertical padding should be small enough not to overlap neighbouring lines noticeably, or zero, with horizontal padding providing the breathing room instead.
Vertical margins on inline elements are simpler: they do nothing at all, neither painted nor layout-affecting, and they are ignored by the browser. Setting margin-top on a link has no visible effect, and no effect on the line's layout, which is why authors who try to space inline elements vertically with margins find that nothing happens. The remedy is again to change the display type, or to use a different mechanism, such as line height on the containing block, which does affect line spacing. Horizontal margins on inline elements, by contrast, work exactly as expected: they push neighbouring inline content away horizontally, creating space between words and inline elements within the line, and they are the correct tool for spacing inline elements horizontally.
A related point is that replaced inline elements, like images, behave differently from non-replaced inline elements, like links and spans: images do respect width, height, and vertical margins, because their size is intrinsic and their layout is not purely text-based. That exception is why an image with a vertical margin moves as expected, while a link with the same margin does not, and it is a distinction worth knowing when debugging inline spacing. For non-replaced inline elements, the rule stands: horizontal box-model properties work fully, vertical padding is painted but does not affect layout, and vertical margin does nothing. Knowing that rule prevents a whole class of "why does this spacing not work?" questions, and it points directly to the remedy — inline-block — whenever vertical box-model control is needed for an element that must remain in a line.
Check: What happens to vertical padding on an inline element?
Section 41 — Height, content, and overflow
A fixed height that is too small for its content causes overflow, and how that overflow is handled determines whether readers can still reach the content or lose it. This section gathers the height and overflow ideas from Sections 6, 23, and 24 into a single decision guide, because height is the dimension where box-model decisions most often go wrong. Width problems are usually visible immediately — a row wraps, a container overflows horizontally — but height problems can be subtle: text clipped at the bottom of a box, a button cut off, a card whose last line is hidden, all of which look like missing content rather than a sizing error, and all of which stem from a height that was set too small for the content it must hold.
The first decision is whether a fixed height is needed at all. In most cases, it is not: a block box's height should be automatic, growing with its content, so that any amount of content — a short label, a long paragraph, a translated text that is longer than the original — fits without overflow. Automatic height is robust to content variation, which is the norm on the web, where content changes, translations vary in length, and user settings change font sizes. A fixed height is fragile to all of those variations, because it assumes a known content size, and any deviation from that assumption produces overflow. The professional default is therefore automatic height, with fixed heights reserved for cases where the design genuinely requires a box of a particular size, such as a hero section that should fill a proportion of the viewport, a thumbnail grid where cards must align, or a scrolling region whose size is constrained by the layout.
When a fixed height is genuinely required, the second decision is how overflow should be handled. The options, from Sections 23 and 24, are: visible, which lets content spill out, overlapping neighbours — rarely desired, but useful for dropdowns and tooltips that should extend beyond their container; hidden, which clips content invisibly — useful for image crops and rounded corners, but harmful for text readers need; and auto or scroll, which provides scrolling within the box — the honest solution when content must remain reachable within a fixed size. Choosing among them is a matter of asking whether the overflowing content matters: if it is decorative and can be cropped, hidden is fine; if it is content readers need, scrolling is required; if it should extend beyond the box by design, visible is correct. There is no universal answer, only a decision per box, based on what its content is.
A third consideration is minimum height, from Section 25, which is often a better tool than fixed height. A min-height guarantees a box is at least a certain size — a hero section at least half the viewport, a card at least as tall as its siblings — while still allowing it to grow if its content exceeds that minimum. Minimum height is therefore the preferred way to express "this box should be about this tall" in most designs, reserving fixed height for the rarer "this box must be exactly this tall, and its content must fit or scroll within it".
Check: Why is a minimum height usually safer than a fixed height?
Section 42 — Percentage heights
Percentage heights are relative to the containing block's height, but only if that height is determined; otherwise, they resolve to automatic. That behaviour is the source of the classic "percentage height does nothing" puzzle, and it deserves explanation, because it contrasts with percentage widths, which almost always work. A percentage width resolves against the containing block's width, which is almost always determined, because block containers fill their parent's width by default, so a width percentage has a definite basis. A percentage height resolves against the containing block's height, which is usually automatic — determined by its content — so a height percentage often has no definite basis, and the specification says that in that case, the percentage resolves to automatic, meaning the element's height is determined by its content, as if no percentage had been set.
Consider the common attempt: a page with a div set to height: 100%;, intended to fill the viewport, inside a body whose height is automatic. The div's percentage has no definite basis, because the body's height depends on its content, which includes the div, creating a circular dependency: the div's height depends on the body's, and the body's depends on the div's. The browser breaks the circle by treating the div's height as automatic, so the div grows to fit its content, not to fill the viewport, and the author sees a div that is much shorter than intended, with no error to explain why. The fix is to give the chain of ancestors definite heights, all the way to the root: html, body { height: 100%; } makes the body's height definite — 100% of the viewport, via the html element — and then a child at 100% has a basis and fills the body. That chain — every ancestor from the element up to the root must have a definite height — is the rule, and missing any link breaks it.
Modern alternatives have reduced the need for percentage height chains. Viewport units, like vh, express height as a percentage of the viewport directly, without depending on ancestors: height: 100vh; means the full viewport height, regardless of the containing block, which is simpler and more robust for hero sections and full-screen panels. Flexbox and grid also provide height distribution without percentage chains: a flex container with a definite height distributes that height to its items, and a grid container does the same for its rows, so children can fill available space without percentage heights. Those systems are the preferred modern approach for full-height layouts, because they avoid the fragile ancestor chain.
Nevertheless, percentage heights still appear in existing code and in specific cases where a proportion of a definite container is wanted — a child at 50% of a fixed-height panel, for instance — and understanding their conditional behaviour prevents confusion when they do not work. The diagnostic question is always: is the containing block's height definite? If yes, the percentage works; if no, it resolves to automatic, and the element's height is content-based. Checking the ancestor chain, from the element up to the root, for a definite height at each step, identifies the broken link, and the fix is either to make the chain definite or to use a viewport unit or a flex or grid layout instead.
Check: Why does height: 100%; sometimes have no effect?
Section 43 — Shadows, outlines, and layout
Box shadows and outlines do not affect layout: they are painted outside the box without changing its size or pushing neighbours. That property, noted for outlines in Section 21 and for shadows in Section 22, deserves emphasis as a general principle, because it distinguishes visual effects from box-model layers. Padding, border, and margin are layout properties: they occupy space, affect sizes, and move neighbours. Shadows and outlines are painting properties: they are drawn after layout, in the space around the box, without participating in layout calculations. That distinction means that adding, removing, or changing a shadow or outline never reflows the page — neighbours do not move, containers do not grow, and the layout remains stable — which is a valuable property for interactive effects.
The stability is most valuable for hover and focus effects. A button whose shadow grows on hover — from a subtle shadow to a stronger one, suggesting that it lifts towards the reader — does so without moving any neighbouring element, because the shadow is painted outside the box and does not affect the box's size or position. A link whose outline appears on focus does so without shifting the text around it, because the outline is drawn over the margin area without consuming it. If those same effects were achieved with borders, as Section 21 warned, the layout would shift: a border added on hover would grow the box and push neighbours, unless space had been reserved with a transparent border in advance. Shadows and outlines avoid that problem by design, which is why they are the preferred tools for state-based visual changes.
There are limits to that freedom. Shadows and outlines can be clipped by an ancestor with overflow: hidden, because clipping applies to painting, not just to content: a shadow that extends beyond a clipping ancestor is cut off at the ancestor's edge, just as overflowing content would be. That can produce a card whose shadow is mysteriously cut off on one side, with the cause being an ancestor's overflow setting rather than the shadow itself. The remedy is to ensure that ancestors of shadowed elements do not clip, or to give the shadow room within the clipping ancestor, by adding padding or margin to accommodate it. Similarly, outlines drawn in the margin area can overlap neighbouring content visually, without affecting its layout, which is usually fine for a thin focus ring, but can look messy for a thick outline on a densely packed page, where the outline overlaps adjacent text.
The general lesson is to classify properties by whether they affect layout or only painting, and to choose accordingly. For permanent structure — the size and spacing of boxes — use the box-model layers: content, padding, border, margin. For temporary emphasis — hover lifts, focus rings, selection highlights — use painting properties: shadows and outlines, which can appear and disappear without disturbing the layout. That classification keeps interactive effects smooth and layouts stable, and it prevents the common bug where a hover effect causes the page to jump. A page whose interactive effects are all painting-based feels polished, because nothing moves except the element being interacted with, and that polish is a direct consequence of understanding which properties affect layout and which do not.
Check: Why does a hover shadow not move neighbouring elements?
Section 44 — Outline offset
outline-offset moves an outline away from the element's border, creating a gap between the two, or, with a negative value, drawing the outline inside the border. It is a small property with a disproportionate effect on the polish of focus indicators, because it controls whether a focus ring hugs the element tightly or stands clear of it. A focus outline drawn directly on the border can be hard to see, especially if the border and the outline are similar colours, or if the element's background is busy. An outline offset of a few pixels — outline-offset: 2px; or 4px; — separates the outline from the border by a gap, making it stand out as a distinct ring around the element, clearly visible against any background, and clearly signalling focus.
The gap created by outline-offset is transparent, like margin: it shows whatever lies behind the element, and it does not affect layout, because outlines never affect layout, as the previous section explained. That means an offset outline can overlap neighbouring content visually, if the offset is large and the layout is dense, but for the small offsets used for focus rings — 2 to 4 pixels — that overlap is negligible and the benefit in visibility is substantial. A negative offset draws the outline inside the border, which can be useful when an element is at the edge of a container and an outside outline would be clipped, or when the design wants a focus ring inset within the element rather than around it. Negative offsets are less common, but they are valid and occasionally the right solution for edge cases.
Outline-offset interacts with border-radius in modern browsers: an offset outline around a rounded element follows a rounded shape, expanded by the offset amount, so the focus ring remains concentric with the element's curve, which looks intentional rather than like a rectangle slapped over a rounded box. That behaviour is not universal in older browsers, where an offset outline might remain rectangular around a rounded element, but in current browsers it is consistent, and it is one reason offset focus rings look professional on rounded buttons and cards. Testing focus rings on rounded elements, at the offsets you use, is therefore part of polishing a design, not an optional extra.
The broader point is that focus indicators deserve design attention, not just default browser styling. A focus ring that is clearly visible, well-separated from the element, and consistent across the site signals to keyboard users that they are welcome and that their navigation is supported. Outline-offset is one of the tools for achieving that, alongside outline width, style, and colour, and together they allow a focus style that fits the site's design while remaining unmistakable. A few pixels of offset is a small detail, but it is the kind of detail that distinguishes a site where accessibility was considered from one where it was left to defaults — and it costs a single declaration to get right.
Check: What does a positive outline-offset do to a focus ring?
Section 45 — Rounded corners and percentages
Border-radius percentages are relative to the element's dimensions: the horizontal radius is a percentage of the width, and the vertical radius a percentage of the height. That dual basis means a percentage radius produces different curves on rectangles and squares, and it is the key to understanding why 50% makes a circle on a square but an ellipse on a rectangle. On a square element, 50% of the width equals 50% of the height, so the horizontal and vertical radii are equal, and the four quarter-circles meet to form a full circle. On a rectangular element, 50% of the width is larger than 50% of the height, so the horizontal radius exceeds the vertical radius, and the four quarter-ellipses meet to form an ellipse, wider than it is tall. That ellipse is often the desired effect for pill shapes and oval badges, but it surprises authors who expected a circle.
The percentage basis also means that a radius percentage scales with the element: a card at border-radius: 10%; has a larger absolute curve when it is wider, because 10% of a larger width is more pixels, while a card at border-radius: 8px; has the same absolute curve at any size. Which behaviour is desired depends on the design: for avatars and circular elements, percentages are correct, because the curve should remain proportional as the element scales; for cards and buttons, fixed pixel radii are usually correct, because the curve should feel consistent across sizes, not grow with the element. A card that doubles in width should not necessarily double its corner curve, because the curve is a detail, not a proportion of the card. Choosing between percentage and pixel radii is therefore a design decision about whether the curve should scale or stay constant.
Elliptical radii, where horizontal and vertical values are given separately with a slash, as in border-radius: 50% / 30%;, allow explicit control over both dimensions, producing an ellipse with a specified horizontal and vertical curvature. That form is less common, but it is useful for custom shapes, such as a banner with gently curved top corners that are wider than they are tall, or a badge with a distinctive oval profile. The slash syntax applies to the shorthand as well as to individual corners, and it follows the same value-count rules as other shorthands, with values before the slash for horizontal radii and values after it for vertical radii. Mastering the slash form is not essential for everyday work, but knowing it exists prevents confusion when it appears in existing code.
A final practical note: percentage radii are capped by the browser to avoid overlapping curves. If the radii of adjacent corners would overlap — for example, two corners each at 60% of the width on the same edge, totalling 120% — the browser scales them down proportionally so that they fit exactly, preserving their ratio. That capping ensures that rounded corners never produce impossible shapes, and it means that very large percentage radii degrade gracefully to the maximum possible curve, which is a pill or circle shape, rather than breaking. The rule is forgiving, like much of CSS, but understanding it prevents surprise when a large radius produces a pill shape instead of the more extreme curve that was requested.
Check: Why does border-radius: 50%; make an ellipse on a rectangle?
Section 46 — Clipping children to rounded corners
A parent's border-radius clips its background and border to the rounded shape, but not its children, unless the parent also has overflow: hidden. That distinction is the cause of a familiar bug: a card with rounded corners, containing an image at its top that extends to the card's edges, shows the image's square corners poking out beyond the card's rounded corners, spoiling the rounded effect. The explanation is that border-radius affects the painting of the element itself — its background and border are clipped to the curve — but child elements are painted independently, in their own boxes, which are rectangular unless they themselves are rounded. A child that fills its parent to the edges will therefore show its square corners outside the parent's curve, because nothing has told the child to be rounded, and the parent's curve does not automatically clip it.
The remedy is overflow: hidden on the parent, which clips all of the parent's content, including children, to the parent's shape, including its rounded corners. With overflow hidden, the image's corners are cut off at the parent's curve, and the card looks correctly rounded, with the image following the card's shape. That remedy works because overflow clipping respects the border shape: the clipping region is the parent's padding box, shaped by its border-radius, so anything outside that shaped region — including a child's square corner — is hidden. It is a clean, one-declaration fix, and it is the standard solution to the rounded-card-with-image problem, worth memorising as a pattern: rounded parent plus edge-to-edge child equals overflow hidden on the parent.
The remedy has a trade-off, which is the clipping side effect from Section 23: overflow hidden clips everything that extends beyond the parent, including shadows, dropdowns, and tooltips that should spill out. A rounded card with a dropdown menu that should extend below the card will have its dropdown clipped if the card has overflow hidden for its rounded corners, creating a conflict between two desired behaviours — rounded clipping and overflowing content — that cannot both be satisfied by overflow hidden alone. In such cases, alternatives include rounding the child's corners directly, to match the parent's, rather than clipping the child, or restructuring the layout so that the overflowing element is not a child of the rounded parent. Those alternatives are more work, but they preserve both behaviours, and they are worth considering when overflow hidden would break an interaction.
A related case is a parent with a background image or colour that should follow its rounded shape: that background is clipped automatically, without overflow hidden, because it belongs to the parent itself, not to a child. Only children need the overflow remedy, which is a useful diagnostic: if a rounded element's own background follows its curve but its child's content does not, the fix is overflow hidden; if the parent's own background does not follow its curve, the problem lies elsewhere, such as a missing border-radius on the element that actually has the background. Distinguishing parent painting from child painting, and knowing which one overflow affects, turns a confusing visual bug into a precise, fixable problem, and it is a good example of how the box model's painting rules, once understood, make layout bugs diagnosable rather than mysterious.
Check: Why does a child image poke out of a rounded parent's corners, and what fixes it?
Section 47 — The body's default margin
Browsers give the body element a default margin, usually 8 pixels, which creates a gap around the page's content. That default is part of the user-agent stylesheet, from Chapter 6, Section 27, and it exists for a historical reason: in the early web, pages were documents, and a small margin around the document made it look like a page rather than text jammed against the window's edge. On a modern site, that default margin is usually unwanted, because designs typically want full-bleed sections — hero images, coloured bands, navigation bars that extend to the viewport's edges — and an 8-pixel gap around everything prevents those sections from reaching the edge, producing a white frame that was not designed.
The standard remedy is to remove the body's margin explicitly, with body { margin: 0; }, usually as part of a base or reset layer at the top of the stylesheet. That single declaration gives the author full control over the page's edges: sections can extend to the viewport's edge when desired, and spacing can be added deliberately, with padding on containers or margins on elements, rather than relying on a browser default that applies uniformly and cannot be adjusted per section. Removing the default does not remove all spacing; it removes an uncontrolled spacing, replacing it with spacing that the author chooses, which is the general principle behind resets: replace browser defaults with deliberate decisions, so that every gap on the page is there because the author put it there, not because a browser default happened to create it.
There is a nuance worth noting: the body's margin can also collapse with the margins of its children, in the parent-child collapsing pattern from Section 13, which can produce surprising gaps at the top of a page. A first child with a top margin inside a body with a default margin can collapse through the body's edge, moving the whole page content down by the larger margin, rather than spacing the child inside the body. Removing the body's margin does not prevent that collapse — it merely changes the values involved — but it simplifies the situation, because the body's margin is no longer a participant, and the child's margin acts alone. For full control, some stylesheets also address the html element's margin and padding, though browsers do not give html a default margin, so body alone is usually sufficient.
More comprehensive resets go further, removing default margins and padding from many elements — headings, paragraphs, lists — to create a completely blank slate, but that approach, discussed in Chapter 6, Section 6 for the universal reset, has the cost of removing useful defaults that must then be re-added. The body's margin is a special case, because it affects the whole page's edges and is almost universally unwanted in modern design, so removing it alone is a safe, standard step, while removing all default margins is a judgement call that depends on the project's approach to base styles. For this chapter, the point is simple: know that the body has a default margin, know that it creates an 8-pixel frame, and know that body { margin: 0; } removes it, giving you control of the page's edges from the start.
Check: Why do most stylesheets start with body { margin: 0; }?
Section 48 — Padding or margin: a decision guide
Choose padding when the space should be inside the element, with its background and click area; choose margin when the space should be outside, transparent and separating. That single sentence is the decision guide for the most frequent spacing choice in CSS, and the rest of this section expands it into a set of questions that resolve the choice in practice. The questions are: should the space be coloured? Should it be clickable? Should it collapse with neighbouring space? Should it be part of the element's size? Each question points to one answer, and together they cover almost every case you will encounter.
If the space should be coloured with the element's background, it is padding, because backgrounds paint padding but not margin, as Section 30 explained. A card's internal breathing room, a button's coloured area around its label, a section's coloured band around its content — all are padding, because the colour must extend into the space. If the space should be transparent, showing the parent behind it, it is margin, because margins are transparent by definition, as Section 31 explained. A gap between cards on a grey page, showing grey, is margin, because the gap should be the page's colour, not the cards'. Asking "what colour should this space be?" therefore answers the padding-versus-margin question in many cases, without further analysis.
If the space should be clickable or hoverable as part of the element, it is padding, because padding is inside the box and participates in pointer events, while margin is outside and does not, as Section 31 noted. A button's tap target, a link's hover area, a menu item's clickable region — all should be enlarged with padding, not margin, because margin enlarges the gap around the element without enlarging the element itself. If the space should not be interactive — a gap between separate items, where clicking should land on the parent or on nothing — then margin is correct, because it creates separation without extending interactivity.
If the space should collapse with neighbouring space, following the document's vertical rhythm, it is margin, because only margins collapse, as Sections 12 to 14 explained. Spacing between paragraphs, between headings and paragraphs, and between sections in a document flow is usually margin, because collapsing produces the single-gap rhythm that documents need. If the space should never collapse, remaining exactly as specified regardless of neighbours, it is padding, because padding never collapses. Spacing inside a component — a card's internal gaps, a form's field spacing — is usually padding or gap, because components need predictable, non-collapsing spacing. And if the space should be part of the element's size for layout arithmetic — a box that must be exactly a certain total size including its internal space — then padding under border-box is the answer, because it lives inside the declared size, while margin always lives outside it. Running through those questions — colour, interactivity, collapsing, size — resolves the choice reliably, and with practice, the answers become immediate.
Check: A gap between two cards should show the page background. Should it be padding or margin?
Section 49 — Box model and responsive design
Responsive design depends on the box model, because fluid widths, maximum widths, and border-box sizing are what allow a layout to adapt to any screen. A responsive page is one whose boxes resize, reflow, and restack as the viewport changes, and every one of those behaviours is a box-model behaviour: widths expressed as percentages adapt to the container, maximum widths cap growth on large screens, border-box sizing keeps percentage arithmetic correct when padding is added, and automatic heights allow boxes to grow as text wraps to more lines on narrow screens. Without those box-model foundations, responsive techniques like media queries and flexible layouts would have nothing to work with, because the boxes themselves would not be flexible.
The core responsive pattern, from Sections 25 and 35, is a fluid width with a maximum: a container at 100% width, capped at a readable maximum, centred with auto margins, adapts to a phone by filling the screen, to a tablet by filling a wider screen, and to a desktop by stopping at the maximum and centring, with empty space on the sides. That pattern requires all three box-model ideas working together: the percentage width for fluidity, the maximum for capping, and border-box for ensuring that padding inside the container does not break the width. It also requires automatic height, so that the container grows as its content wraps on narrower screens, rather than clipping or overflowing. A responsive container is therefore not a special kind of box; it is an ordinary box, with ordinary box-model properties, chosen to adapt.
Padding and margin also adapt responsively, though less automatically. Fixed pixel padding that looks generous on a desktop can feel cramped or excessive on a phone, depending on the design, and responsive stylesheets often adjust padding at different screen sizes, using media queries to reduce padding on narrow screens and increase it on wide ones. That adjustment is a design decision, not an automatic behaviour: padding does not scale with the viewport unless it is expressed in a relative unit, such as a percentage of width or a viewport unit, and even then, the scaling follows width, not the design's intent, as Sections 11 and 36 warned. The professional approach is to set sensible default padding, then adjust it at breakpoints where the design needs it, rather than relying on automatic scaling to do the job.
Finally, responsive design exposes box-model mistakes more harshly than fixed design, because a mistake that is invisible at one width becomes visible at another. A row of percentage cards that fits on a desktop under content-box, because the overflow is small, may wrap badly on a tablet, where the overflow is proportionally larger. A fixed height that fits its content on a desktop may clip its content on a phone, where the text wraps to more lines and needs more height. A margin that collapses harmlessly on a wide screen may collapse through a parent on a narrow screen, where the structure differs. Testing at multiple widths — phone, tablet, desktop — is therefore not just a responsive check, but a box-model check, because it reveals sizing and spacing assumptions that only hold at one width.
Check: Why does responsive design rely on border-box sizing and maximum widths?
Section 50 — Chapter 8 in one paragraph
Every element is a box of content, padding, border, and margin, sized by width and height under a box-sizing model, spaced by margins that can collapse, and decorated by borders, radius, outlines, and shadows that may or may not affect layout. Mastering that model lets you predict sizes, spacing, and overflow instead of guessing. That summary gathers the chapter's threads into a single picture, and it is worth pausing to see how they connect, because the box model is not a list of isolated properties but a system in which each part interacts with the others. Content is what the box holds; padding is the space inside it that carries its background; border is its edge; margin is the space outside it that separates it from neighbours. Width and height measure the box, with box-sizing determining which layers they include. Margins collapse vertically, creating document rhythm, and they can be negative, auto, or percentage-based, each with its own behaviour. Borders, radius, outlines, and shadows decorate the box, with different effects on layout: borders affect size, radius affects painting, outlines and shadows affect neither.
The practical skills that follow from that picture are the ones this chapter has emphasised throughout. You can now calculate a box's total size under either box-sizing model, and you know why border-box is the standard. You can choose between padding and margin by asking whether the space should be coloured, clickable, collapsing, or part of the size. You can predict when margins will collapse, and you know how to prevent collapse when it is unwanted. You can centre a block with auto margins, constrain an image with maximum width, clip children to rounded corners with overflow hidden, and debug any spacing problem with the box-model diagram in developer tools. Those are not abstract accomplishments; they are the daily work of front-end layout, and they are the foundation for everything that follows.
Looking forward, the layout chapters that follow — on normal flow in more depth, on flexbox, and on grid — all arrange boxes, and they all assume the box model from this chapter. A flex item is a box with padding, border, and margin; a grid cell contains a box with the same layers; and the spacing between flex or grid items, whether by gap or by margin, follows the same principles of inside versus outside space that this chapter established. When a flex layout misbehaves, the cause is often a box-model issue — padding added to a percentage width, a margin collapsing unexpectedly, a fixed height clipping content — rather than a flexbox issue, and the box-model knowledge from this chapter is what lets you distinguish the two. For now, do the practical task below, which asks you to build a card layout and to measure its boxes, because the best way to internalise the box model is to build boxes, inspect them, and see the model in action on a real page.
Check: In your own words, name the four box layers and say which two affect an element's total size under content-box.
Practical task
Build a page with three cards in a row, each with a heading, a paragraph and a button. Use border-box sizing throughout, padding inside the cards, margins between them, a border and rounded corners on each card, and centre the row on the page with auto margins and a maximum width. Then open developer tools, inspect one card, and write down its content, padding, border and margin sizes from the box-model diagram, checking that the total matches what you expect.
Chapter questions
- A box has a declared width of 300px, 20px of padding on each side, and a 2px border on each side. What is its total width under content-box and under border-box?
- Two paragraphs have top and bottom margins of 24px and 16px. What is the gap between them, and why?
- When should you use padding instead of margin, and when should you use margin instead of padding? Give an example of each.
- A child element's top margin is moving its parent instead of spacing inside it. What is happening, and how do you fix it?
- Why does
margin: 0 auto;fail to centre a block that has no declared width?