~/
CSS Box Model
Quiz
...

CSS Box Model

beginner · updated Tue Sep 08 2026Contribute

Master the CSS box model, including margin, padding, border, and content, to create precise and professional web layouts.

CSS Box Model

Every element on a page is a box. The box model is the set of rules that decides how big that box is and how it sits next to its neighbours. Once you can picture the four layers below, “why is this element wider than I asked for?” stops being a mystery.

The Four Parts

Each layer wraps the one inside it, from the middle outwards:

  • Content — the text, images, or child elements themselves.
  • Padding — breathing room inside the box, between the content and the border.
  • Border — the visible (or invisible) line drawn around the padding.
  • Margin — empty space outside the border that pushes neighbouring elements away.

Use the controls to step through the diagram and see each layer in turn.

Box Sizing

width and height do not automatically mean “the final size of the box”. The box-sizing property decides what they actually measure:

  • content-box (the default) — width sizes only the content. Padding and border are added on top, so the element ends up larger than the number you wrote.
  • border-box — width sizes the content plus padding plus border, so the element stays exactly the size you asked for.

The example renders one box of each kind. Both are given width: 200px, padding: 20px and a 5px border — run it, then edit any value and run again to compare.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <style>
    body {
      font-family: system-ui, sans-serif;
      padding: 20px;
    }

    .row {
      display: flex;
      gap: 30px;
      align-items: flex-start;
    }

    .box {
      width: 200px;
      padding: 20px;
      border: 5px solid #3498db;
      background: #eaf4fd;
    }

    /* The default: width covers the content only. */
    .content {
      box-sizing: content-box;
    }

    /* The fix: width covers content + padding + border. */
    .border {
      box-sizing: border-box;
    }
  </style>
</head>
<body>
  <div class="row">
    <div class="box content">
      <strong>content-box</strong>
      <p>200px of content + padding + border</p>
    </div>
    <div class="box border">
      <strong>border-box</strong>
      <p>200px in total, padding and border included</p>
    </div>
  </div>
</body>
</html>

Notice the left box ends up 250px wide (200 + 20 + 20 + 5 + 5) while the right one stays at 200px. That extra 50px is exactly why almost every real codebase sets box-sizing: border-box.

Universal Reset

Because content-box surprises people, most projects start with a one-line reset. This is boilerplate rather than something worth previewing, so it is not runnable:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
  • margin: 0 removes the browser’s default spacing around headings, paragraphs and the page body.
  • padding: 0 removes default padding (for example on lists).
  • box-sizing: border-box makes every element’s width mean what you expect.

Margin

Margin is the space outside the border. The shorthand takes one to four values, and the number of values changes what each one controls:

/* All sides */
margin: 10px;

/* Top, right, bottom, left */
margin: 10px 20px 10px 20px;

/* Top, horizontal, bottom */
margin: 10px 20px 10px;

/* Vertical, horizontal */
margin: 10px 20px;

/* Center horizontally */
margin: 0 auto;

/* Negative margin (pull element) */
margin-top: -20px;

Two patterns are worth calling out: margin: 0 auto gives equal left and right margins, which centers a block that has a fixed width, and a negative margin pulls the element in the opposite direction.

Padding

Padding is the space inside the border, between it and the content. It uses the same one-to-four-value shorthand as margin, but it never accepts auto and it never collapses:

/* All sides */
padding: 10px;

/* Top, right, bottom, left */
padding: 10px 20px 10px 20px;

/* Top, horizontal, bottom */
padding: 10px 20px 10px;

/* Vertical, horizontal */
padding: 10px 20px;

Remember that padding counts towards the element’s size under content-box. Under border-box it eats into the content instead, shrinking the space left for text.

Border

The border shorthand sets width, style and color in a single line. You can also target one side at a time, and round the corners with border-radius:

/* Basic border */
border: 1px solid black;

/* Individual sides */
border-top: 2px dashed red;
border-right: 3px double blue;
border-bottom: 1px solid green;
border-left: 5px groove gray;

/* Border radius (rounded corners) */
border-radius: 10px;

/* Different radius for each corner */
border-radius: 10px 20px 30px 40px;

/* Circle (50%) */
border-radius: 50%;

A border needs a style to be visible. border: 1px black shows nothing because border-style defaults to none — always include solid, dashed, dotted and friends.

Complete Example

Here is the whole model working together in a small card. The markup and the CSS live in one HTML file — the CSS sits in a <style> block at the top, and the card markup follows in the body. Run it, then change the padding or the border-radius and run again.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <style>
    body {
      font-family: system-ui, sans-serif;
      background: #f4f6f8;
      padding: 20px;
    }

    .card {
      width: 300px;
      padding: 20px;
      border: 1px solid #ddd;
      border-radius: 10px;
      margin: 20px auto;
      background-color: white;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }

    .card-title {
      font-size: 1.5rem;
      margin-bottom: 10px;
    }

    .card-content {
      padding: 15px;
      border-left: 3px solid #3498db;
      margin-bottom: 20px;
    }

    .card-button {
      padding: 10px 20px;
      background-color: #3498db;
      color: white;
      border: none;
      border-radius: 5px;
      margin: 0;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div class="card">
    <h2 class="card-title">Card Title</h2>
    <p class="card-content">Card content goes here.</p>
    <button class="card-button">Click Me</button>
  </div>
</body>
</html>

The .card uses margin: 20px auto to center itself, padding for inner space, border plus border-radius for its outline, and box-shadow to lift it off the page. The .card-content paragraph uses a thick left border as an accent — border and padding working side by side.

Collapsing Margins

When two vertical margins meet, they do not add up — they collapse to the larger of the two. This only happens to margins (never padding) and only between block boxes stacked vertically.

The example renders two identical heading/paragraph pairs. In the first, the h1’s 20px bottom margin and the p’s 30px top margin collapse into a single 30px gap. The second pair sits in a flex container, where margins never collapse, so the gap is the full 50px:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <style>
    body {
      font-family: system-ui, sans-serif;
      padding: 20px;
    }

    section {
      background: #f4f6f8;
      padding: 10px 20px;
      margin-bottom: 20px;
    }

    /* display:flex stops the children's margins from collapsing. */
    section.flex {
      display: flex;
      flex-direction: column;
    }

    h2 {
      font-size: 0.75rem;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      color: #666;
      margin-bottom: 10px;
    }

    h1 {
      margin-bottom: 20px;
    }

    p {
      margin-top: 30px;
    }
  </style>
</head>
<body>
  <section>
    <h2>Margins collapse</h2>
    <h1>Heading</h1>
    <p>Paragraph — the gap is 30px, not 50px.</p>
  </section>

  <section class="flex">
    <h2>Collapse prevented</h2>
    <h1>Heading</h1>
    <p>Paragraph — now the gap is the full 50px.</p>
  </section>
</body>
</html>

To prevent collapsing:

  • Make the parent a flex or grid container.
  • Add padding or a border to the parent (this stops parent/child collapsing).
  • Use padding instead of margin where collapse would cause a problem.

Best Practices

  1. Use border-box — Makes layout predictable
  2. Use margin: 0 auto — Centers elements
  3. Use padding for internal spacing — Not margin
  4. Reset margins on body — Prevents unexpected gaps
  5. Use shorthand — margin: 10px 20px is cleaner

Common Mistakes

  1. Forgetting box-sizing — Width calculations break
  2. Collapsing margins — Unexpected gaps
  3. Using margin on inline elements — Only works on block elements
  4. Not resetting margins — Browser defaults cause issues
  5. Overusing negative margin — Can break layouts