CSS Margin

โ–ถ Try It Yourself

Margin is the outermost layer of the CSS box model โ€” transparent space that separates an element from its neighbours. While padding pushes content away from a border, margin pushes the entire element away from surrounding elements. In this lesson you will master margin shorthand, the auto-centering trick, margin collapse behaviour, and negative margins.

Margin Properties

Syntax Values Applied Example
margin: A All four sides equal margin: 16px
margin: A B Top+Bottom / Left+Right margin: 16px 32px
margin: A B C D Top / Right / Bottom / Left (clockwise) margin: 8px 16px 24px 32px
margin: 0 auto 0 vertical, auto horizontal Centers block elements horizontally
margin-inline: auto Horizontal auto (logical property) Modern writing-mode-aware centering

Margin Collapse Rules

Scenario Expected Actual (collapsed)
Siblings: 20px bottom + 30px top 50px gap 30px โ€” the larger value wins
Parent has no border/padding; child has 24px margin-top Child 24px inside parent Parent gets pushed down 24px โ€” margin escapes
Empty element with top and bottom margin only Both applied Collapsed to the larger of the two

Negative Margins

Usage Effect Common Use Case
margin-top: -20px Pulls element 20px upward Overlapping cards, pull-quotes
margin-left: -20px Pulls element 20px leftward Full-bleed images inside padded containers
margin: -1px Collapses borders between items Bordered list items with no double border
Note: Margin collapse only happens in the block direction (vertically in horizontal writing modes). Margins on flex and grid children never collapse. Adding overflow: hidden, padding, or border to a parent prevents parent-child margin collapse.
Tip: To create consistent vertical spacing without margin collapse surprises, use a single direction โ€” apply only margin-bottom to elements. Spacing always flows downward, so only one margin participates at each gap.
Warning: Negative margins are valid CSS but can cause overlaps and unpredictable behaviour. If you need to overlap elements intentionally, prefer position: absolute with offsets โ€” it is far easier to reason about and debug.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Margin</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #f1f5f9; }

    /* Container centred with auto margin */
    .container {
      max-width: 600px;
      margin: 0 auto;       /* 0 top/bottom, equal left/right */
      padding: 32px;
      background: white;
    }

    /* Single-direction margins โ€” no collapse surprises */
    .card {
      background: #ede9fe;
      border: 1px solid #c4b5fd;
      border-radius: 8px;
      padding: 16px 20px;
      margin-bottom: 16px;  /* only bottom โ€” gap is always exactly 16px */
    }

    /* Margin collapse demo */
    .collapse-a {
      margin-bottom: 40px;
      background: #fef3c7;
      padding: 12px 16px;
      border-radius: 6px;
    }
    .collapse-b {
      margin-top: 20px;   /* collapses with 40px above โ€” gap = 40px, not 60px */
      background: #d1fae5;
      padding: 12px 16px;
      border-radius: 6px;
    }

    /* Negative margin pulls element upward */
    .pulled-up {
      background: #fce7f3;
      padding: 16px;
      border-radius: 8px;
      margin-top: -24px;    /* overlaps preceding sibling */
      margin-left: 48px;    /* offset so content remains visible */
      position: relative;
      border: 1px solid #f9a8d4;
    }

    /* margin-inline: auto โ€” modern centering */
    .centered-modern {
      width: 280px;
      margin-inline: auto;
      background: #e0f2fe;
      padding: 12px 16px;
      border-radius: 8px;
      margin-top: 16px;
      font-size: 0.875rem;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="card">Card A โ€” margin-bottom: 16px</div>
    <div class="card">Card B โ€” gap above is exactly 16px (no collapse)</div>

    <p class="collapse-a">Sibling A โ€” margin-bottom: 40px</p>
    <p class="collapse-b">Sibling B โ€” margin-top: 20px โ€” gap is 40px (collapsed to larger)</p>

    <div class="pulled-up">Negative margin-top: -24px โ€” overlaps sibling above</div>

    <div class="centered-modern">margin-inline: auto (modern centering)</div>
  </div>
</body>
</html>

How It Works

Step 1 โ€” margin: 0 auto Centers Block Elements

margin: 0 auto gives zero vertical margin and distributes all remaining horizontal space equally left and right. This only works on block-level elements with an explicit width or max-width โ€” without a constrained width, the element already fills the container and there is no space to distribute.

Step 2 โ€” Single-Direction Margins Avoid Collapse

Using only margin-bottom on stacked cards means only one margin participates at each gap. The collapse algorithm finds nothing to merge โ€” the gap is always exactly 16px.

Step 3 โ€” Margin Collapse Selects the Larger Value

Between .collapse-a (40px bottom) and .collapse-b (20px top), CSS collapses them into a single 40px gap. The 20px is not lost โ€” both margins share the same space, and the larger one determines the size.

Step 4 โ€” Negative Margin Shifts Toward the Margin Edge

margin-top: -24px pulls .pulled-up upward by 24px, overlapping the preceding sibling. Following content adjusts as if the element occupies its original position minus 24px โ€” siblings above and below still react to its box.

Step 5 โ€” margin-inline: auto Is the Modern Standard

margin-inline: auto is the logical property equivalent of margin: 0 auto. It works correctly in right-to-left and vertical writing modes, making it the future-proof choice for internationalised layouts.

Real-World Example: Article Layout with Vertical Rhythm

/* article.css โ€” vertical rhythm with single-direction margins */
*, *::before, *::after { box-sizing: border-box; }

body {
  font-family: Georgia, 'Times New Roman', serif;
  background: #fafaf9;
  color: #1c1917;
  margin: 0;
  padding: 0;
}

.article-wrap {
  max-width: 720px;
  margin-inline: auto;
  padding: 48px 24px;
}

/* All headings use margin-bottom only */
h1 { font-size: 2.25rem; margin: 0 0 8px;  line-height: 1.15; }
h2 { font-size: 1.5rem;  margin: 0 0 12px; }
h3 { font-size: 1.2rem;  margin: 0 0 8px;  }
p  { margin: 0 0 20px;   line-height: 1.75; font-size: 1.05rem; }

/* Section spacing โ€” intentional top margin exception */
.article-section { margin-top: 48px; }

/* Pull-quote โ€” negative margin escapes the column */
.pull-quote {
  margin: 32px -32px;
  padding: 24px 32px;
  background: #fef9c3;
  border-left: 5px solid #eab308;
  font-size: 1.2rem;
  font-style: italic;
  color: #78350f;
  border-radius: 0 8px 8px 0;
}

/* Figure โ€” image extends slightly beyond text column */
figure {
  margin: 32px -16px;
}
figure img {
  width: 100%;
  border-radius: 8px;
  display: block;
}
figcaption {
  text-align: center;
  font-size: 0.85rem;
  color: #78716c;
  margin-top: 8px;
  font-style: italic;
}

/* Back-to-top โ€” auto margin pushes to the right */
.back-top {
  display: block;
  width: fit-content;
  margin-left: auto;
  margin-top: 48px;
  padding: 10px 20px;
  background: #1c1917;
  color: white;
  text-decoration: none;
  border-radius: 6px;
  font-size: 0.85rem;
  font-family: system-ui, sans-serif;
}

Common Mistakes

Mistake 1 โ€” Expecting both margins to add together

โŒ Wrong โ€” assuming a 50px gap between elements:

.heading   { margin-bottom: 30px; }
.paragraph { margin-top: 20px; }
/* Actual gap = 30px (collapsed), not 50px */

โœ… Correct โ€” use single-direction margins for predictable spacing:

.heading   { margin-bottom: 30px; }
.paragraph { margin-top: 0; }   /* gap is exactly 30px */

Mistake 2 โ€” Using margin to position overlapping elements

โŒ Wrong โ€” large negative margins cause unpredictable layout shifts:

.badge { margin-top: -50px; margin-left: 200px; }

โœ… Correct โ€” use position: absolute for precise overlay positioning:

.parent { position: relative; }
.badge  { position: absolute; top: -10px; right: -10px; }

Mistake 3 โ€” margin: auto on inline elements

โŒ Wrong โ€” auto has no effect on inline elements:

span { margin: 0 auto; } /* no centering โ€” span is inline */

โœ… Correct โ€” change display first:

span { display: block; margin: 0 auto; width: fit-content; }

▶ Try It Yourself

Quick Reference

Syntax Sides Notes
margin: 16px All four Single value
margin: 8px 16px Top+Bottom / Left+Right Two-value shorthand
margin: 8px 16px 24px 32px Top / Right / Bottom / Left Clockwise from top
margin: 0 auto 0 vertical, auto horizontal Centers block elements
margin-inline: auto Horizontal only Modern logical property
Negative margin Any side Pulls element toward that edge

🧠 Test Yourself

Element A has margin-bottom: 40px. Element B below it has margin-top: 25px. What is the actual gap between them?





โ–ถ Try It Yourself