CSS Reference Guide

All TopicsPlayground

The Box Model

Every element rendered on a webpage is a rectangular box. The CSS Box Model defines how content, padding, border, and margin combine to determine the total space an element occupies. Mastering it is essential to controlling layout.

margin padding border box-sizing outline border-radius margin collapsing

What Is the Box Model

In CSS, every element generates a rectangular box. The box model describes how four concentric areas stack around the element's content:

  1. Content — The actual text, image, or child elements inside the box.
  2. Padding — Transparent space between the content and the border.
  3. Border — A visible (or invisible) line surrounding the padding.
  4. Margin — Transparent space outside the border that separates the element from its neighbors.

Visual Diagram

Below is a fully interactive representation of the box model, built with nested <div> elements. Each colored layer corresponds to one area of the model.

Live Example — Box Model Diagram
Margin
Border
Padding
Content

■ Margin   ■ Border   ■ Padding   ■ Content

Total Element Size Calculation

Under the default content-box model, the total width and height of an element are calculated as:

Formula
Total Width  = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right
Total Height = margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom
Live Example — Total Size Calculation
width: 200px
padding: 20px
border: 5px
margin: 15px
Rendered content width: 200px
+ padding-left + padding-right: 20 + 20 = 40px
+ border-left + border-right: 5 + 5 = 10px
Visible box width: 250px
+ margin-left + margin-right: 15 + 15 = 30px
Total space occupied: 280px
DevTools Tip

All modern browsers display the box model visually in DevTools. Right-click an element, choose "Inspect", and look for the box model diagram in the Computed or Layout panel. Hover over the diagram sections to see each area highlighted on the page.

Content Area

The content area is the innermost part of the box model. It holds the element's actual content — text, images, or child elements. The size of the content area is controlled by the width and height properties, along with their min- and max- variants.

width & height

These properties set explicit dimensions for the content area. By default (with box-sizing: content-box), they do not include padding or border.

CSS
.box {
  width: 300px;
  height: 150px;
}

/* Auto is the default — block elements expand to fill parent width */
.auto-box {
  width: auto;   /* default */
  height: auto;  /* grows with content */
}

min-width, max-width, min-height, max-height

These constrain the box's dimensions, creating flexible but bounded layouts. They are essential for responsive design.

CSS
.responsive-card {
  width: 100%;
  max-width: 600px;   /* never wider than 600px */
  min-width: 280px;   /* never narrower than 280px */
}

.text-container {
  min-height: 200px;  /* at least this tall */
  max-height: 80vh;   /* at most 80% of viewport */
  overflow-y: auto;   /* scroll if content overflows */
}
Live Example — min/max Constraints
width: 100%
max-width: 300px
min-width: 120px
min-height: 80px
width: 50%
max-width: 200px
max-height: 100px
overflow: auto
(resize your browser to see these constraints in action)
PropertyDefaultApplies ToDescription
widthautoAll except inlineSets the content width
heightautoAll except inlineSets the content height
min-widthautoAll except inlineMinimum content width
max-widthnoneAll except inlineMaximum content width
min-heightautoAll except inlineMinimum content height
max-heightnoneAll except inlineMaximum content height
Pro Tip

Prefer max-width: 100% on images and media to prevent them from overflowing their container: img { max-width: 100%; height: auto; }. This is one of the most common responsive patterns.

Padding

Padding is the transparent space between the content area and the border. It pushes the content inward. Padding is always non-negative (you cannot use negative values) and inherits the element's background color.

Individual Padding Properties

CSS
.box {
  padding-top: 20px;
  padding-right: 30px;
  padding-bottom: 20px;
  padding-left: 30px;
}

Shorthand — padding

The padding shorthand accepts 1 to 4 values, applied clockwise starting from the top:

CSS
/* 1 value: all four sides */
.a { padding: 20px; }
/* top=20  right=20  bottom=20  left=20 */

/* 2 values: vertical | horizontal */
.b { padding: 10px 30px; }
/* top=10  right=30  bottom=10  left=30 */

/* 3 values: top | horizontal | bottom */
.c { padding: 10px 30px 20px; }
/* top=10  right=30  bottom=20  left=30 */

/* 4 values: top | right | bottom | left (clockwise) */
.d { padding: 10px 20px 30px 40px; }
/* top=10  right=20  bottom=30  left=40 */
Live Example — Padding Shorthand Values
padding: 20px
(all sides equal)
padding: 10px 40px
(vertical | horizontal)
padding: 8px 30px 24px
(top | horiz | bottom)
padding: 5px 15px 25px 40px
(top | right | bottom | left)

Percentage Padding

When you use a percentage value for padding, it is always calculated relative to the width of the containing block — even for vertical padding (padding-top and padding-bottom). This quirk is actually useful for creating aspect-ratio boxes.

CSS
/* Aspect ratio trick: 16:9 responsive box */
.aspect-16-9 {
  width: 100%;
  padding-top: 56.25%;  /* 9/16 = 0.5625 = 56.25% */
  height: 0;
  position: relative;
}

.aspect-16-9 > * {
  position: absolute;
  inset: 0;
}
Live Example — Percentage Padding (16:9 Aspect Ratio)
16 : 9 Aspect Ratio Box
(resize the window to see it scale)
Gotcha: Percentage Padding Direction

padding-top: 50% and padding-bottom: 50% are resolved against the element's containing block width, not height. This catches many developers off guard. Modern CSS offers aspect-ratio as a cleaner alternative for most use cases.

Border

The border wraps around the padding and content. Unlike padding and margin, borders are visible by default (when given a style). A border has three sub-properties: border-width, border-style, and border-color.

border-width

Sets the thickness of the border. Accepts length values or keywords (thin, medium, thick).

CSS
.box {
  border-width: 2px;              /* all sides */
  border-width: 1px 3px;           /* vertical | horizontal */
  border-width: 1px 2px 3px 4px;  /* top | right | bottom | left */
}

/* Individual sides */
.box {
  border-top-width: 3px;
  border-right-width: 1px;
  border-bottom-width: 3px;
  border-left-width: 1px;
}

border-style

Defines the line pattern of the border. The border is invisible until you set a style (default is none). CSS defines ten border styles:

CSS
.box { border-style: solid; }    /* continuous line */
.box { border-style: dashed; }   /* series of dashes */
.box { border-style: dotted; }   /* series of dots */
.box { border-style: double; }   /* two parallel lines */
.box { border-style: groove; }   /* carved into the page */
.box { border-style: ridge; }    /* opposite of groove */
.box { border-style: inset; }    /* sunken appearance */
.box { border-style: outset; }   /* raised appearance */
.box { border-style: none; }     /* no border (default) */
.box { border-style: hidden; }   /* same as none, except in table border collapsing */
Live Example — All Border Styles
solid
dashed
dotted
double
groove
ridge
inset
outset
none (invisible)
hidden (invisible)

border-color

Sets the color of the border. Defaults to the element's color property value (i.e., currentColor).

CSS
.box {
  border-color: #e74c3c;                          /* all sides */
  border-color: #e74c3c #3498db;                 /* vertical | horizontal */
  border-color: #e74c3c #3498db #2ecc71 #e67e22; /* top | right | bottom | left */
}

border Shorthand

The border shorthand sets width, style, and color in a single declaration. Order does not matter, but style is required for the border to appear.

CSS
.box {
  border: 2px solid #3498db;
}

/* Individual side shorthands */
.box {
  border-top: 3px dashed #e74c3c;
  border-right: 1px solid #ccc;
  border-bottom: 3px double #2ecc71;
  border-left: 1px solid #ccc;
}
Live Example — Mixed Border Sides
border: 3px solid
each side different
border-left only
(blockquote style)
border-bottom only
(underline style)
Note: border vs. border-top overrides

The border shorthand resets all four sides. If you write border: 2px solid red; border-top: none;, it works. But if you reverse the order to border-top: none; border: 2px solid red;, the top border reappears because the shorthand overwrites the individual property. Always put the shorthand first, then override specific sides.

Border Radius

The border-radius property rounds the corners of an element's outer border edge. It is purely visual and does not affect the box model calculations.

Single Value

CSS
.rounded {
  border-radius: 8px;   /* all four corners */
}

.more-rounded {
  border-radius: 20px;  /* more pronounced rounding */
}

Four Values (per corner)

Values go clockwise: top-left, top-right, bottom-right, bottom-left.

CSS
.custom-corners {
  border-radius: 10px 20px 30px 40px;
  /* top-left: 10px  top-right: 20px  bottom-right: 30px  bottom-left: 40px */
}

/* Individual corner properties */
.box {
  border-top-left-radius: 10px;
  border-top-right-radius: 20px;
  border-bottom-right-radius: 30px;
  border-bottom-left-radius: 0;
}

Elliptical Radii with /

You can specify separate horizontal and vertical radii using a / separator, creating elliptical curves instead of circular ones.

CSS
.elliptical {
  border-radius: 50px / 20px;
  /* horizontal-radius: 50px  vertical-radius: 20px */
}

.organic {
  border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%;
  /* creates a blob / organic shape */
}

Circles and Pills

CSS
/* Perfect circle (equal width and height required) */
.circle {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

/* Pill shape (works with any width) */
.pill {
  padding: 8px 24px;
  border-radius: 9999px;  /* any very large value works */
}
Live Example — Border Radius Variations
8px
20px
50%
circle
pill shape
10px 30px
10px 30px
elliptical
50% / 30%
organic
blob
Tip: 50% vs large pixel values

border-radius: 50% creates a circle only when the element is a square (equal width and height). For non-square elements, 50% creates an ellipse. Use a large pixel value like 9999px for pill-shaped buttons where the width varies.

Outline

An outline is a line drawn outside the border edge. Unlike borders, outlines do not take up space in the layout and do not affect the box model. They can overlap adjacent content.

Outline vs Border

FeatureBorderOutline
Affects layout / box sizeYesNo
Can differ per sideYesNo (uniform on all sides)
Follows border-radiusYesYes (modern browsers)
Can be offsetNoYes (outline-offset)
Part of box modelYesNo
CSS
.box {
  outline: 3px solid #e74c3c;
  outline-offset: 5px;  /* space between border and outline */
}

/* Individual properties */
.box {
  outline-width: 2px;
  outline-style: dashed;
  outline-color: #3498db;
  outline-offset: 4px;
}
Live Example — Outline vs Border
border

Takes up layout space

outline

Does NOT take up space

outline-offset
6px

Pushed outward from box

negative
offset

Negative offset goes inward

Accessibility and Focus Rings

Outlines are critical for keyboard accessibility. Browsers show a default outline when elements are focused via keyboard. Never remove the outline without providing an alternative visual indicator.

CSS
/* WRONG — removes all focus indicators */
*:focus {
  outline: none;  /* Don't do this! */
}

/* CORRECT — custom focus styles */
*:focus-visible {
  outline: 2px solid #6c8cff;
  outline-offset: 2px;
}

/* Hide outline for mouse clicks, show for keyboard */
button:focus:not(:focus-visible) {
  outline: none;
}
button:focus-visible {
  outline: 3px solid #6c8cff;
  outline-offset: 2px;
  border-radius: 4px;
}
Live Example — Focus Ring Demo (click and Tab through these)

Press Tab to cycle through these elements and observe the browser's default focus ring (outline).

Accessibility Warning

Removing outline on interactive elements without providing an alternative (such as box-shadow or a border change) makes your site unusable for keyboard-only users. Use :focus-visible to customize focus styles without harming accessibility.

Margin

Margin is the outermost layer of the box model — the transparent space outside the border that separates an element from its neighbors. Unlike padding, margins can be negative and can collapse with adjacent margins.

Individual Properties & Shorthand

CSS
/* Individual sides */
.box {
  margin-top: 20px;
  margin-right: 15px;
  margin-bottom: 20px;
  margin-left: 15px;
}

/* Shorthand (same rules as padding: 1/2/3/4 values) */
.a { margin: 20px; }                              /* all four sides */
.b { margin: 10px 30px; }                         /* vertical | horizontal */
.c { margin: 10px 30px 20px; }                   /* top | horizontal | bottom */
.d { margin: 10px 20px 30px 40px; }             /* top | right | bottom | left */

Auto Centering

Setting margin-left and margin-right to auto horizontally centers a block-level element with a declared width. This is one of the most fundamental centering techniques in CSS.

CSS
.centered {
  width: 600px;      /* must have an explicit width */
  margin: 0 auto;    /* top/bottom=0, left/right=auto */
}

/* Also works with max-width for responsive centering */
.responsive-centered {
  max-width: 800px;
  margin-inline: auto;  /* modern logical property */
}
Live Example — margin: auto Centering
width: 70%  |  margin: 0 auto
max-width: 300px
margin: 0 auto

Negative Margins

Unlike padding, margins can be negative. Negative margins pull an element in the specified direction, or pull adjacent elements toward it.

CSS
/* Pull element upward */
.overlap-up {
  margin-top: -20px;
}

/* Extend beyond parent padding */
.full-bleed {
  margin-left: -20px;
  margin-right: -20px;
}
Live Example — Negative Margins
Normal box (no negative margin)
margin-top: -20px (overlaps the box above)
margin-left: -24px; margin-right: -24px (full bleed, extends beyond parent padding)

Percentage Margins

Like percentage padding, all percentage margins (including top and bottom) are calculated relative to the width of the containing block.

CSS
.box {
  margin: 5%;  /* all four margins = 5% of parent's width */
}
Why percentages resolve to parent width

Both vertical and horizontal percentage margins resolve against the containing block's width for consistency. If vertical margins resolved against height, a circular dependency could occur: content height depends on margin, and margin depends on content height.

Margin Collapsing

Margin collapsing is one of the most confusing behaviors in CSS. When the vertical margins of two block-level elements touch (with nothing between them), they merge into a single margin equal to the larger of the two. This only happens with vertical margins, never horizontal.

When Margins Collapse

There are three main scenarios:

1. Adjacent Siblings

When two block-level siblings are stacked vertically, the bottom margin of the first and the top margin of the second collapse into one.

CSS
.box-a { margin-bottom: 30px; }
.box-b { margin-top: 20px; }

/* Resulting gap between them = 30px (NOT 50px) */
/* The larger margin wins */
Live Example — Adjacent Sibling Margin Collapse

Without collapse awareness (you might expect 50px):

margin-bottom: 30px
margin-top: 20px

Actual gap = 30px (collapsed), not 50px

2. Parent-Child Collapse

If a parent has no top padding, border, or anything else separating its top edge from its first child's top margin, the child's top margin escapes and collapses with the parent's margin.

CSS
/* The child's margin-top "leaks" out of the parent */
.parent {
  margin-top: 0;
  /* No padding-top, no border-top */
}
.child {
  margin-top: 40px;
  /* This margin escapes the parent! */
}
Live Example — Parent-Child Margin Collapse

Collapsed (no barrier):

child: margin-top: 30px
(margin escapes parent)

Fixed (with padding):

child: margin-top: 30px
(contained by parent's padding)

3. Empty Blocks

An element with no height, no padding, no border, and no content will have its own top and bottom margins collapse with each other.

CSS
/* This empty div's top and bottom margins collapse into one */
.empty {
  margin-top: 20px;
  margin-bottom: 30px;
  /* Resulting margin = 30px (the larger one) */
}

How to Prevent Margin Collapsing

Several techniques prevent margin collapse by introducing a separation between the margins:

CSS
/* 1. Add padding to the parent */
.parent { padding-top: 1px; }

/* 2. Add border to the parent */
.parent { border-top: 1px solid transparent; }

/* 3. Use overflow other than visible */
.parent { overflow: hidden; }  /* or auto */

/* 4. Make parent a flex or grid container */
.parent { display: flex; flex-direction: column; }
.parent { display: grid; }

/* 5. Use display: flow-root (creates new BFC) */
.parent { display: flow-root; }
Live Example — Preventing Margin Collapse

overflow: hidden

Contained margin

display: flex

Contained margin

display: flow-root

Contained margin
Best Practice

To avoid margin collapsing surprises, many developers adopt a "single-direction margin" convention: only use margin-bottom (or margin-top) for vertical spacing, never both. This makes spacing predictable and eliminates collapsing between siblings.

When margins do NOT collapse

Margins never collapse in these contexts: between flex items, between grid items, inline-level elements, floated elements, absolutely or fixed positioned elements, or elements with overflow other than visible on the parent.

box-sizing

The box-sizing property determines what the width and height properties refer to. It has two possible values, and understanding the difference is critical.

content-box (default)

With content-box, the width and height set only the content area. Padding and border are added on top of the declared dimensions.

CSS
.content-box-demo {
  box-sizing: content-box;  /* default */
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Rendered width = 200 + 20 + 20 + 5 + 5 = 250px */
}

border-box

With border-box, the width and height include padding and border. The content area shrinks to accommodate them. This is usually what developers want.

CSS
.border-box-demo {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Rendered width = exactly 200px */
  /* Content area = 200 - 20 - 20 - 5 - 5 = 150px */
}

Visual Comparison

Live Example — content-box vs border-box

Both boxes have width: 250px, padding: 20px, border: 5px solid. Notice the difference in total rendered width.

content-box (default):

width: 250px (content only)
+ padding: 40px + border: 10px
Total rendered: 300px

border-box:

width: 250px (total box)
padding + border included
Total rendered: 250px

Universal Reset Pattern

Nearly every modern CSS project applies border-box globally. The recommended pattern uses the inherit value on * so components that opt into a different model can change it on a parent and have children inherit it.

CSS
/* Universal box-sizing reset — industry standard */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Alternative: inheritable pattern */
html {
  box-sizing: border-box;
}
*,
*::before,
*::after {
  box-sizing: inherit;
}
Always Use border-box

The border-box model is more intuitive: when you say width: 300px, the element is exactly 300px wide, regardless of padding and border. Every major CSS framework (Bootstrap, Tailwind, Normalize.css) applies this reset. Add it to the very top of your stylesheet.

Display and the Box Model

The display property fundamentally changes how the box model applies to an element. The two key display types — block and inline — behave very differently.

Block-Level Elements

Block-level elements (display: block) get the full box model treatment:

Inline Elements

Inline elements (display: inline) have a restricted box model:

Inline-Block

display: inline-block gives you the best of both worlds: the element flows inline with text but respects all box model properties (width, height, vertical margin/padding).

CSS
/* Block: full box model, new line */
.block { display: block; }

/* Inline: width/height/vertical margin ignored */
.inline { display: inline; }

/* Inline-block: full box model, flows inline */
.inline-block { display: inline-block; }
Live Example — Block vs Inline vs Inline-Block

Here is text with a display:inline (width/height ignored) element, followed by more text.

Here is text with a display:inline-block (width/height respected) element, followed by more text.

display: block — takes full width, starts on a new line
Property block inline inline-block
width / heightRespectedIgnoredRespected
Horizontal marginRespectedRespectedRespected
Vertical marginRespected (collapses)IgnoredRespected
Horizontal paddingRespectedRespectedRespected
Vertical paddingRespectedVisual only (overlaps)Respected
Line break behaviorNew lineFlows inlineFlows inline
Gotcha: Inline Elements and Vertical Padding

Vertical padding on inline elements is painted visually but does not affect line height or push surrounding content. This often causes overlapping backgrounds. If you need vertical spacing on an inline element, switch to inline-block or inline-flex.

Common Gotchas & Pro Tips

Common Gotchas

Gotcha 1: Forgetting box-sizing

Without box-sizing: border-box, setting width: 100% on an element with padding or border causes it to overflow its parent. This is the number one box model bug for beginners. Always apply the universal reset.

CSS
/* BUG: overflows parent because padding is added to 100% */
.input {
  width: 100%;
  padding: 16px;
  /* box-sizing defaults to content-box */
  /* Rendered width = 100% + 32px — overflows! */
}

/* FIX */
.input {
  width: 100%;
  padding: 16px;
  box-sizing: border-box;
  /* Rendered width = exactly 100% */
}
Live Example — 100% Width + Padding Overflow

content-box (overflows):

width:100% + padding:16px + border:3px = OVERFLOW

border-box (fits perfectly):

width:100% including padding and border = FITS
Gotcha 2: Margin Collapse in Unexpected Places

A common surprise: your first child's margin-top "escapes" its parent container, pushing the entire parent down instead of creating space inside the parent. Fix: add padding-top: 1px, overflow: hidden, or display: flow-root on the parent.

Gotcha 3: Inline Elements Ignore width/height

Setting width or height on a <span>, <a>, <strong>, or other inline elements has no effect. You must change the display to inline-block, block, flex, or inline-flex first.

Gotcha 4: Percentage Height Needs an Explicit Parent Height

height: 50% only works if the parent has an explicit (non-auto) height. If the parent's height is auto (the default), the percentage height resolves to auto and is effectively ignored. For full-page layouts, set html, body { height: 100%; }.

Gotcha 5: Outline Does Not Follow border-radius (in Older Browsers)

In older browsers, outlines are always rectangular, even on elements with rounded corners. Modern browsers (Chrome 94+, Firefox 88+, Safari 16.4+) render outlines that follow border-radius. If you must support older browsers, use box-shadow instead for a rounded focus indicator.

Pro Tips

Tip 1: Use Logical Properties for Internationalization

Instead of margin-left / padding-right, use margin-inline-start / padding-inline-end. These logical properties adapt automatically for right-to-left (RTL) languages.

CSS
/* Physical (breaks in RTL) */
.card { padding-left: 20px; margin-right: 16px; }

/* Logical (works in any writing mode) */
.card { padding-inline-start: 20px; margin-inline-end: 16px; }
Tip 2: Debug with Outline, Not Border

When debugging layout, use outline: 1px solid red instead of border. Outlines do not affect layout or change the size of elements, so they will not shift things around while you are debugging.

CSS
/* Debugging helper: shows all element boxes without affecting layout */
* {
  outline: 1px solid rgba(255, 0, 0, 0.2);
}
Tip 3: Use gap Instead of Margins Between Flex/Grid Items

Flex and Grid containers support the gap property, which creates consistent spacing between children without worrying about margin collapsing, first/last child margins, or negative margins to undo row margins. Prefer gap whenever possible.

CSS
/* OLD approach: margin on children with negative margin on parent */
.grid {
  display: flex;
  flex-wrap: wrap;
  margin: -8px;
}
.grid > * { margin: 8px; }

/* MODERN: clean gap property */
.grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
Tip 4: aspect-ratio Replaces the Padding Hack

Instead of the old padding-top: 56.25% trick for maintaining aspect ratios, modern CSS has a dedicated aspect-ratio property. It is cleaner, more readable, and does not require absolute positioning of children.

CSS
/* Modern aspect ratio */
.video-container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

.square {
  width: 200px;
  aspect-ratio: 1;  /* shorthand for 1/1 */
}
Tip 5: box-shadow as a Pseudo-Border

You can use box-shadow with no blur and no spread to create a visual border that does not take up space (like outline but with per-side control and radius following). Multiple shadows let you create multi-colored borders or inset effects.

CSS
/* "Border" using box-shadow (no layout impact) */
.shadow-border {
  box-shadow: 0 0 0 3px #6c8cff;
  border-radius: 8px;
}

/* Double border effect */
.double-border {
  box-shadow:
    0 0 0 3px #6c8cff,
    0 0 0 6px #a78bfa;
}
Live Example — box-shadow as Border
shadow
"border"
double
"border"
inset
"border"

Quick Reference: Box Model Properties

AreaPropertiesCan Be Negative?Affects Layout?
Contentwidth, height, min-*, max-*NoYes
Paddingpadding, padding-*NoYes
Borderborder, border-*NoYes
Outlineoutline, outline-*No (offset can be)No
Marginmargin, margin-*YesYes (collapses vertically)
Previous CSS Basics