Have you ever set the width of a box on a webpage and then been confused because it turned out much bigger than you expected? You set it to 300px, but it came out looking like 360px? You are not alone ยท this is one of the most common surprises beginners face in CSS. The reason is how CSS calculates the actual size of an element by default.
In this lesson, you will learn:
- What the CSS Box Model is (a quick recap to set the foundation)
- Why elements often appear bigger than you set them
- What the
box-sizingproperty is and how it solves this problem - How to use
box-sizing: border-boxto write predictable, clean layouts - A professional trick used by almost every real-world website today
- Hands-on exercises and a mini-project to practise everything
No prior knowledge of box-sizing is needed. If you know basic HTML and CSS (how to write selectors and properties), you are ready to begin.
Before we dive in, let us make sure you understand two foundational ideas: the Box Model and what padding and border mean in CSS.
What Is the CSS Box Model?
Every single HTML element ยท a heading, a paragraph, a <div>, a button ยท is treated by the browser as a rectangular box. This box has four layers, like the layers of a picture frame:
+-----------------------------+
| MARGIN | โ Space OUTSIDE the element
| +-----------------------+ |
| | BORDER | | โ The visible outline/frame
| | +-----------------+ | |
| | | PADDING | | | โ Space INSIDE, between border and content
| | | +-----------+ | | |
| | | | CONTENT | | | | โ Your actual text, image, etc.
| | | +-----------+ | | |
| | +-----------------+ | |
| +-----------------------+ |
+-----------------------------+- Content ยท The actual text, image, or child elements inside
- Padding ยท The breathing room between the content and the border
- Border ยท A visible (or invisible) frame around the element
- Margin ยท Space outside the border that separates this element from its neighbours
What Are Width and Height in CSS?
When you write width: 300px; in CSS, you are telling the browser: "Make the content area of this element 300 pixels wide."
Notice the key phrase: content area. By default, CSS does NOT include padding and border in that 300px. It only applies to the inner content area.
This means the element's actual visible size on screen is:
Actual width = width + left padding + right padding + left border + right border
Actual height = height + top padding + bottom padding + top border + bottom borderThis is the root cause of elements appearing bigger than expected.
The Problem: Default Box Sizing
Let us build an intuition with a real-world analogy before we look at code.
Analogy: Ordering a Pizza Box
Imagine you order a pizza and ask for a 30 cm box. The restaurant gives you a box where the pizza itself is 30 cm ยท but then they add a 5 cm thick foam lining on each side (padding) and a 1 cm cardboard frame (border). The final box you receive is actually:
30 cm (pizza) + 5 cm (foam left) + 5 cm (foam right) + 1 cm (frame left) + 1 cm (frame right)
= 42 cm totalYou asked for 30 cm but got 42 cm! That is exactly what CSS does by default.
In CSS terms, the default behaviour is called box-sizing: content-box. The width you set only applies to the content ยท not the padding or border.
Example 1 ยท Seeing the Problem
Here are two <div> elements. Both have width: 300px and height: 100px. The first has no padding. The second has padding: 50px. Watch what happens to the actual size:
<!DOCTYPE html>
<html>
<head>
<style>
/* Both divs are declared at the SAME size */
.div1 {
width: 300px;
height: 100px;
border: 1px solid blue;
background-color: lightblue;
}
.div2 {
width: 300px;
height: 100px;
padding: 50px; /* 50px on all 4 sides */
border: 1px solid red;
background-color: lightsalmon;
}
</style>
</head>
<body>
<div class="div1">I am div1. Width declared: 300px</div>
<div class="div2">I am div2. Width declared: 300px but padding: 50px</div>
</body>
</html>Expected output (what you see on screen):
div1 โ Actual width = 300px + 1px + 1px (borders) = 302px wide
div2 โ Actual width = 300px + 50px + 50px (padding) + 1px + 1px (borders) = 402px wideEven though BOTH divs say width: 300px, div2 is 100 pixels wider on screen because its padding is added on top of the declared width.
๐ก Think about it: What would happen if you had four of these
div2boxes side by side in a row, expecting them all to fit in a 1200px container? They would overflow and break your layout!
The Solution: box-sizing: border-box
The CSS property box-sizing was introduced to fix exactly this problem. It controls how the browser calculates the total width and height of an element.
There are two possible values:
| Value | What It Means |
|---|---|
content-box | Default. Width/height apply to the CONTENT only. Padding and border are added on top. |
border-box | Width/height include padding and border. The content shrinks to fit inside. |
The key insight about border-box:
When you set box-sizing: border-box;, the browser keeps the element at exactly the width/height you declare. If there is padding or a border, the browser shrinks the content area to make room for them ยท so the total stays exactly the declared size.
Using the pizza analogy again: with border-box, you get a box that is exactly 30 cm total. The pizza inside gets smaller to make room for the foam and cardboard, but the box itself is exactly 30 cm as requested.
Example 2 ยท Applying border-box to Both Divs
<!DOCTYPE html>
<html>
<head>
<style>
.div1 {
width: 300px;
height: 100px;
border: 1px solid blue;
background-color: lightblue;
box-sizing: border-box; /* โ Added this line */
}
.div2 {
width: 300px;
height: 100px;
padding: 50px;
border: 1px solid red;
background-color: lightsalmon;
box-sizing: border-box; /* โ Added this line */
}
</style>
</head>
<body>
<div class="div1">Div1: width 300px, border-box</div>
<div class="div2">Div2: width 300px, padding 50px, border-box</div>
</body>
</html>Expected output:
div1 โ Actual width on screen = exactly 300px
div2 โ Actual width on screen = exactly 300px โ
Both divs are now the same width on screen. The padding in div2 is now contained inside the 300px. The content area becomes 300 - 50 - 50 - 1 - 1 = 198px, but that is handled automatically by the browser. You just work with 300px and it stays 300px.
๐ก Think about it: Why is this so powerful for layout? If you are building a two-column layout and want each column to be exactly 50% wide,
border-boxensures that even if you add padding to each column, they still fit perfectly side by side.
The Universal border-box Reset
Since box-sizing: border-box is almost always more intuitive and useful, professional developers apply it to every element on the page using the universal CSS selector *:
* {
box-sizing: border-box;
}Line-by-line explanation:
*ยท This is the universal selector. It targets every single HTML element on the page ยท every div, paragraph, heading, input, button, image ยท everything.{ยท Opens the rule blockbox-sizing: border-box;ยท Sets the box-sizing model toborder-boxfor all elements}ยท Closes the rule block
Why use this?
When you apply border-box universally, you can confidently set widths and heights knowing they will never surprise you with extra pixels from padding or borders. Many browsers already use border-box for some form elements (like <input> and <textarea>), so applying it universally also ensures consistency across all elements.
โ Real World Fact: Almost every professional CSS framework, including Bootstrap and Tailwind CSS, applies
box-sizing: border-boxglobally as a reset. When you see* { box-sizing: border-box; }at the top of a CSS file, you know the developer cares about clean, predictable layouts.
Example 3 ยท Universal Reset in Action
<!DOCTYPE html>
<html>
<head>
<style>
/* Apply border-box to EVERYTHING on the page */
* {
box-sizing: border-box;
}
/* Now ALL elements follow border-box rules automatically */
.container {
width: 600px;
padding: 20px;
border: 2px solid black;
background-color: #f0f0f0;
}
.column {
width: 50%; /* Exactly half of 600px = 300px */
padding: 15px;
border: 1px solid grey;
background-color: white;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<div class="column">Column 1 โ exactly 50% wide</div><div class="column">Column 2 โ exactly 50% wide</div>
</div>
</body>
</html>Expected output:
Container: 600px wide with 20px inner padding
Column 1: 300px wide (50%) with 15px padding and 1px border โ all contained within 300px
Column 2: 300px wide (50%) with 15px padding and 1px border โ all contained within 300px
Both columns sit perfectly side by side inside the 600px container โ
Without border-box, the columns would overflow the container because their padding (15px ร 2 = 30px) would be added to their 50% width.
Example A ยท Same Width, Different Padding (No border-box)
/* WITHOUT border-box โ default content-box behaviour */
.box-a {
width: 200px;
padding: 0px;
border: 2px solid navy;
}
.box-b {
width: 200px;
padding: 20px;
border: 2px solid navy;
}Calculating actual sizes:
box-a actual width = 200 + 0 + 0 + 2 + 2 = 204px
box-b actual width = 200 + 20 + 20 + 2 + 2 = 244pxThey look different on screen even though both declare width: 200px.
Example B ยท Same Width, Different Padding (WITH border-box)
/* WITH border-box */
.box-a {
width: 200px;
padding: 0px;
border: 2px solid navy;
box-sizing: border-box;
}
.box-b {
width: 200px;
padding: 20px;
border: 2px solid navy;
box-sizing: border-box;
}Calculating actual sizes:
box-a actual width = exactly 200px โ
box-b actual width = exactly 200px โ
(content shrinks to 200 - 20 - 20 - 2 - 2 = 156px internally)Both boxes look the same width on screen.
Example C ยท Understanding the Content Shrinkage
This example helps you see how the content area shrinks when border-box is used:
* {
box-sizing: border-box;
}
.card {
width: 400px;
padding: 40px;
border: 5px solid darkgreen;
background-color: lightgreen;
}What the browser calculates internally:
Total declared width: 400px
Left border: -5px
Right border: -5px
Left padding: -40px
Right padding: -40px
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Content area width: 310px โ Browser auto-adjusts thisThe element still appears exactly 400px wide on screen. The browser just arranges the internal layers to fit within that budget.
| Property | Values | What It Does |
|---|---|---|
box-sizing | content-box | Default. width/height = content only. Padding + border are extra. |
box-sizing | border-box | width/height = content + padding + border. Element stays exactly declared size. |
box-sizing Property Reference. Open your editor, type the examples above by hand, modify them, and observe what changes.Exercise 1 ยท Spot the Size Difference
Objective: Observe how padding changes the actual size of an element without border-box.
Scenario: You are building a product card for an online shop. Each card should be 250px wide. You add padding for spacing.
Steps:
- Create an HTML file with the code below
- Open it in a browser
- Observe that both cards declare
width: 250pxbut look different sizes
<!DOCTYPE html>
<html>
<head>
<style>
.card {
width: 250px;
border: 2px solid #333;
background-color: #fafafa;
margin: 10px;
display: inline-block;
vertical-align: top;
}
.card-no-padding {
/* No padding โ card stays close to 250px */
}
.card-with-padding {
padding: 20px; /* Adds 40px total to width! */
}
</style>
</head>
<body>
<div class="card card-no-padding">
<p>Card A โ No padding. Width: 250px declared.</p>
</div>
<div class="card card-with-padding">
<p>Card B โ Padding: 20px. Width: 250px declared.</p>
</div>
</body>
</html>Expected output: Card B is visibly wider than Card A on screen.
Self-check questions:
- How many extra pixels wide is Card B compared to Card A?
- If you put four of these cards side by side expecting 1000px total, what would actually happen?
Hints:
- Card B actual width = 250 + 20 + 20 + 2 + 2 = 294px
- Four Card B elements = 4 ร 294 = 1176px ยท that is 176px too wide for a 1000px container!
Exercise 2 ยท Applying the Fix
Objective: Add box-sizing: border-box to fix the layout from Exercise 1.
Steps:
- Take the code from Exercise 1
- Add
* { box-sizing: border-box; }at the top of your CSS - Observe that both cards are now the same width
<!DOCTYPE html>
<html>
<head>
<style>
/* THE FIX */
* {
box-sizing: border-box;
}
.card {
width: 250px;
border: 2px solid #333;
background-color: #fafafa;
margin: 10px;
display: inline-block;
vertical-align: top;
}
.card-no-padding {
/* No padding */
}
.card-with-padding {
padding: 20px;
}
</style>
</head>
<body>
<div class="card card-no-padding">
<p>Card A โ No padding.</p>
</div>
<div class="card card-with-padding">
<p>Card B โ Padding: 20px.</p>
</div>
</body>
</html>Expected output: Both cards appear exactly 250px wide. โ
What-if challenge: What happens if you change padding: 20px to padding: 100px? Try it and see ยท does the element stay 250px wide? What happens to the text inside?
Exercise 3 ยท Two-Column Layout
Objective: Build a clean two-column layout using percentages and border-box.
Scenario: You are building a blog page with a main content area (70% wide) and a sidebar (30% wide). They must sit side by side.
<!DOCTYPE html>
<html>
<head>
<style>
* {
box-sizing: border-box;
}
.layout {
width: 900px;
background-color: #eee;
overflow: hidden; /* Clear floats */
}
.main-content {
width: 70%;
padding: 20px;
border: 1px solid #999;
background-color: white;
float: left;
}
.sidebar {
width: 30%;
padding: 20px;
border: 1px solid #999;
background-color: #f9f9f9;
float: left;
}
</style>
</head>
<body>
<div class="layout">
<div class="main-content">
<h2>Main Article</h2>
<p>This is the main content area. It takes up 70% of the layout.</p>
</div>
<div class="sidebar">
<h2>Sidebar</h2>
<p>This is the sidebar. It takes up 30%.</p>
</div>
</div>
</body>
</html>Expected output: Both columns sit perfectly side by side inside the 900px layout. Total = 70% + 30% = 100% โ
Self-check questions:
- What would happen without
box-sizing: border-box? - Remove the
* { box-sizing: border-box; }line and reload. What do you observe?
Mistake 1 ยท Forgetting box-sizing and wondering why things overflow
Wrong approach (default content-box):
.sidebar {
width: 30%;
padding: 20px;
border: 2px solid grey;
float: left;
}
.main {
width: 70%;
padding: 20px;
border: 2px solid grey;
float: left;
}Problem: 30% + 70% = 100%, which seems right. But padding and border add extra pixels, making the total width MORE than 100%. The second column drops below the first.
Correct approach:
* {
box-sizing: border-box; /* Add this first! */
}
.sidebar {
width: 30%;
padding: 20px;
border: 2px solid grey;
float: left;
}
.main {
width: 70%;
padding: 20px;
border: 2px solid grey;
float: left;
}Now 30% + 70% truly = 100% because padding and border are contained within each percentage. โ
Mistake 2 ยท Applying border-box to only one element in a pair
/* Mistake: Only one element gets border-box */
.div1 {
width: 300px;
/* Uses default content-box */
}
.div2 {
width: 300px;
padding: 20px;
box-sizing: border-box; /* Only div2 has border-box */
}Problem: The two elements calculate their sizes differently, leading to inconsistent layouts that are hard to debug.
Fix: Always apply border-box universally:
* {
box-sizing: border-box;
}Mistake 3 ยท Confusing margin with padding in the context of box-sizing
Important: box-sizing: border-box only includes padding and border within the declared width. It does NOT include margin.
* {
box-sizing: border-box;
}
.box {
width: 200px;
padding: 20px; /* Included in 200px โ
*/
border: 2px solid; /* Included in 200px โ
*/
margin: 30px; /* NOT included โ adds space OUTSIDE the 200px โ ๏ธ */
}The element on screen:
- The box itself = exactly 200px wide โ
- There is 30px of invisible space around the outside of the box (margin)
- The total space the element occupies in the flow = 200px + 30px + 30px = 260px
Margin is always external. border-box does not change this behaviour.
Mistake 4 ยท Setting padding larger than width
* {
box-sizing: border-box;
}
.tiny-box {
width: 50px;
padding: 40px; /* 40 + 40 = 80px padding โ more than the width! */
}Problem: The padding alone exceeds the declared width. The browser cannot make the content area negative. It will set the content area to 0 (or a very small value) and the box may not behave as expected.
Fix: Keep padding smaller than the total width it is being applied to. A good rule of thumb: padding should not exceed 40% of the element's width.
Let us build a realistic mini-project: a 3-card product grid for an online shop. Each card will have an image placeholder, a product name, a price, and a button ยท and all three cards must be exactly the same width with consistent padding.
Stage 1 ยท Setup
Create an HTML file. Set up the page structure with a heading and a container:
<!DOCTYPE html>
<html>
<head>
<title>Product Grid</title>
<style>
/* STAGE 1: Global reset */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
padding: 30px;
}
h1 {
text-align: center;
margin-bottom: 30px;
color: #333;
}
</style>
</head>
<body>
<h1>Our Products</h1>
<!-- Cards will go here -->
</body>
</html>Lesson 67 complete! ๐
You covered:
- โ Lesson Introduction
- โ Prerequisite Concepts
- โ Conceptual Understanding
- โ Simple Standalone Examples
- โ The `box-sizing` Property Reference
- โ Guided Practice Exercises
- โ Common Beginner Mistakes