When do you use margin and when padding?
Padding is space inside an element's border. It takes the element's background, makes clickable areas bigger and keeps text away from the edge of a card. Margin is space outside the border. It is always transparent and separates one element from its neighbours.
A quick test: if the space should be coloured like the box, or should count as part of a button you can tap, it is padding. If it is a gap between two things, it is margin, or better, a gap on their parent.
Browsers already add margin to many elements. Paragraphs, headings, lists and <figure> all have default top and bottom margins, and <body> has 8px all round. Much of the spacing you see on an unstyled page comes from these defaults, so check the DevTools box diagram before adding more.


margin and padding go clockwise from the top. When you give fewer than four, the missing sides copy their opposite.How do the 1 to 4 value shorthands work?
The margin and padding shorthands take one to four values. Four values go clockwise starting at the top: top, right, bottom, left. A memory aid is the word TRouBLe. With one value, all four sides match. With two, the first is top and bottom and the second is left and right. With three, the first is top, the second is both sides and the third is bottom.
The rule behind it: any side you leave out copies its opposite side. That is why padding: 12px 16px is the most common form for buttons and bars, a little room above and below and more on the sides.
Swapping the two values is a classic mistake. margin: auto 0 reads naturally as "auto on the sides" but actually means auto on top and bottom and zero on the sides, which does not centre anything.
.btn {
padding: 12px 20px;
}
.card {
margin: 0 0 24px;
}What are logical properties like margin-inline?
Logical properties describe sides by the direction text flows instead of by the screen. The inline direction is the way a line of text runs, left to right in English. The block direction is the way lines stack, top to bottom. So margin-inline sets left and right, padding-block sets top and bottom, and margin-inline-start is the left side in English and the right side in Arabic or Hebrew.
For a single-language English site the result looks identical to the physical properties. The gain comes when a page is translated into a right-to-left language: logical spacing flips automatically, and physical spacing has to be overridden by hand.
The two-value forms read cleanly too. margin-inline: auto centres a block, and padding-block: 24px 16px sets the start and end of the block axis. All logical spacing properties have been supported in every current browser for years.
.post {
max-width: 640px;
margin-inline: auto;
padding-block: 24px;
padding-inline: 20px;
}How do auto margins centre and push things?
A block element with a set width or max-width and margin-inline: auto sits in the middle of its container. The browser shares the leftover space equally between the two auto margins. Without a width limit there is no leftover space, so nothing appears to happen.
Inside a flex container, auto margins work in both directions and take all free space. margin-left: auto on the last link in a navigation bar pushes it to the far right, which is a common way to separate a "Sign in" link from the main menu. In a flex or grid item, margin: auto centres the item both ways.
Auto vertical margins do nothing in normal block flow. They resolve to zero, which is why margin: auto alone does not centre something vertically on a plain page.
.menu {
display: flex;
}
.menu .signin {
margin-left: auto;
}When are negative margins acceptable?
Margins can be negative, and padding cannot. A negative margin pulls an element toward or past its neighbour, or past its container's edge. A typical honest use is a full-bleed image inside a padded card: a negative inline margin equal to the card's padding lets the photo touch both edges of the card.
Use them sparingly. Negative margins make layout depend on exact numbers elsewhere, so a change to the card's padding breaks the image. They can also cause overlap that hides content or covers clickable links. When you see a negative margin in AI-generated CSS, ask what it is compensating for. Often it is undoing another margin that should be removed instead.
Linking the negative value to a variable keeps the two numbers in step, and calc() can flip the sign for you.
.card {
--pad: 20px;
padding: var(--pad);
}
.card .bleed {
margin-inline: calc(var(--pad) * -1);
}Why is gap the modern way to space siblings?
The gap property sets space between the children of a flex or grid container. It adds space only between items, never before the first or after the last, and never doubles up. That removes the old routine of adding a margin to every item and then cancelling it on the last one with :last-child.
It takes one value for both directions or two values for rows then columns, such as gap: 16px 24px. When flex items wrap onto a second line, the row gap spaces the lines too. Supported for flexbox in all current browsers since 2021.
For a plain vertical stack of blocks that are not in a flex or grid container, margins are still the tool. Many sites use a small helper with display: flex, flex-direction: column and a gap so the spacing between stacked items lives in one place.
.stack {
display: flex;
flex-direction: column;
gap: 16px;
}How does a spacing scale keep a design consistent?
Random spacing values such as 13px, 18px and 22px make a page look slightly off even when nobody can say why. A spacing scale is a short set of steps, often doubling or following a base of 4px or 8px, stored as custom properties on :root. Every margin, padding and gap then picks a step from the scale.
Using rem units for the scale makes spacing grow when a reader increases their default font size, which keeps text and the space around it in proportion. Name the steps by size, from extra small to extra large, so they stay useful whatever component uses them.
To check a page, open DevTools and hover over a few components. If most spacing values come from the scale and the odd ones out have a reason, the system is working.
:root {
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
--space-xl: 4rem;
}
.card {
padding: var(--space-md);
margin-bottom: var(--space-lg);
}Field notes
- Padding is space inside the border, and margin is space outside it.
- Shorthands with four values go clockwise from the top.
- Auto margins on the sides centre a block that has a set width.
gapadds space only between items in a flex or grid container.
Easy to get wrong
With two values the first is vertical and the second horizontal. Auto has to be on the sides to centre a block.
A margin on every item also lands after the last one. A gap on a flex or grid container spaces only between items.
Auto margins centre a block only when it is narrower than its container. Without a width limit there is no space to share.
Padding cannot be negative, so the declaration is dropped. Only margins accept negative values.
Questions people ask
Should I use px or rem for spacing?
rem scales with the reader's default font size, which keeps spacing in proportion to text. Use px for hairline details like 1px borders.
Does gap work without display: flex or grid?
No. On a normal block container the browser computes the value but it has no effect. It also works in multi-column layouts as the column gap.
Why do two stacked margins not add up?
Vertical margins between blocks in normal flow collapse into the larger of the two. Flex and grid items never collapse, which is another reason to prefer gap.
Can I mix logical and physical properties?
Yes, but whichever comes later wins for the side they share. Pick one style per project to avoid confusing overrides.