Skip to content
beginner css 10 min read

CSS Box Model Explained: Margin, Padding, and Border

Understand the CSS box model and how margin, padding, border, and content work together.

css box model css margin padding css border box box sizing css

What Is the CSS Box Model?

Every element you render in a browser is a rectangular box. The CSS box model defines how that box is structured and how its dimensions are calculated. Until you truly understand this model, you'll constantly fight layouts that don't behave the way you expect — elements overflowing their containers, spacing that looks wrong, or widths that refuse to add up correctly.

The box model consists of four layers, from the inside out:

  1. Content — where your text, images, or child elements live
  2. Padding — transparent space between the content and the border
  3. Border — a visible (or invisible) frame around the padding
  4. Margin — transparent space outside the border, separating this element from others

Here's a quick visual reference:

+---------------------------+
|         MARGIN            |
|  +---------------------+  |
|  |       BORDER        |  |
|  |  +--------------+   |  |
|  |  |   PADDING    |   |  |
|  |  |  +--------+  |   |  |
|  |  |  | CONTENT|  |   |  |
|  |  |  +--------+  |   |  |
|  |  +--------------+   |  |
|  +---------------------+  |
+---------------------------+

The Default Sizing Problem: content-box

By default, browsers use box-sizing: content-box. This means when you set width: 300px, you're only setting the content area width. Any padding and border you add gets stacked on top of that, making the element wider than you declared.

.box {
  width: 300px;
  padding: 20px;
  border: 5px solid #333;
  /* box-sizing: content-box (default) */
}

The actual rendered width of .box here is:

300px (content)
+ 20px (padding-left) + 20px (padding-right)
+ 5px (border-left) + 5px (border-right)
= 350px total

You asked for 300px, you got 350px. This surprises almost every developer at least once.

The Fix: box-sizing: border-box

Switching to box-sizing: border-box changes the calculation so that width and height include padding and border. The content area shrinks to accommodate them, but the outer dimensions match exactly what you specified.

.box {
  width: 300px;
  padding: 20px;
  border: 5px solid #333;
  box-sizing: border-box;
  /* Total rendered width: exactly 300px */
  /* Content area: 300 - 40 - 10 = 250px */
}

The best practice is to apply this globally from the start of every project:

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

This single reset prevents most box model headaches before they start. It works reliably in every browser in use today, and it makes Flexbox and Grid layouts far more predictable.

Understanding Margin, Padding, and Border in Detail

Padding

Padding is the space between your content and its border. It's transparent but inherits the element's background color, which is why increasing padding makes a colored box appear bigger — the background fills the padded area.

.card {
  padding: 24px;              /* all four sides */
  padding: 16px 24px;         /* top/bottom | left/right */
  padding: 8px 16px 24px 32px; /* top | right | bottom | left */
  
  /* Logical properties (preferred for i18n) */
  padding-block: 16px;   /* top and bottom */
  padding-inline: 24px;  /* left and right */
}

Avoid using padding to create spacing between separate elements — that's what margin is for.

Border

A border requires three values to be visible: width, style, and color. The style is the one developers most often forget, which results in an invisible border.

.box {
  border: 2px solid #e2e8f0;        /* shorthand */
  border-top: 4px solid #3b82f6;    /* single side */
  border-radius: 8px;               /* rounds corners */
  
  /* Individual properties */
  border-width: 2px;
  border-style: solid; /* dashed, dotted, double, none */
  border-color: #e2e8f0;
}

Need to experiment with rounded corners visually? Use the border-radius generator to dial in the exact values without trial and error.

Margin

Margin controls the space outside the border. Unlike padding, margin doesn't inherit background — it's always transparent. Use margin: auto on block elements to center them horizontally inside their container.

.container {
  width: 800px;
  margin: 0 auto; /* centers the element horizontally */
}

.section {
  margin-top: 48px;
  margin-bottom: 32px;
  
  /* Logical property equivalent */
  margin-block: 32px 48px;
}

Margin Collapse

One of the most misunderstood behaviors in CSS is margin collapse. When two block elements stack vertically, their adjacent margins don't add up — the larger margin wins and the smaller one disappears.

.heading {
  margin-bottom: 32px;
}

.paragraph {
  margin-top: 16px;
}

/* The space between them is 32px, not 48px */

Margin collapse only happens vertically (between top and bottom margins). It doesn't occur horizontally, on floated elements, or inside flex/grid containers. When you're inside a flex or grid layout, you can forget about collapse entirely and use gap for spacing instead.

A Complete Practical Example

Here's a real-world card component that demonstrates all four box model layers working together:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <style>
    *,
    *::before,
    *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      font-family: system-ui, sans-serif;
      background: #f1f5f9;
      padding: 40px;
    }

    .card {
      width: 100%;
      max-width: 360px;
      background: #ffffff;
      border: 1px solid #e2e8f0;
      border-radius: 12px;
      overflow: hidden;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    }

    .card__image {
      width: 100%;
      height: 200px;
      object-fit: cover;
      display: block; /* removes inline gap below image */
    }

    .card__body {
      padding: 24px; /* padding adds space inside, within 360px */
    }

    .card__title {
      font-size: 1.25rem;
      font-weight: 700;
      color: #1e293b;
      margin-bottom: 8px;
    }

    .card__text {
      font-size: 0.9375rem;
      color: #64748b;
      line-height: 1.6;
      margin-bottom: 20px;
    }

    .card__btn {
      display: block;
      width: 100%;
      padding: 12px 24px;
      background: #3b82f6;
      color: #fff;
      font-size: 1rem;
      font-weight: 600;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      text-align: center;
    }

    .card__btn:hover {
      background: #2563eb;
    }
  </style>
</head>
<body>
  <div class="card">
    <img 
      class="card__image" 
      src="https://picsum.photos/360/200" 
      alt="Card cover"
    >
    <div class="card__body">
      <h2 class="card__title">Card Component</h2>
      <p class="card__text">
        The total card width stays at 360px regardless of padding and 
        border, because we're using border-box sizing globally.
      </p>
      <button class="card__btn">Get Started</button>
    </div>
  </div>
</body>
</html>

The card width is always exactly 360px. The 24px padding inside .card__body doesn't inflate it — the content area shrinks instead. That's border-box doing exactly what you want. You can add depth and polish using box-shadow without affecting the layout at all. For more shadow options, check out the box-shadow generator.

Common Mistakes to Avoid

Mixing box-sizing values — If your global reset uses border-box but a third-party component overrides it back to content-box, you'll get inconsistent sizing. Keep an eye on specificity in your CSS.

Assuming margin always pushes elements apart — Adjacent vertical margins collapse. If you're debugging a gap that's smaller than expected, check if collapse is the cause.

Using padding to space sibling elements — Padding is internal spacing. For gaps between separate elements, use margin or, better yet, gap inside a flex or grid container.

Forgetting display: block on images — Inline images have a small gap beneath them caused by baseline alignment. Add display: block to remove it.

Applying padding to inline elements and expecting vertical spacing — Inline elements accept horizontal padding reliably, but vertical padding doesn't push surrounding lines apart. Convert to inline-block or block if you need vertical spacing.

Debugging the Box Model

When spacing looks off, open browser DevTools and inspect the element. The Computed panel shows a visual diagram of the exact margin, border, padding, and content measurements for any selected element. This is the fastest way to catch unexpected extra space or overflow.

If you're writing complex CSS and want to validate or clean up your rules quickly, run your stylesheet through the CSS formatter to catch syntax issues and improve readability.

Next Steps

Now that you understand the CSS box model, margin collapse, and the critical difference between content-box and border-box, you're ready to build more predictable layouts. Here's where to go next:

  • Flexbox Guide — Learn how display: flex changes spacing behavior and why gap beats margin for flex children
  • CSS Grid Layout — Apply box model knowledge to two-dimensional layouts with precise control over rows and columns
  • CSS Specificity and the Cascade — Understand why your box model rules sometimes don't apply as expected
  • Border Radius Generator — Create and preview rounded corners without writing CSS by hand
  • Box Shadow Generator — Build layered shadow effects that add depth without impacting layout
  • CSS Formatter — Clean up and validate your stylesheets as your codebase grows

Mastering the box model is one of those fundamentals that pays off immediately and keeps paying off every time you touch a layout.

Related Tools

Continue Learning