We are still cooking the magic in the way!
The CSS Box Model In-Depth
Understanding the CSS Box Model
Every single element rendered on a web page is treated by the browser as a rectangular box. The CSS Box Model is the fundamental concept that describes how these rectangular boxes are structured, sized, and spaced. It is not an exaggeration to say that the box model is the single most important concept in CSS layout. Every width you set, every bit of spacing you add, every border you draw -- all of it operates within the rules of the box model. If you do not understand the box model deeply, you will spend countless hours debugging layouts that behave in ways you did not expect.
The box model has four distinct layers, each wrapping around the previous one from the inside out. Think of it like an onion with four layers, or a picture inside a frame with a mat and then wall space around it:
- Content -- The innermost area where your actual content lives: text, images, child elements, videos, or any other content. When you set
widthandheighton an element, in the default box model, you are setting the size of this content area only. - Padding -- The transparent breathing room between the content and the border. Padding pushes the border outward, away from the content. A critical detail: the element's background color and background image extend into the padding area. This means padding is visually "inside" the element.
- Border -- A line (visible or invisible) that wraps around the padding. The border can have its own width, style, and color. It sits between the padding and the margin.
- Margin -- The transparent space outside the border that creates distance between this element and its neighbors. The background does not extend into the margin. Margin is always transparent.
The box-sizing Property: content-box vs border-box
The box-sizing property controls a fundamental question: when you set width and height on an element, what exactly are you sizing? The answer depends on which box-sizing model is active. There are two possible values, and the difference between them is the source of more confusion and layout bugs than almost anything else in CSS.
content-box: The Default (and the Problem)
By default, every element uses box-sizing: content-box. In this model, the width and height properties set the size of the content area only. Any padding and border you add are calculated on top of the specified width and height, making the element's actual rendered size larger than the dimensions you wrote in your CSS.
Example: The Problem with content-box
/* With content-box (the default): */
.card {
width: 300px;
padding: 20px;
border: 5px solid #333;
/* Let's calculate the actual rendered width:
Content width: 300px (what you set)
+ Padding left: 20px
+ Padding right: 20px
+ Border left: 5px
+ Border right: 5px
= Total width: 350px (50px MORE than you wanted!)
*/
}
/* This becomes a real problem with percentages: */
.half-width {
width: 50%;
padding: 20px;
border: 1px solid #ccc;
/* Total width = 50% + 40px padding + 2px border
This OVERFLOWS the parent container because the total
exceeds 50% of the parent's width! Two of these
side by side will NOT fit in a row. */
}With content-box, you constantly have to do mental math. The actual space an element occupies horizontally is: width + padding-left + padding-right + border-left-width + border-right-width. Vertically it is: height + padding-top + padding-bottom + border-top-width + border-bottom-width. This makes responsive layouts frustrating because percentage-based widths break the instant you add any padding or border. It also makes it nearly impossible to create multi-column layouts where columns add up to exactly 100%.
border-box: The Better Option
When you set box-sizing: border-box, the behavior changes dramatically. Now the width and height properties include the content, padding, and border. The browser automatically subtracts the padding and border from the specified width to determine how much space the content area gets. The result is that an element's total rendered size always matches what you specified.
Example: The Simplicity of border-box
/* With border-box: */
.card {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 5px solid #333;
/* Total rendered width = 300px (EXACTLY what you set)
The browser calculates:
Content area = 300 - 20 - 20 - 5 - 5 = 250px
The content area shrinks to accommodate padding and border,
but the overall element stays at exactly 300px. */
}
/* Percentage widths work perfectly now: */
.half-width {
box-sizing: border-box;
width: 50%;
padding: 20px;
border: 1px solid #ccc;
/* Total width = exactly 50% of parent. Period.
Content area adjusts automatically.
Two of these side by side fit perfectly! */
}
/* A three-column layout that actually works: */
.column {
box-sizing: border-box;
width: 33.333%;
padding: 15px;
border: 1px solid #ddd;
float: left;
/* All three columns fit in exactly 100% width */
}Why border-box is Universally Preferred
Almost every modern CSS framework, CSS reset, and professional developer uses border-box as the default for all elements. The reasons are entirely practical:
- Predictable sizing -- When you set
width: 300px, the element is 300px wide. No surprises, no extra math, no overflow. - Responsive layouts work -- You can set
width: 50%and add as much padding and border as you want without ever overflowing the parent. - Grid and column layouts -- Creating a three-column layout where each column is
width: 33.33%with padding actually works, instead of breaking because padding pushes the total width past 100%. - Less mental math -- You no longer need to subtract padding and border from your desired total width. What you write is what you get.
- Consistency with design tools -- When a designer says "this card is 300px wide," they mean the whole card, including its padding and border.
border-boxmatches that mental model.
The Universal box-sizing Reset
Because border-box is so universally preferred, developers apply it globally to every element on the page. The recommended approach uses the inherit pattern, which makes it easy to override for specific components if needed:
Example: The Universal box-sizing Reset
/* THE RECOMMENDED GLOBAL RESET */
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
/*
Why use inherit instead of just setting border-box on *?
If you wrote: * { box-sizing: border-box; }
That works, but it means EVERY element is locked to border-box.
If you embed a third-party widget that expects content-box,
you cannot change it without overriding every element inside it.
With the inherit approach:
- All elements inherit border-box from html by default
- If a third-party component needs content-box, you set it
on the component's root element, and all its children
automatically inherit content-box.
*/
/* Example: A third-party widget that requires content-box */
.legacy-widget {
box-sizing: content-box;
/* All children of .legacy-widget inherit content-box
because they use box-sizing: inherit */
}
/* Another approach (simpler, used by many frameworks): */
*, *::before, *::after {
box-sizing: border-box;
}
/* This is simpler but less flexible for third-party overrides */box-sizing: border-box reset at the very top of your CSS file, before any other styles. This single rule will save you from countless layout headaches throughout your entire project. Every major CSS framework -- Bootstrap, Tailwind CSS, Foundation, Bulma -- includes this reset. It is considered an absolute best practice in modern CSS.Padding in Detail
Padding creates space between the content of an element and its border. It is considered "inside" the element: the element's background color and background image extend through the padding area. Padding values cannot be negative -- if you need to pull content in the opposite direction, you need to use negative margins instead.
Padding Shorthand and Longhand
The padding shorthand property accepts one, two, three, or four values. The browser interprets them differently depending on how many you provide:
Example: Padding Shorthand Values
/* ONE VALUE: applies to ALL four sides */
.box-a {
padding: 20px;
/* top = 20px, right = 20px, bottom = 20px, left = 20px */
}
/* TWO VALUES: vertical | horizontal */
.box-b {
padding: 10px 30px;
/* top = 10px, right = 30px, bottom = 10px, left = 30px */
}
/* THREE VALUES: top | horizontal | bottom */
.box-c {
padding: 10px 20px 30px;
/* top = 10px, right = 20px, bottom = 30px, left = 20px */
}
/* FOUR VALUES: top | right | bottom | left (clockwise from top) */
.box-d {
padding: 10px 20px 30px 40px;
/* top = 10px, right = 20px, bottom = 30px, left = 40px */
}
/* LONGHAND: Individual side properties */
.box-e {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;
}margin, border-width, border-style, and border-color shorthand properties as well. Once you memorize it, you will use it everywhere.Percentage Padding
When you use percentages for padding, something surprising happens: all four sides -- including padding-top and padding-bottom -- are calculated relative to the element's containing block's width, not its height. This initially seems counterintuitive, but it is by design and has a useful application.
Example: Percentage Padding for Aspect Ratios
/* Percentage padding is relative to the parent's WIDTH */
.parent {
width: 400px;
}
.child {
padding: 10%;
/* All four sides get 40px (10% of 400px parent width) */
/* Even padding-top and padding-bottom are based on WIDTH */
}
/* Classic trick: maintaining aspect ratios with percentage padding */
.aspect-ratio-16-9 {
width: 100%;
height: 0;
padding-bottom: 56.25%; /* 9/16 = 0.5625 = 56.25% */
position: relative;
overflow: hidden;
}
.aspect-ratio-16-9 > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Modern alternative: the aspect-ratio property */
.modern-aspect-ratio {
width: 100%;
aspect-ratio: 16 / 9;
/* Much simpler! But the padding trick is still useful
for older browser support */
}aspect-ratio CSS property now provides a simpler solution, but understanding the padding trick is still valuable because you will encounter it in older codebases and it works in browsers that do not yet support aspect-ratio.Margin in Detail
Margin creates space outside the border of an element. It pushes adjacent elements away to create distance. Unlike padding, the background color does not extend into the margin area -- margins are always transparent. And unlike padding, margin values can be negative, which we will explore shortly.
Margin Shorthand and Longhand
The margin shorthand follows exactly the same one-to-four value pattern as padding (TRBL clockwise order):
Example: Margin Shorthand and the auto Value
/* Same shorthand pattern as padding */
.box {
margin: 20px; /* all four sides */
margin: 10px 30px; /* vertical | horizontal */
margin: 10px 20px 30px; /* top | horizontal | bottom */
margin: 10px 20px 30px 40px; /* top | right | bottom | left */
}
/* Individual side properties */
.box-sides {
margin-top: 10px;
margin-right: auto;
margin-bottom: 10px;
margin-left: auto;
}
/* THE AUTO VALUE: Centering Block Elements Horizontally */
.centered-box {
width: 600px;
margin: 0 auto;
/* How this works:
- top and bottom margins are 0
- left and right margins are "auto"
- The browser calculates the remaining horizontal space
in the parent and splits it equally between left and right
- Result: the element is perfectly centered horizontally
*/
}
/* Common pattern for page containers */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
/* Centered, never wider than 1200px, with some
horizontal padding so content does not touch edges */
}
/* Pushing an element to the right with auto */
.push-right {
margin-left: auto;
/* In a flex container, this pushes the element
to the far right side */
}auto value for margin only works for horizontal centering on block-level elements that have a defined width. It does not work for vertical centering in normal document flow, and it does not work on inline elements. For vertical centering, you need Flexbox (align-items: center) or Grid (place-items: center). However, in a Flexbox context, margin: auto does work in both directions, which is a powerful centering technique.Margin Collapsing
Margin collapsing is one of the most confusing and surprising behaviors in CSS. When two vertical margins (top/bottom) touch each other, they do not add up. Instead, they collapse into a single margin whose size equals the larger of the two values. This behavior only applies to vertical margins in the normal document flow -- horizontal margins (left/right) never collapse.
Scenario 1: Adjacent Siblings
When two block-level siblings are stacked vertically, the bottom margin of the first element collapses with the top margin of the second element:
Example: Margin Collapsing Between Siblings
<style>
.first {
margin-bottom: 30px;
background: lightblue;
padding: 20px;
}
.second {
margin-top: 20px;
background: lightcoral;
padding: 20px;
}
</style>
<div class="first">First element (margin-bottom: 30px)</div>
<div class="second">Second element (margin-top: 20px)</div>
/* Expected gap: 30px + 20px = 50px? WRONG!
Actual gap: 30px (the larger of the two values wins)
The margins COLLAPSE into a single 30px margin. */
/* If both margins are equal: */
.equal-a { margin-bottom: 25px; }
.equal-b { margin-top: 25px; }
/* Gap = 25px (not 50px) */
/* If one margin is 0: */
.has-margin { margin-bottom: 40px; }
.no-margin { margin-top: 0; }
/* Gap = 40px (the larger of 40 and 0) */Scenario 2: Parent and First/Last Child
If there is no border, padding, inline content, or block formatting context separating a parent's margin from its first (or last) child's margin, those margins collapse together. The child's margin effectively "leaks out" through the parent:
Example: Parent-Child Margin Collapsing
<style>
/* THE PROBLEM: */
.parent {
margin-top: 40px;
background: lightyellow;
/* No padding-top, no border-top! */
}
.child {
margin-top: 25px;
background: lightgreen;
padding: 10px;
}
</style>
<div class="parent">
<div class="child">Child with 25px top margin</div>
</div>
/* The child's 25px top margin collapses with the parent's
40px top margin. The result is a single 40px margin
ABOVE the parent. Inside the parent, the child appears
flush against the top -- there is NO space between the
parent's top edge and the child. The margin "leaked out." */
/* THE FIX: Add ANY separation between the margins */
/* Fix 1: Add padding to the parent */
.parent-fix-1 {
margin-top: 40px;
padding-top: 1px; /* Even 1px prevents collapse! */
background: lightyellow;
}
/* Fix 2: Add a border to the parent */
.parent-fix-2 {
margin-top: 40px;
border-top: 1px solid transparent;
background: lightyellow;
}
/* Fix 3: Create a new Block Formatting Context (BFC) */
.parent-fix-3 {
margin-top: 40px;
overflow: hidden; /* Creates a BFC */
background: lightyellow;
}
/* Fix 4: Use display: flow-root (modern, explicit BFC) */
.parent-fix-4 {
margin-top: 40px;
display: flow-root;
background: lightyellow;
}Scenario 3: Empty Blocks
If a block element has no height, no padding, no border, and no content, its own top and bottom margins collapse into a single margin:
Example: Empty Block Margin Collapsing
<style>
.empty {
margin-top: 20px;
margin-bottom: 30px;
/* No height, no padding, no border, no content */
}
</style>
<div class="above">Above</div>
<div class="empty"></div>
<div class="below">Below</div>
/* The empty div's top (20px) and bottom (30px) margins
collapse into a single 30px margin. Then that 30px
margin may further collapse with the margins of the
elements above and below it! */How to Prevent Margin Collapsing
There are several reliable ways to prevent margin collapsing:
- Add
padding(even 1px) between the margins that are collapsing. - Add a
border(even 1px solid transparent) between the margins. - Use
overflow: hiddenoroverflow: autoon the parent to create a new Block Formatting Context (BFC). - Use
display: flexordisplay: gridon the parent. Flex and grid containers do not have margin collapsing between their children. - Use
display: flow-rooton the parent, which explicitly creates a new BFC without any side effects. - Add inline content (even a non-breaking space
) between the parent and child.
margin-bottom on elements (never margin-top), or vice versa. This way, vertical margins never touch and cannot collapse.Negative Margins and Their Uses
Unlike padding (which cannot be negative), margins can have negative values. Negative margins pull an element in the opposite direction of what a positive margin would do. They effectively reduce the space an element takes up, and can even cause elements to overlap.
Example: Negative Margins in Practice
/* Pull an element upward, overlapping the element above */
.overlap-up {
margin-top: -20px;
/* The element moves up 20px from where it would
normally be, overlapping whatever is above it */
}
/* Pull an element to the left */
.pull-left {
margin-left: -15px;
}
/* PRACTICAL USE 1: Breaking out of a container's padding */
.container {
padding: 30px;
background: #f5f5f5;
}
.full-width-image {
margin-left: -30px;
margin-right: -30px;
/* The image extends to the edges of the container,
ignoring the container's 30px padding on both sides */
}
/* PRACTICAL USE 2: Overlapping card design */
.card-overlap {
margin-top: -40px;
position: relative; /* So it appears above the element behind it */
z-index: 1;
background: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* PRACTICAL USE 3: Removing extra spacing from child elements */
.grid {
display: flex;
flex-wrap: wrap;
margin: -10px; /* Counteract the 10px margin on children */
}
.grid-item {
margin: 10px;
width: calc(33.333% - 20px);
}
/* PRACTICAL USE 4: Old-school centering (historical) */
.old-center {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 300px;
margin-top: -150px; /* Half the height */
margin-left: -200px; /* Half the width */
/* Modern alternative: transform: translate(-50%, -50%) */
}Width and Height: auto Behavior, min/max Properties
The width and height properties control the dimensions of the content area (in content-box) or the entire box up to the border (in border-box). Understanding how these properties behave by default, and how to use min/max constraints, is essential for responsive design.
The Default: auto
By default, both width and height are set to auto. But "auto" means different things for each:
- width: auto on a block element means "take up the full available width of the parent, minus my own margins." The element stretches to fill its container.
- height: auto means "be exactly as tall as needed to contain all my content." The element shrinks to fit.
- width: auto on an inline or inline-block element means "be as wide as my content needs."
Example: Width and Height Behavior
/* Block element with width: auto (the default) */
.block-default {
/* width: auto -- fills the parent's width */
/* height: auto -- shrinks to fit content */
background: lightblue;
padding: 20px;
}
/* Setting a fixed width */
.fixed-width {
width: 400px;
/* PROBLEM: On screens narrower than 400px, this overflows! */
}
/* Using max-width for responsive sizing */
.responsive-width {
width: 100%;
max-width: 400px;
/* Takes full parent width but never exceeds 400px */
/* On small screens: 100% of parent (responsive) */
/* On large screens: stops at 400px */
}
/* min-width sets a floor */
.min-example {
min-width: 200px;
/* Element will never be narrower than 200px,
even if its parent is narrower (it will overflow) */
}
/* Common responsive container pattern */
.container {
width: 100%;
max-width: 1200px;
min-width: 320px;
margin: 0 auto;
padding: 0 20px;
}
/* min-height: at least this tall, but can grow */
.hero-section {
min-height: 100vh;
/* At least the full viewport height,
but grows taller if content needs it */
}
/* max-height with overflow handling */
.scrollable-list {
max-height: 400px;
overflow-y: auto;
/* Never taller than 400px; shows scrollbar if needed */
}
/* DANGER: Fixed height on text containers */
.bad-practice {
height: 200px;
/* If the text content is taller than 200px,
it will OVERFLOW and overlap elements below!
Never set fixed height on text containers. */
}
.good-practice {
min-height: 200px;
/* At least 200px, but grows with content. Safe! */
}height on elements that contain text is one of the most common CSS mistakes. Text length varies based on language, viewport width, user font size settings, and dynamic content from databases. Use min-height if you need a minimum dimension, and let the element grow naturally. Similarly, prefer max-width over fixed width for responsive layouts.Inline vs Block Box Model Differences
The display property fundamentally changes how an element participates in the box model. The two most basic display values -- block and inline -- treat box model properties very differently, and understanding these differences is critical.
Block Elements
Block-level elements (like <div>, <p>, <h1>-<h6>, <section>, <article>) respect all box model properties fully:
widthandheightwork as expected.paddingon all four sides works normally -- it pushes content inward and expands the element visually.marginon all four sides works normally -- it creates space around the element.- By default, a block element takes up the full available width of its parent.
- Each block element starts on a new line.
Inline Elements
Inline elements (like <span>, <a>, <strong>, <em>, <code>) have significant limitations in the box model:
widthandheightare completely ignored. The element's size is determined by its content.padding-topandpadding-bottomare applied visually (the background extends), but they do not push away surrounding content. The padding overlaps adjacent lines.margin-topandmargin-bottomare completely ignored.padding-left,padding-right,margin-left, andmargin-rightwork normally.- Multiple inline elements sit side by side on the same line, flowing like text.
inline-block: The Best of Both Worlds
The display: inline-block value gives you inline flow behavior (elements sit side by side) combined with block-level box model behavior (all properties work):
Example: Block vs Inline vs Inline-Block
<style>
/* BLOCK: all box model properties work, full width, new line */
.block-demo {
display: block;
width: 250px;
height: 80px;
padding: 15px;
margin: 15px;
border: 2px solid blue;
background: lightblue;
}
/* INLINE: width/height ignored, vertical margin ignored */
.inline-demo {
display: inline;
width: 250px; /* IGNORED */
height: 80px; /* IGNORED */
padding: 15px; /* Horizontal works; vertical overlaps */
margin: 15px; /* Horizontal works; vertical IGNORED */
border: 2px solid red;
background: lightcoral;
}
/* INLINE-BLOCK: all properties work, no forced new line */
.inline-block-demo {
display: inline-block;
width: 250px; /* Works! */
height: 80px; /* Works! */
padding: 15px; /* Works on all sides! */
margin: 15px; /* Works on all sides! */
border: 2px solid green;
background: lightgreen;
}
</style>
<div class="block-demo">Block</div>
<span class="inline-demo">Inline</span>
<span class="inline-block-demo">Inline-Block</span>Example: Practical inline-block Usage
/* Navigation links with inline-block */
.nav-links a {
display: inline-block;
padding: 10px 20px;
margin-right: 4px;
background: #2c3e50;
color: white;
text-decoration: none;
border-radius: 4px;
transition: background 0.2s;
}
.nav-links a:hover {
background: #34495e;
}
/* Card grid with inline-block */
.card {
display: inline-block;
width: 30%;
margin: 1.5%;
padding: 20px;
vertical-align: top; /* Align tops of cards */
border: 1px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
}
/* IMPORTANT: inline-block elements are affected by
whitespace in HTML. Spaces or newlines between
inline-block elements create small gaps. Solutions:
1. Remove whitespace in HTML
2. Set font-size: 0 on parent, reset on children
3. Use flexbox instead (recommended) */inline-block is still perfectly valid, Flexbox and CSS Grid have largely replaced it for multi-element layouts. Flexbox eliminates the whitespace gap issue and provides much better control over alignment, spacing, and distribution. Use inline-block for simple one-off styling, and Flexbox or Grid for component and page layouts.Using DevTools to Inspect the Box Model
Browser DevTools provide powerful visual tools for understanding and debugging the box model. Here is how to use them effectively:
DevTools Box Model Inspection Steps
/* Step 1: Open DevTools */
/* Right-click any element -> "Inspect" (or press F12 / Cmd+Opt+I) */
/* Step 2: Select an element in the Elements panel */
/* Click on any element in the DOM tree */
/* Step 3: Find the Box Model diagram */
/* In Chrome: Look in the "Computed" tab or scroll down in "Styles" */
/* In Firefox: Look in the "Layout" tab or "Box Model" section */
/* Step 4: Read the values */
/* The diagram shows nested rectangles:
- Outermost (orange): margin values
- Next (yellow/olive): border values
- Next (green): padding values
- Innermost (blue): content dimensions (width x height)
*/
/* Step 5: Hover over elements */
/* When you hover over an element in the Elements panel,
the page highlights:
- Content area in blue
- Padding in green
- Border in yellow/olive
- Margin in orange
This visual overlay is incredibly helpful for
understanding spacing issues. */
/* Step 6: Edit values live */
/* You can click on any value in the box model diagram
and change it directly. The page updates in real time.
This is perfect for experimenting with spacing. */
/* Step 7: Check computed box-sizing */
/* In the Computed tab, search for "box-sizing" to see
whether the element is using content-box or border-box.
This often explains why an element is wider/narrower
than you expected. */Common Pitfalls and How to Debug Them
Pitfall 1: Element Wider Than Expected
/* SYMPTOM: Your element overflows its container */
/* CAUSE: Using content-box with padding or border */
.problem {
width: 100%;
padding: 20px;
border: 1px solid #ccc;
/* Total width = 100% + 40px + 2px = overflows! */
}
/* FIX: Switch to border-box */
.solution {
box-sizing: border-box;
width: 100%;
padding: 20px;
border: 1px solid #ccc;
/* Total width = exactly 100%. Done. */
}Pitfall 2: Mysterious Gap Above a Container
/* SYMPTOM: There is a gap above your container that you
cannot explain, even though you set margin: 0 on it */
/* CAUSE: Parent-child margin collapsing. A child's margin-top
is "leaking through" the parent. */
.parent {
background: white;
/* No padding-top or border-top */
}
.first-child {
margin-top: 30px;
/* This 30px margin leaks OUTSIDE the parent! */
}
/* FIX: Add padding-top or overflow to the parent */
.parent-fixed {
background: white;
padding-top: 1px; /* Prevents collapse */
/* Or: overflow: hidden; */
/* Or: display: flow-root; */
}Pitfall 3: Width/Height Not Working on span or a
/* SYMPTOM: You set width and height on a <span> or <a>
but nothing happens */
/* CAUSE: These are inline elements. Inline elements
ignore width and height. */
span.tag {
width: 100px; /* Ignored! */
height: 30px; /* Ignored! */
padding: 5px 10px;
}
/* FIX: Change display to inline-block or block */
span.tag {
display: inline-block; /* Now width/height work! */
width: 100px;
height: 30px;
padding: 5px 10px;
}Pitfall 4: Adjacent Margins Not Adding Up
/* SYMPTOM: You expect 60px between two elements but only get 40px */
/* CAUSE: Margin collapsing between siblings */
.element-a { margin-bottom: 40px; }
.element-b { margin-top: 20px; }
/* Gap = 40px (not 60px) -- the larger margin wins */
/* FIX OPTION 1: Use padding on one element instead */
.element-a { margin-bottom: 0; padding-bottom: 40px; }
.element-b { margin-top: 20px; }
/* FIX OPTION 2: Only use margin in one direction */
.element-a { margin-bottom: 40px; }
.element-b { margin-top: 0; }
/* FIX OPTION 3: Wrap in a flex container */
.wrapper {
display: flex;
flex-direction: column;
/* Flex children do not have margin collapsing */
}Exercise 1: Box Model Exploration
Create an HTML page with four <div> elements. Give the first one box-sizing: content-box with width: 300px, padding: 20px, and border: 5px solid black. Give the second one box-sizing: border-box with the exact same width, padding, and border. Compare their rendered widths in DevTools. The first should be 350px total; the second should be 300px total. For the third, create a responsive card using max-width: 400px, width: 100%, and box-sizing: border-box with generous padding and a border, and verify it never exceeds 400px but shrinks on small screens. For the fourth, create a centered container using margin: 0 auto and max-width: 800px, then place a full-width banner inside it using negative margins to break out of the container's padding.
Exercise 2: Margin Collapsing Lab
Build a page that demonstrates all three types of margin collapsing. First, create two sibling <div> elements where the first has margin-bottom: 50px and the second has margin-top: 30px. Use DevTools to verify the gap is 50px (not 80px). Second, create a parent <div> with a background color and a child <div> with margin-top: 40px. Observe how the child's margin leaks out of the parent. Then fix it using four different methods: (a) padding-top: 1px, (b) border-top: 1px solid transparent, (c) overflow: hidden, and (d) display: flow-root. Third, create an empty <div> with margin-top: 20px and margin-bottom: 40px and verify that its total contribution to spacing is 40px. Finally, wrap all examples in a display: flex; flex-direction: column container and observe that collapsing stops.