In the previous lesson, width: 300px produced a 344px box because padding and border were added on top. The box-sizing property changes that rule, and almost every modern stylesheet switches it on the first line.
content-box versus border-box
box-sizing decides which part of the box width and height describe.
.content-box {
box-sizing: content-box; /* the default */
width: 300px;
padding: 20px;
border: 2px solid;
/* visible width: 300 + 40 + 4 = 344px */
}
.border-box {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid;
/* visible width: 300px; content shrinks to 256px */
}
| Value | width covers | Adding padding |
|---|---|---|
content-box | Content only | Makes the box bigger |
border-box | Content, padding and border | Makes the content area smaller |
With border-box, the number you write is the size you see. That makes layouts far easier to reason about, especially with percentages:
.column {
box-sizing: border-box;
width: 50%;
padding: 1.5rem; /* still exactly half the row */
}
With content-box, two of those columns would be 50% plus padding each, more than 100% in total, and the second would wrap below the first.
The common reset
Most projects apply border-box to every element:
*,
*::before,
*::after {
box-sizing: border-box;
}
The ::before and ::after selectors cover generated content, which you will meet in the pseudo-elements lesson. Put this rule at the very top of your stylesheet.
You may also see an "inherit" version: html { box-sizing: border-box; } *, *::before, *::after { box-sizing: inherit; }. It lets a third-party component switch back to content-box for its whole subtree. Either version is fine; pick one and use it everywhere.
width and height
Block elements such as <div>, <p> and <section> fill the available width by default. Their height grows to fit their content. In most cases that is exactly what you want, so leave both alone.
Avoid fixed heights on anything that contains text. height: 200px looks fine with your sample copy, then a longer translation, a larger font setting or a narrower screen makes the text overflow and spill over the next section. If you need a minimum, use min-height.
/* Fragile */
.card {
height: 200px;
}
/* Robust */
.card {
min-height: 200px;
}
Min and max sizes
Four properties set limits instead of exact sizes:
| Property | Meaning |
|---|---|
min-width | Never narrower than this |
max-width | Never wider than this |
min-height | Never shorter than this |
max-height | Never taller than this |
Combine a flexible width with a limit and the element adapts to the space it gets:
.page {
width: 100%;
max-width: 70rem;
margin-inline: auto;
padding-inline: 1rem;
}
On a phone the page fills the screen. On a large monitor it stops at 70rem and centres. No media query needed.
When limits conflict, min-width beats max-width, and both beat width.
Readable text columns
.article {
max-width: 65ch;
}
Long lines are tiring to read. Capping the width in ch keeps lines a comfortable length whatever the font size.
Images that never overflow
img {
max-width: 100%;
height: auto;
}
An image larger than its container is scaled down to fit; a smaller one keeps its natural size. height: auto keeps the proportions correct. This rule belongs in every base stylesheet. Serving the right image file for each screen size is covered in the Responsive Web Design course.
Buttons with a minimum target size
.button {
min-height: 2.75rem;
min-width: 2.75rem;
padding: 0.5rem 1rem;
}
The button grows with its label, but never shrinks below a comfortable size for fingers and pointers.
Sizing keywords
width also accepts keywords that size the box from its content:
.tag {
width: fit-content; /* as wide as the content, but no wider than available */
}
min-contentis the narrowest the content can go, usually the longest word.max-contentis the width the content wants with no wrapping.fit-contentismax-content, but capped at the available space.
These become especially useful in Grid, which you will see in the subgrid and intrinsic layout lesson.
aspect-ratio
aspect-ratio keeps a box in proportion as its width changes:
.video-frame {
width: 100%;
aspect-ratio: 16 / 9;
}
.avatar {
width: 4rem;
aspect-ratio: 1; /* square */
border-radius: 50%;
}
Set one dimension and the browser works out the other. If the content is taller than the ratio allows, the box grows by default rather than cutting it off.
A starter base stylesheet
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
img,
svg,
video {
display: block;
max-width: 100%;
height: auto;
}
button,
input,
select,
textarea {
font: inherit;
}
You will build on this throughout the course.
Debugging size problems
- Element wider than expected: inspect it and check the box diagram in the Computed tab. If the padding is outside the width,
box-sizingis stillcontent-box. - Horizontal scrollbar on the page: the cause is usually one element wider than the viewport, often with a fixed
widthin px orwidth: 100vw. Temporarily add* { outline: 1px solid red; }to see every box's edges. - Text spilling out of a box: look for a fixed
heightand change it tomin-height.
Summary
content-box(the default) adds padding and border towidth;border-boxincludes them.- Apply
box-sizing: border-boxto every element with the universal reset. - Let height follow content; use
min-heightinstead ofheightfor text containers. - Combine flexible widths with
max-width, and give imagesmax-width: 100%. fit-content,min-content,max-contentandaspect-ratiosize boxes from content or proportion.