CSS Padding
padding is the CSS property that controls the space between an element’s content and its border. Every visible box on a page — a button, a card, a paragraph — uses padding to keep its content from touching its own edges. Understanding padding thoroughly means understanding how it interacts with width, height, and box-sizing, because it directly changes how large an element actually renders on screen.
Overview / How it works
Every element in CSS is rendered as a rectangular box made of four layers, from the inside out: content, padding, border, and margin. This is called the box model. Padding sits directly around the content area and inside the border. It always takes on the element’s background — if you set a background-color or background-image on an element, that background extends underneath the padding, stopping exactly at the inner edge of the border. This is different from margin, which is always transparent and sits outside the border.
By default, in the standard box model (box-sizing: content-box), padding is added on top of the width and height you specify. If you set width: 200px and padding: 20px, the content area is 200px wide, but the padding adds 20px to each side, making the element’s total rendered width 240px (200 + 20 + 20). This surprises a lot of beginners, and it’s the single most common source of layout bugs involving padding. Most modern stylesheets fix this globally with box-sizing: border-box, which is covered in detail below.
Padding also affects layout in other ways: it never collapses (unlike vertical margins between block elements), it always accepts only non-negative values, and it can be set as a length (px, em, rem) or a percentage. Percentage padding has a special, often-misunderstood rule explained in the "Under the hood" section below.
Syntax
The padding shorthand can take one, two, three, or four values, controlling all four sides at once:
padding: <top> <right> <bottom> <left>;
| Number of values | Meaning |
|---|---|
| 1 value | Applies to all four sides |
| 2 values | First = top & bottom, second = left & right |
| 3 values | First = top, second = left & right, third = bottom |
| 4 values | Top, right, bottom, left — clockwise starting from the top |
You can also target a single side with the longhand properties, or use the newer logical properties that adapt to writing direction:
| Property | Controls |
|---|---|
padding-top / padding-bottom |
One physical side |
padding-left / padding-right |
One physical side |
padding-block |
Block-start and block-end (top/bottom in horizontal writing modes) |
padding-inline |
Inline-start and inline-end (left/right in LTR horizontal writing modes) |
Accepted value types are lengths (px, em, rem, etc.) and percentages. Negative values are not allowed — the browser will simply ignore an invalid declaration and fall back to whatever padding value it would otherwise have.
Examples
Example 1: Basic padding on all sides
.card {
padding: 20px;
background-color: #f4f4f4;
border: 1px solid #ccc;
}
Applies to: <div class="card">...</div>
Result: The card’s light-gray background and border now sit 20px away from the text or child elements inside it on every side. The content no longer touches the border — there’s an even ring of breathing room all the way around.
This is the simplest and most common use of padding: one value, applied uniformly, to give an element internal breathing room.
Example 2: Different padding per side with the 4-value shorthand
.notice {
padding: 10px 20px 15px 5px;
background-color: #fff8e1;
border-left: 4px solid #ffb300;
}
Result: The notice box gets 10px of space above its text, 20px on the right, 15px below, and only 5px on the left (which sits right next to the amber accent border). The asymmetry pulls the text slightly closer to the colored border edge while keeping generous space on the other three sides.
This pattern — a thin accent border with tighter padding on that side — is common for callout boxes, alerts, and blockquotes.
Example 3: Padding with box-sizing and logical properties on a button
.button {
padding-block: 0.75em;
padding-inline: 1.5em;
box-sizing: border-box;
background-color: #2563eb;
color: #ffffff;
border: none;
border-radius: 6px;
}
Result: The button renders as a solid blue rounded rectangle. Because the padding values are in em, they scale with the button’s own font size — a larger font-size on the button produces proportionally larger padding automatically. Using padding-block and padding-inline instead of top/bottom/left/right means the spacing would automatically flip sides correctly if the page’s writing direction were right-to-left.
This is a realistic, production-style button: box-sizing: border-box means any explicit width you later add won’t be inflated by the padding, and em-based padding keeps the button’s proportions consistent as text size changes.
How it works step by step / Under the hood
Consider this box model calculation, which is exactly what the browser’s layout engine performs:
.box {
width: 300px;
padding: 20px;
border: 5px solid #000;
box-sizing: content-box;
}
- Step 1 — content width: The browser reads
width: 300px. Undercontent-box(the default), this value describes the content area only. - Step 2 — add padding: 20px of padding is added to each side of that content area: 300 + 20 + 20 = 340px.
- Step 3 — add border: The 5px border is added to each side on top of that: 340 + 5 + 5 = 350px.
- Step 4 — final rendered width: The element occupies 350px of horizontal space in the page layout, even though you only wrote
width: 300px.
If you instead set box-sizing: border-box on that same box, the browser reverses the math: it treats the declared width: 300px as the final outer size, and shrinks the content area to make padding and border fit inside it (content becomes 300 − 20 − 20 − 5 − 5 = 250px wide). This is why border-box is so widely recommended — it makes padding predictable instead of additive.
Percentage padding has its own quirk worth understanding deeply: a percentage padding value — even padding-top or padding-bottom — is always calculated relative to the width of the containing block, never its height. This is a leftover of how the original CSS box model spec was written, and it’s the mechanism behind the classic "aspect-ratio box" trick, where padding-top: 56.25% on an empty element creates a 16:9 box regardless of its height.
Common Mistakes
Mistake 1: Forgetting box-sizing and getting an element wider than intended
.box {
width: 300px;
padding: 20px;
}
This looks like it should produce a 300px-wide box, but because the default box-sizing is content-box, padding is added on top of the width, producing a 340px-wide box. In a fixed-width layout (like a 3-column grid built with floats or fixed widths), this causes the box to overflow its container or wrap unexpectedly.
Fixed:
.box {
width: 300px;
padding: 20px;
box-sizing: border-box;
}
Now the box stays exactly 300px wide in total, with the content area shrinking to accommodate the padding. Many teams add *, *::before, *::after { box-sizing: border-box; } globally at the top of their stylesheet specifically to avoid this class of bug everywhere.
Mistake 2: Assuming percentage padding is relative to height
.spacer {
padding-top: 10%;
padding-bottom: 10%;
}
A developer might expect this to create padding equal to 10% of the element’s own height, especially inside a tall container. In reality, as explained above, percentage padding on any side is always computed from the containing block’s width, so resizing the browser window horizontally will change this spacing even though nothing about the element’s height changed — a frequent source of "my spacing changes when I resize the window and I don’t know why" bug reports.
Fixed (use a fixed or viewport-relative unit instead, if height-independent spacing was the actual goal):
.spacer {
padding-block: 40px;
}
Use percentage padding intentionally only when you specifically want width-relative sizing (such as the aspect-ratio trick), and reach for px, rem, or em otherwise.
Best Practices
- Set
box-sizing: border-boxglobally (or at least on components you size explicitly) so padding never silently inflates an element’s declared width or height. - Prefer
remfor padding that should stay consistent across a page, andemfor padding that should scale with a specific element’s own font size (like buttons and badges). - Use the shorthand
paddingwhen all or most sides share similar values, and the longhand or logical properties (padding-top,padding-inline, etc.) when you need to override just one side without repeating the others. - Prefer logical properties (
padding-block,padding-inline) over physical ones (padding-top,padding-left) in components that need to support right-to-left languages. - Remember that padding is never negative — if you need an element to visually overlap its container, use negative margin or transform instead.
- Don’t rely on percentage padding for vertical spacing unless you specifically want it tied to the container’s width.
Practice Exercises
Exercise 1: Create a .card class with a fixed width: 250px, a 2px solid border, and 24px of padding on all sides, such that the element’s total rendered width is still exactly 250px. Which property do you need to add, and what value?
Exercise 2: Write a single padding shorthand declaration that gives an element 8px of top padding, 16px of left and right padding, and 12px of bottom padding, using as few values as the shorthand allows.
Exercise 3: Using only padding-top (or padding-bottom) and a percentage value, create an empty <div> that always maintains a 4:3 aspect ratio regardless of its width. Hint: the percentage should equal (height ÷ width) × 100.
Summary
paddingcreates space between an element’s content and its border, and takes on the element’s background color/image.- The shorthand accepts 1 to 4 values in top/right/bottom/left (clockwise) order; longhand and logical properties let you target individual sides.
- Under the default
content-boxmodel, padding adds to the declared width/height;box-sizing: border-boxmakes the declared size the final outer size instead. - Percentage padding values — on every side, including top and bottom — are always calculated relative to the containing block’s width, not its height.
- Padding values must be zero or positive; negative padding is invalid and ignored.
- Logical properties like
padding-blockandpadding-inlineadapt automatically to the page’s writing direction.
