Control size and spacing with the box model
Outcome
Section titled “Outcome”You will control the width and spacing of the profile page with the CSS box model. You will also use DevTools to explain an element’s computed content, padding, border, and margin.
Why this matters
Section titled “Why this matters”Every visible HTML element produces one or more boxes. A reliable box-model strategy helps you build layouts that remain readable when the content, viewport width, or text size changes.
What you will practice
- Identify content, padding, border, and margin and explain the purpose of each layer.
- Predict the rendered width of a box that uses content-box or border-box sizing.
- Use percentages, rem, px, width, and max-width for different sizing jobs.
- Explain how block and inline boxes participate in normal document flow.
- Recognize margin collapse and diagnose clipping or overflow caused by fixed dimensions.
- Use browser DevTools to inspect the computed box model and test temporary spacing changes.
What is new and what is reused
Section titled “What is new and what is reused”- New: The four box-model layers,
box-sizing, normal flow, block and inline boxes, fluid and maximum widths, logical spacing properties, margin collapse, overflow, and the computed box-model view in DevTools. - Reused: The
html-profileproject, external CSS, element and class selectors, CSS declarations, browser reloading, and DevTools inspection.
Starting point
Before you start
- The html-profile folder from the preceding CSS foundations lesson.
- index.html and styles.css at the same folder level.
- A profile page that already uses the supplied colors, typeface, heading styles, link style, footer border, and .project-entry class.
- VS Code and a current version of Edge, Chrome, or Firefox.
- Current state
- The profile page has visual styles, but its content still uses browser-default margins and has no deliberate maximum width or internal spacing system.
- First action
- Open html-profile/styles.css and find the existing .project-entry rule.
- First checkpoint
- Each project entry has visible space between its content and its border, and visible space between one project entry and the next.
- Help trigger
- Use the recovery note or ask for help if a box becomes wider than the page, text is clipped, or DevTools does not show the padding, border, and margin values from styles.css.
Required result
Section titled “Required result”You have completed the lesson when:
- every element uses
border-boxsizing through one shared rule; - the browser’s default body margin is replaced with an intentional page-width rule;
header,main, andfooteruse a fluid width, a maximum width, and automatic inline margins;- sections, the current-focus
aside, project entries, and the footer use deliberate margin or padding values; - project entries have visible content, padding, border, and margin layers;
- no repeated
brelements or empty HTML elements create visual space; - ordinary page text can grow vertically without a fixed height or hidden overflow; and
- you can inspect one project entry in DevTools and identify its content, padding, border, margin,
box-sizing, and computed width.
See the four box-model layers
Section titled “See the four box-model layers”The browser creates a box when it lays out an element. The box model describes four nested layers of that box.
Box model structure
Four layers around an element
Read from the outside toward the center.
The same structure in text is:
- Content: The text, image, or nested elements.
widthandheightcontrol this area under the default sizing model. - Padding: Space between the content and border. The element’s background is visible through the padding.
- Border: The visible boundary around the content and padding.
- Margin: Transparent space outside the border. Margin separates the element from nearby boxes.
Padding and margin both create space, but they do different jobs. Use padding when the space belongs inside an element’s boundary. Use margin when the space separates that element from another element.
Add all four layers to the project entries
Section titled “Add all four layers to the project entries”In styles.css, replace the existing .project-entry rule with this version:
/* Reusable project style */.project-entry { background-color: #ffffff; border: 2px solid #9aa9b8; margin-block: 1rem; padding: 1.25rem;}The project text is the content. padding creates space inside the border. The border shows the element’s boundary. margin-block creates space before and after the article in the page’s block direction, which is top to bottom for this English page.
rem is relative to the root element’s font size. With a common browser default of 16px, 1rem computes to 16px, but a user’s font settings can change that relationship. Relative spacing can therefore respond to the text settings.
- Save
styles.cssand reload the page. - Confirm that each project entry has a complete border on all four sides.
- Confirm that project text no longer touches the border.
- Confirm that a visible gap separates the two project entries.
If it does not work
Section titled “If it does not work”- If the old bottom border remains, confirm that you replaced the full
.project-entryrule instead of adding a second incomplete version. - If only one project entry changes, confirm that both
articleelements still containclass="project-entry". - If the text touches the border, inspect the spelling of
paddingand confirm that its declaration is inside the.project-entrybraces.
Checkpoint: Each project entry shows the four layers
- What now works
- Each project article contains text, internal padding, a complete border, and outside margin that separates it from the next article.
- Files changed
html-profile/styles.css- What remains
- Make width calculations predictable, constrain the page width, and add spacing to the larger page regions.
- Next action
- Go to the top of styles.css and add the shared box-sizing rule from the next section.
- If it does not work
- Inspect one project article and confirm that .project-entry supplies its border, margin-block, and padding declarations.
Understand normal document flow
Section titled “Understand normal document flow”Normal flow is the browser’s default method for placing boxes when no layout system or positioned layout takes over. The profile page already uses normal flow: the page regions and text appear in source order from top to bottom.
Two common box behaviors matter here:
| Box behavior | Profile-page examples | Default behavior |
|---|---|---|
| Block | header, main, section, article, h2, p, and footer |
Starts on a new line and normally uses the available inline width. The next block box follows it. |
| Inline | a and text inside a paragraph |
Participates in a line of text, fits its content, and can wrap with the text. A normal inline box does not take a declared width in the same way as a block box. |
The HTML element still describes the content’s meaning. The CSS display value controls the box behavior. Changing a link to a block box would not change it into a section, and changing a section’s display would not remove its semantic purpose.
You do not need to change display in this lesson. The next lesson will introduce Flexbox when related boxes need a one-dimensional layout instead of normal block flow.
Make width calculations predictable
Section titled “Make width calculations predictable”Most elements use box-sizing: content-box by default. Under this model, a declared width controls only the content area. Padding and border add to the rendered outer width.
Worked size comparison
The same width declaration can produce two outer widths
content-box
The declared width controls the content area.
- Calculation
240 + 48 + 8 = 296px- Included
- 240px content, 48px padding, and 8px border
border-box
The declared width controls the content, padding, and border together.
- Calculation
240px total- Included
- 184px content, 48px padding, and 8px border
border-box keeps the declared outer width stable. Margin stays outside the width in both sizing models.For the content-box example, the horizontal size is:
240px content+ 24px left padding + 24px right padding+ 4px left border + 4px right border= 296px outer widthFor the border-box example, the declared 240px already includes the content, padding, and border. The browser gives the content the remaining 184px.
Margin remains outside the declared width under both sizing models. Height calculations follow the same principle with top and bottom padding and borders.
Apply one sizing model to every element
Section titled “Apply one sizing model to every element”Add this rule at the top of styles.css, before the body rule:
/* Predictable sizing */* { box-sizing: border-box;}The universal selector * matches every element. The rule makes future width calculations include content, padding, and border. This lesson uses the universal selector for one shared sizing default; later CSS lessons will cover more selector patterns.
The rule might not create an obvious visual change yet because the project entries do not have a declared width. It changes how the browser will interpret the page-width rules in the next section.
- Save
styles.cssand reload the page. - Inspect one project entry in DevTools.
- Find
box-sizingin the Computed, Layout, or equivalent panel. - Confirm that the computed value is
border-box.
If it does not work
Section titled “If it does not work”- If DevTools shows
content-box, confirm that the selector is*and the declaration isbox-sizing: border-box;. - If the complete stylesheet stops applying after this edit, confirm that the rule has both braces and appears outside every other rule.
Control the page width
Section titled “Control the page width”A long line of text becomes difficult to scan. The page can use the available width on a small viewport and stop growing when the viewport becomes wide.
First, add margin: 0; to the existing body rule. Use this complete rule so the earlier text and color settings stay intact:
/* Page defaults */body { margin: 0; color: #1f2937; background-color: #f4f7fb; font-family: Arial, sans-serif; line-height: 1.6;}Browsers normally add a small default margin to body. Setting it to 0 removes that unknown outer space. The next rule provides the intentional page margins.
Add this rule after the body rule:
/* Page width */header,main,footer { width: 90%; max-width: 48rem; margin-inline: auto;}The commas form a selector list. The browser applies the same declaration block to each named element.
Each value has a different job:
width: 90%lets each region use 90 percent of its containing block’s width. The remaining space prevents the content from touching a narrow viewport’s edges.max-width: 48remstops the regions from growing beyond a readable measure.margin-inline: autodistributes the remaining inline space equally on both sides, so each block is centered. The inline direction runs from left to right on this English page.
The width can shrink below 48rem; the max-width only sets an upper limit. The element keeps its natural height, so its content can wrap and add more lines.
- Save and reload the page.
- Make the browser window narrow. Confirm that the three page regions remain inside the viewport and keep space on both sides.
- Make the window wide. Confirm that the content stops growing and remains centered.
- At 200% browser zoom, confirm that the page text wraps and remains visible.
If it does not work
Section titled “If it does not work”- If a region touches the viewport edge, confirm that it matches the
header, main, footerselector list and thatwidthis90%. - If the regions stay on the left, confirm that
margin-inlinehas the valueautoand that the regions have a width smaller than their containing block. - If the page has horizontal scrolling, inspect the widest visible element and confirm that the universal
border-boxrule applies.
Checkpoint: The page width is fluid and limited
- What now works
- Header, main, and footer use 90 percent of the available width, stop at 48rem, and remain centered. Every inspected element uses border-box sizing.
- Files changed
html-profile/styles.css- What remains
- Add deliberate vertical spacing, account for collapsing margins, test overflow, and inspect computed dimensions.
- Next action
- Add the section, aside, and footer spacing rules from the next section.
- If it does not work
- Inspect header or main and confirm that width, max-width, margin-inline, and box-sizing all appear as active declarations.
Add spacing in normal flow
Section titled “Add spacing in normal flow”Use CSS to control visual spacing. Keep the semantic HTML unchanged. Repeated br elements and empty elements do not describe content, and they make the spacing difficult to maintain.
Add these rules after the page-width rule:
/* Region spacing */section,aside { margin-block: 2rem;}
aside { border-inline-start: 0.25rem solid #1f4e79; padding-inline-start: 1rem;}
footer { margin-block-start: 2rem; padding-block: 1.5rem;}margin-block controls the outside space at the start and end of the block direction. padding-inline-start adds inside space between the aside’s left border and its content on this English page. These logical properties describe the writing direction instead of naming a physical side.
The existing footer border now has padding below and above its content. The footer’s top margin separates its border from the preceding page content.
Account for collapsing margins
Section titled “Account for collapsing margins”Vertical margins of adjacent block boxes in normal flow can collapse. When the bottom margin of one box meets the top margin of the next box, the browser uses one combined margin instead of adding both positive margins together.
The new sections use margin-block: 2rem. When two sections are adjacent, the space between them is normally 2rem, not 4rem. If two positive adjoining margins differ, the larger margin normally determines the collapsed space.
This behavior applies to some vertical block margins in normal flow. Padding and borders do not collapse. Horizontal margins do not collapse. Flex and grid items also follow different margin behavior.
Do not add extra empty HTML to compensate for a margin that collapsed. Inspect the two boxes, then decide whether the space belongs inside one box as padding or between boxes as margin.
- Save and reload the page.
- Confirm that the main sections and current-focus aside have clear vertical separation.
- Confirm that the aside’s text has space after its left border.
- Confirm that the footer text has space inside the top border.
- Inspect the gap between two adjacent sections. Confirm in DevTools that each section has a
2remblock margin even though the visible gap is not4rem.
If it does not work
Section titled “If it does not work”- If an aside border touches its text, confirm that
padding-inline-startis on theasiderule, not thesection, asiderule. - If the footer border disappears, keep the existing
border-topdeclaration from the preceding lesson in the earlierfooterrule. - If a gap is larger than expected, inspect both adjacent elements and identify every active margin before changing a value.
Test overflow without hiding content
Section titled “Test overflow without hiding content”Overflow occurs when content does not fit inside the box dimensions available to it. The browser’s default visible overflow protects content from being silently clipped, but it can also reveal an unsuitable fixed size.
Run this temporary experiment in the .project-entry rule:
.project-entry { background-color: #ffffff; border: 2px solid #9aa9b8; height: 4rem; margin-block: 1rem; overflow: hidden; padding: 1.25rem;}Save and reload. A project description can become partly or completely hidden because 4rem must contain the text, padding, and border. Zooming the browser or adding text makes the problem more severe.
Remove height: 4rem; and overflow: hidden;, then save and reload again. The project entries return to their content-based height, and all text remains visible.
overflow: auto can provide a scrollbar for a deliberately constrained region, such as a code sample. It is not a good default repair for ordinary article text. Let a text container grow unless the interface has a specific reason to constrain it.
- Confirm that you observed clipped content during the temporary experiment.
- Confirm that both temporary declarations are now removed.
- Reload at 200% zoom and confirm that each project entry grows to contain all of its text.
If it does not work
Section titled “If it does not work”- If nothing becomes clipped, temporarily reduce the height to
3remor add one sentence to a project description. Remove the temporary change after the observation. - If text remains clipped after the test, search
styles.cssforheightandoverflowand remove the two temporary declarations from.project-entry.
Inspect the computed box model in DevTools
Section titled “Inspect the computed box model in DevTools”DevTools can show the browser’s final used dimensions after it applies percentages, relative units, the cascade, and the sizing model.
- Reload the saved page.
- Right-click one project entry and select Inspect.
- Move to the selected
article class="project-entry"in the element tree if DevTools selected a nested heading or paragraph. - Open the Computed, Layout, or equivalent panel.
- Find the box-model diagram. Identify the values for content size, padding, border, and margin.
- Find
box-sizingand confirm that its value isborder-box. - In the Styles or Rules panel, change
padding: 1.25remtemporarily topadding: 2rem. - Confirm that the content area becomes smaller while the article’s available outer width remains stable.
- Reload the page. The temporary DevTools edit disappears.
- Inspect
main, resize the browser, and watch its computed width change until it reaches the48remmaximum.
The exact panel name and displayed numbers depend on the browser and viewport width. The required evidence is the relationship: content sits inside padding, padding sits inside the border, margin remains outside, and border-box includes the first three parts in a declared width.
If it does not work
Section titled “If it does not work”- If the diagram shows zeros for padding or margin, confirm that DevTools selected the
articlerather than its child heading. - If a value appears crossed out, another declaration won in the cascade. Select the active declaration to identify its source file and line.
- If a temporary DevTools change remains after reload, confirm that you did not also save the same value in
styles.css.
Checkpoint: The computed box model matches the CSS
- What now works
- DevTools shows each project entry's content, padding, border, margin, border-box sizing, and computed width. Temporary DevTools edits disappear after reload.
- Files changed
html-profile/styles.css- What remains
- Complete the final checks and explain how the sizing and spacing rules produce the visible page.
- Next action
- Complete the self-check against the saved source and rendered page.
- If it does not work
- Select article.project-entry first, then inspect one layer or computed property at a time.
Self-check
Complete these checks against the required result.
- Point to one project entry and identify its content, padding, border, and margin in the rendered page.
- Confirm that the universal selector sets box-sizing to border-box for every inspected element.
- Explain why the 240px content-box example becomes 296px wide and why the border-box example remains 240px wide.
- Confirm that header, main, and footer use width: 90%, max-width: 48rem, and margin-inline: auto.
- Explain why the percentage, rem, and px values have different jobs in the page styles.
- Identify one block box and one inline box in the profile page and describe their normal-flow behavior.
- Confirm that sections, the current-focus aside, project entries, and footer have the required margin or padding.
- Explain why two adjoining 2rem vertical margins can produce a 2rem gap instead of a 4rem gap.
- Search index.html and confirm that no repeated br elements or empty elements create visual spacing.
- Search styles.css and confirm that .project-entry no longer contains the temporary height or overflow declarations.
- View the page in a narrow browser window and at 200% zoom. Confirm that all content remains visible and that the page has no unintended horizontal scrolling.
- Use DevTools to identify the computed content size, padding, border, margin, and box-sizing of one project entry.
How the browser resolves the layout
Section titled “How the browser resolves the layout”The browser first places the profile page’s block and inline boxes in normal flow. It then resolves relative sizes against their containing blocks and font sizes. max-width limits the fluid page regions, and automatic inline margins center them.
For each box, the browser calculates the content area, adds padding and border according to box-sizing, and places margin outside the border. Some adjoining vertical block margins collapse. Content can increase the box’s height because the required styles do not force a fixed height.
This model provides a stable base for Flexbox. Flexbox will change how a container arranges its direct children, but every flex item still has the same content, padding, border, and margin layers.
Record the box-model checkpoint
Section titled “Record the box-model checkpoint”After the required self-check passes, record the working state in the existing html-profile repository:
git statusgit diffgit add index.html styles.cssgit diff --stagedgit commit -m "Improve profile sizing and spacing"git pushIf index.html did not change, stage only styles.css. Reload GitHub and confirm that the newest commit contains no temporary overflow experiment.
Next step or safe stopping point
Section titled “Next step or safe stopping point”The required lesson is complete when the profile page uses predictable sizing, fluid but limited page widths, deliberate spacing, and content-based heights, and when you can explain the computed box model in DevTools.
Continue to Arrange content with Flexbox to arrange related boxes along a row or column while preserving the box-model rules from this lesson.
If you stop here, leave yourself this resume note: The box model and page width are working. Next, open the Flexbox lesson and identify which direct children should become flex items.