When to use margin vs padding in CSS?
Padding is space inside an element, margin is space outside it. Learn when to use each, how margin collapsing works, and why gap often beats both.
Use padding for space inside an element, between its border and its content. Use margin for space outside an element, between it and its neighbors. A quick test: if the space should have the element's background and react to clicks, it's padding.
.button {
padding: 0.75rem 1.25rem; /* inside: part of the button */
background: #4f46e5;
color: #fff;
}
.article h2 {
margin-top: 2rem; /* outside: distance from what's above */
}Padding: inside the border
Padding is part of the element. The background color or image fills it, and it's part of the clickable area. That makes padding the right choice for:
- buttons, where the padding creates the button's shape around the label,
- links in a navigation bar, so the whole block is clickable and not just the text,
- cards and panels, to keep content away from the edges.
For links, add display: block or inline-block (or put them in a flex container), otherwise vertical padding on an inline element doesn't push the lines around it.
With box-sizing: border-box, padding is included in the element's width. Without it, padding makes the element wider than the width you set. Most projects set border-box on everything in a reset.
Margin: outside the border
Margin is transparent space around the element that separates it from its siblings. It's never clickable and never shows the background. Use it for the distance between headings and paragraphs, between sections, or between a form field and the next one.
Vertical margins collapse
When two block elements sit on top of each other, their vertical margins don't add up. The larger one wins:
<h2 class="title">Pricing</h2>
<p class="intro">Pick the plan that fits your team.</p>.title {
margin-bottom: 24px;
}
.intro {
margin-top: 16px;
}
/* The gap between them is 24px, not 40px */The same happens between a parent and its first or last child. If a card has no padding or border, the margin-top of the heading inside it "leaks" out and pushes the whole card down, while the heading stays glued to the card's top edge. Padding on the card, or display: flow-root, stops that.
Margins don't collapse:
- horizontally,
- between items in a flex or grid container,
- between a parent and its child when padding, a border or
display: flow-rootseparates them.
So the same two elements inside a display: flex; flex-direction: column parent are 40px apart.
Negative values and auto
Margins can be negative, which pulls an element outside its normal position, for example to make an image break out of a padded card. Padding can't be negative, and the browser ignores the declaration.
margin: auto takes up the free space. On a block with a width, margin-inline: auto centers it horizontally. In a flex container, an auto margin pushes an item away from the others:
.navbar {
display: flex;
gap: 1rem;
}
.navbar .login {
margin-left: auto; /* pushed to the right edge */
}Use gap between siblings
For space between items in a flex or grid container, use gap instead of margins:
.card-list {
display: flex;
flex-direction: column;
gap: 1rem;
}With margins, you need extra rules to remove the margin from the first or last item, and it gets messy when items wrap. gap only adds space between items, never before the first or after the last one, and it works in rows and columns.
My rule of thumb: components set their own padding, and the layout around them decides the spacing with gap or margins. A card shouldn't come with a margin-bottom built in, because it doesn't know where it will be used.