Polyglot
Languages Web (HTML / CSS / JS) css box model
Web (HTML / CSS / JS) § css-box-model

Box model

The CSS box model describes how every element’s content, padding, border, and margin combine to occupy space on the page. The display property determines whether an element generates a block-level box (display: block), an inline box (display: inline), or one of the more substantial layout contexts (flex, grid, etc.). The box-sizing property admits substantial control over how the box’s total size is computed: content-box (default — width applies to content only) vs border-box (width includes padding and border — conventionally preferred). The position property admits static (default), relative, absolute, fixed, and sticky positioning. The combination — content/padding/border/margin, the box-sizing choice, the display modes, the positioning system — is the substance of CSS’s spatial model.

The box

Every element is a box with four areas:

┌──────── margin ─────────┐
│  ┌────── border ──────┐ │
│  │  ┌── padding ────┐ │ │
│  │  │   content    │ │ │
│  │  └──────────────┘ │ │
│  └───────────────────┘ │
└────────────────────────┘
.box {
    width: 200px;
    height: 100px;
    padding: 1rem;
    border: 2px solid black;
    margin: 1rem;
    background: lightblue;
}

The default box-sizing: content-box produces total width:

total width = width + padding-left + padding-right + border-left + border-right
            = 200 + 16 + 16 + 2 + 2 = 236px

total space (with margin) = total width + margin-left + margin-right
                         = 236 + 16 + 16 = 268px

box-sizing

The box-sizing: border-box admits width includes padding and border:

.box {
    box-sizing: border-box;
    width: 200px;
    padding: 1rem;
    border: 2px solid black;
    /* Total width is 200px (content area is 200 - 32 - 4 = 164px) */
}

The conventional contemporary discipline applies border-box globally:

*, *::before, *::after {
    box-sizing: border-box;
}

The mechanism admits substantial layout simplification — width is what you specify.

display

The principal display values:

.block { display: block; }                         /* full width, new line */
.inline { display: inline; }                       /* flows with text */
.inline-block { display: inline-block; }           /* inline but admits width/height */
.none { display: none; }                           /* removed from layout */
.flex { display: flex; }                           /* flex container */
.grid { display: grid; }                           /* grid container */
.contents { display: contents; }                   /* removes the box but keeps children */

The principal differences:

DisplayBlockInlineInline-block
Full-width defaultYesNoNo
Admits width/heightYesNoYes
Margin top/bottomYesNoYes
New lineYesNoNo

Block elements: <div>, <p>, <h1><h6>, <section>, <article>, <header>, <footer>, <form>, <ul>, <li>.

Inline elements: <span>, <a>, <strong>, <em>, <img>, <br>.

Margin

.box {
    margin: 1rem;                                  /* all sides */
    margin: 1rem 2rem;                             /* vertical horizontal */
    margin: 1rem 2rem 1rem;                        /* top, h, bottom */
    margin: 1rem 2rem 1rem 0;                      /* top, right, bottom, left */
}

/* Individual: */
.box {
    margin-top: 1rem;
    margin-right: 2rem;
    margin-bottom: 1rem;
    margin-left: 2rem;
}

/* Logical (admits internationalisation): */
.box {
    margin-block: 1rem;                            /* top + bottom */
    margin-inline: 2rem;                           /* left + right (in LTR) */
    margin-block-start: 1rem;                      /* top in LTR */
    margin-inline-end: 1rem;                       /* right in LTR */
}

/* Auto margins (centre): */
.centered {
    width: 800px;
    margin: 0 auto;                                /* horizontal centre */
}

/* Negative margins: */
.box { margin-top: -1rem; }                        /* admit overlap */

Margin collapsing

A distinctive CSS feature: adjacent vertical margins collapse to the larger of the two:

h1 { margin-bottom: 2rem; }
p { margin-top: 1rem; }

The space between <h1> and <p> is 2rem, not 3rem.

The principal rules:

  • Vertical only — horizontal margins do not collapse.
  • Adjacent siblings — collapse.
  • Parent and first/last child — collapse if no padding/border separates them.
  • Empty blocks — collapse top and bottom.

The conventional defence (where collapse is undesirable):

.parent {
    padding: 1px 0;                                /* admit parent padding */
    /* or */
    overflow: auto;                                /* establish block formatting context */
    /* or */
    display: flex;                                 /* flex containers don't collapse */
}

Padding

.box {
    padding: 1rem;                                 /* all sides */
    padding: 1rem 2rem;                            /* vertical horizontal */
    padding: 1rem 2rem 1rem 0;                     /* top, right, bottom, left */
    padding-top: 1rem;
    padding-block: 1rem;
    padding-inline: 2rem;
}

Padding does not collapse — admit substantial space-establishment.

Border

.box {
    border: 1px solid black;                       /* width style color */
    border-width: 1px;
    border-style: solid;
    border-color: black;

    /* Per side: */
    border-top: 2px solid red;
    border-right: 1px dashed blue;

    /* Border radius: */
    border-radius: 0.5rem;                         /* all corners */
    border-radius: 0.5rem 0;                       /* TL+BR, TR+BL */
    border-radius: 50%;                            /* circle/ellipse */
    border-top-left-radius: 1rem;

    /* Outline (drawn outside, doesn't affect layout): */
    outline: 2px solid blue;
    outline-offset: 4px;
}

The principal border styles: solid, dashed, dotted, double, groove, ridge, inset, outset, none, hidden.

width and height

.box {
    width: 200px;
    height: 100px;

    /* Sizing keywords: */
    width: auto;                                   /* default */
    width: 100%;                                   /* parent's width */
    width: 50vw;                                   /* 50% viewport width */

    /* Min/max: */
    min-width: 100px;
    max-width: 800px;
    min-height: 50px;
    max-height: 100vh;

    /* Modern: */
    width: fit-content;                            /* shrink to content */
    width: max-content;                            /* widest content */
    width: min-content;                            /* narrowest content */
    inline-size: 200px;                            /* logical width */
    block-size: 100px;                             /* logical height */
}

The conventional discipline:

  • Use max-width over width for substantial responsive design.
  • Use min-height: 100vh for full-viewport sections.
  • Use width: 100% with max-width for “full width up to a limit”.
.container {
    width: 100%;
    max-width: 800px;
    margin: 0 auto;
}

Length units

The principal CSS units:

/* Absolute: */
width: 100px;                                      /* pixels */
width: 1in;                                        /* inches */
width: 2.54cm;                                     /* centimetres */
width: 12pt;                                       /* points */

/* Font-relative: */
width: 1em;                                        /* current element's font-size */
width: 1rem;                                       /* root element's font-size (typically 16px) */
width: 1ex;                                        /* x-height */
width: 1ch;                                        /* width of '0' character */

/* Viewport-relative: */
width: 100vw;                                      /* 100% viewport width */
height: 100vh;                                     /* 100% viewport height */
width: 50vmin;                                     /* 50% of smaller dimension */
width: 50vmax;                                     /* 50% of larger dimension */

/* New (CSS Values L4): */
height: 100dvh;                                    /* dynamic viewport height (excludes mobile UI) */
height: 100svh;                                    /* small viewport height */
height: 100lvh;                                    /* large viewport height */

/* Percentages: */
width: 50%;                                        /* 50% of parent */

The conventional discipline:

  • rem for font sizes, spacing — admits substantial root-font-size scaling.
  • em for spacing relative to current font.
  • px for borders, fixed thresholds.
  • % for proportional widths.
  • vh/vw for full-viewport layouts.
  • dvh for mobile-friendly viewports.

Position

.static { position: static; }                      /* default; in normal flow */
.relative { position: relative; top: 10px; }       /* offset from normal position */
.absolute { position: absolute; top: 0; left: 0; } /* relative to nearest positioned ancestor */
.fixed { position: fixed; top: 0; }                /* relative to viewport */
.sticky { position: sticky; top: 0; }              /* sticks when scrolling */

The principal differences:

PositionRemoved from flow?ReferenceUse
staticNoDefault
relativeNoOriginal positionAnchor for absolute children
absoluteYesNearest positioned ancestorTooltips, dropdowns, overlays
fixedYesViewportHeaders, modals
stickyPartiallyScroll containerSticky headers/sidebars

For absolute positioning, the anchor is the nearest ancestor with position: relative (or absolute/fixed/sticky):

.parent {
    position: relative;                            /* establish containing block */
}

.tooltip {
    position: absolute;
    top: 100%;                                     /* below parent */
    left: 0;
}

For sticky:

.sticky-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: white;
}

The element sticks to the top as the user scrolls past — substantial for navigation bars.

z-index

For positioned elements, z-index controls stacking:

.modal {
    position: fixed;
    z-index: 100;
}

.tooltip {
    position: absolute;
    z-index: 50;
}

.regular {
    z-index: auto;                                 /* default */
}

The principal rules:

  • z-index works only on positioned elements (not static).
  • Higher wins over lower.
  • Stacking contexts — substantial scoping; child can’t escape parent’s stacking context.

Overflow

When content exceeds container:

.box {
    overflow: visible;                             /* default; content overflows */
    overflow: hidden;                              /* clipped */
    overflow: scroll;                              /* always show scrollbars */
    overflow: auto;                                /* scrollbars when needed */

    /* Per axis: */
    overflow-x: hidden;
    overflow-y: auto;

    /* Modern: */
    overflow: clip;                                /* like hidden but no scrolling */
    text-overflow: ellipsis;                       /* with overflow:hidden + white-space:nowrap */
    overscroll-behavior: contain;                  /* prevent scroll chaining */
}

For single-line ellipsis:

.truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

For multi-line ellipsis (modern browsers):

.truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

Common patterns

Reset

The conventional box-sizing reset:

*, *::before, *::after {
    box-sizing: border-box;
}

body {
    margin: 0;
}

Centred container

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

Aspect ratio

.ratio-16-9 {
    aspect-ratio: 16 / 9;
    width: 100%;
}

.square {
    aspect-ratio: 1;
}

The aspect-ratio admits substantial responsive sizing without padding tricks.

body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

main {
    flex: 1;
}

footer {
    /* sticks to bottom when content is short */
}
.modal-backdrop {
    position: fixed;
    inset: 0;                                      /* shorthand: top/right/bottom/left = 0 */
    background: rgba(0, 0, 0, 0.5);
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal {
    background: white;
    padding: 2rem;
    border-radius: 0.5rem;
    max-width: 500px;
    max-height: 80vh;
    overflow: auto;
}

The inset: 0 admits substantial conciseness for full-coverage absolute/fixed positioning.

Floating action button

.fab {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: blue;
    color: white;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

Sticky table header

table {
    width: 100%;
}

thead th {
    position: sticky;
    top: 0;
    background: white;
    z-index: 1;
}

Responsive image

img {
    max-width: 100%;
    height: auto;
    display: block;
}

The pattern admits substantial responsive image scaling.

Card with shadow

.card {
    background: white;
    padding: 1.5rem;
    border-radius: 0.5rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    transition: box-shadow 0.2s;
}

.card:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

Logical properties

For internationalisation:

.box {
    /* Physical (LTR-specific): */
    margin-left: 1rem;

    /* Logical (admits RTL): */
    margin-inline-start: 1rem;

    padding-block: 1rem 2rem;                      /* top 1rem, bottom 2rem */
    padding-inline: 1rem;                          /* left + right */

    border-inline-start: 2px solid blue;           /* "left" in LTR */
}

The mechanism admits substantial RTL support.

Block formatting context

To prevent margin collapse and to clear floats:

.bfc {
    overflow: auto;                                /* establishes BFC */
    /* or: */
    display: flow-root;                            /* modern, explicit */
    /* or: */
    display: flex;
    /* or: */
    display: grid;
}

inset shorthand

.absolute-cover {
    position: absolute;
    inset: 0;                                      /* top: 0; right: 0; bottom: 0; left: 0 */
    /* ... */
}

.modal {
    position: fixed;
    inset: 0;
    /* equivalent to top:0; right:0; bottom:0; left:0 */
}

.partial {
    inset: 1rem 2rem;                              /* top/bottom: 1rem; left/right: 2rem */
}

Scroll-snap

.carousel {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    display: flex;
}

.slide {
    flex: 0 0 100%;
    scroll-snap-align: start;
}

contain for performance

.card {
    contain: layout paint;                         /* admit substantial isolation */
}

.list-item {
    contain: layout style;
}

The contain admits substantial browser optimisations — substantial for hot animations.

A note on display: none vs visibility: hidden

.removed { display: none; }                        /* gone from layout */
.invisible { visibility: hidden; }                  /* invisible but takes space */
.transparent { opacity: 0; }                        /* visible position, transparent */

The principal differences:

  • display: none — removed from DOM layout; not focusable; not announced by screen readers.
  • visibility: hidden — takes layout space; not focusable; not announced.
  • opacity: 0 — takes layout space; focusable; announced; admits transitions.

For animatable hiding:

.fading {
    opacity: 1;
    transition: opacity 0.3s;
}

.fading.hidden {
    opacity: 0;
    pointer-events: none;
}

A note on the conventional discipline

The contemporary CSS box-model advice:

  • Use box-sizing: border-box globally — admits substantial layout simplification.
  • Use max-width over width for responsive containers.
  • Use logical properties (margin-block, padding-inline) for internationalisation.
  • Use inset: 0 for full-coverage positioning.
  • Use position: sticky for substantial sticky headers/sidebars.
  • Use aspect-ratio for substantial responsive sizing.
  • Use display: flow-root to establish BFC (over overflow: auto).
  • Use rem and em over px for substantial scalability.
  • Avoid margin collapse pitfalls — use flex/grid containers.
  • Use contain for substantial performance optimisation.
  • Use dvh for mobile-friendly full-viewport heights.

The combination — content/padding/border/margin, the box-sizing modes, the display values, the positioning system, the substantial length units, the logical properties for internationalisation — is the substance of CSS’s spatial model. The discipline produces predictable, well-spaced layouts with substantial flexibility for substantial design systems.