Skip to main content

Height, Width, and CSS Sizing: Complete Guide

Understanding how CSS determines an element's size — and which sizing keywords to use — is foundational to building layouts that work at every screen size.

1. The Basic width and height Properties

/* Fixed size — doesn't respond to content or screen size */
.c-box { width: 400px; height: 300px; }

/* Percentage — relative to the PARENT element's size */
.c-box { width: 50%; } /* 50% of parent's width */
.c-box { height: 50%; } /* 50% of parent's HEIGHT — only works if parent has explicit height */

/* Auto — browser calculates based on content and context */
.c-box { width: auto; } /* Block elements: fill available width */
.c-box { height: auto; } /* Fit to content height (default for most elements) */

[!IMPORTANT] height: 100% only works if the parent has an explicit height. If the parent's height is auto (the default), the child's percentage height collapses to 0.

/* Making 100% height work */
html, body { height: 100%; } /* Parent chain needs explicit height */
.l-page { height: 100%; } /* Each ancestor needs it */

/* Better alternative in modern CSS */
.l-page { min-height: 100dvh; } /* No parent chain required */

2. Min and Max Constraints

/* max-width: the element grows to this maximum, then stops */
.o-container { max-width: 1200px; width: 100%; margin-inline: auto; }
/* → On small screens: takes full width. On large: capped at 1200px. */

/* min-width: the element never shrinks below this */
.c-btn { min-width: 120px; } /* Button has minimum width even with short text */

/* max-height: content can grow to this max, then scrolls or overflows */
.c-dropdown { max-height: 300px; overflow-y: auto; }

/* min-height: element is at least this tall, grows with content */
.c-hero { min-height: 100dvh; } /* Full viewport minimum, grows if content is taller */
.c-card { min-height: 200px; } /* Cards have minimum consistent height */

3. Intrinsic Sizing Keywords

These keywords let the element's content determine its size — the modern way to size responsively:

fit-content

/* Element is as wide as its content, but doesn't exceed the available space */
.c-badge { width: fit-content; } /* Shrinks to text width */
.c-tag { width: fit-content; }

/* Common use: centering a block based on its content width */
.c-cta-block {
width: fit-content;
margin-inline: auto; /* Center it */
}

/* fit-content() function: caps at a maximum */
.c-sidebar { width: fit-content(300px); } /* Fit to content but max 300px */

min-content

/* Shrinks to the smallest possible size without overflowing */
/* For text: width of the longest single word */
/* For images: the intrinsic image width */
.c-narrow { width: min-content; }

/* Practical use: grid columns that fit their content tightly */
.o-grid-auto {
grid-template-columns: min-content 1fr; /* First column: tight fit, second: flexible */
}

max-content

/* Expands to fit all content in one line — no wrapping */
.c-nav__menu { width: max-content; }

/* Practical use: table column sizing */
.table { width: max-content; min-width: 100%; }

/* Grid: column fits all content without wrapping */
.o-grid-auto {
grid-template-columns: max-content 1fr; /* Label column: no wrap, content: flexible */
}

4. Viewport Units

/* Classic viewport units */
width: 100vw; /* 100% of viewport WIDTH */
height: 100vh; /* 100% of viewport HEIGHT */
font-size: 5vw; /* Fluid text — scales with viewport width */

/* The scrollbar bug with 100vw */
.full-width { width: 100vw; }
/* ❌ On Windows: 100vw includes scrollbar width → horizontal overflow */
/* ✅ Fix: use 100% on elements that are already inside the page flow */
/* Or: width: 100%; margin-inline: calc(-50vw + 50%) for full-bleed */

/* Dynamic viewport units (modern — accounts for mobile browser UI) */
height: 100dvh; /* dvh: Dynamic — recalculates as mobile browser bar shows/hides */
height: 100svh; /* svh: Small — assumes browser UI is ALWAYS visible (safe minimum) */
height: 100lvh; /* lvh: Large — assumes browser UI is ALWAYS hidden (full screen) */

/* Recommendation: */
.c-hero { min-height: 100dvh; } /* Use dvh for hero sections in 2026 */

5. aspect-ratio

Lock the width-to-height ratio of an element:

/* aspect-ratio: width / height */
.c-card__image { aspect-ratio: 16 / 9; } /* Video-style wide image */
.c-avatar { aspect-ratio: 1 / 1; } /* Perfect square */
.c-avatar { aspect-ratio: 1; } /* Same: shorthand for 1/1 */
.c-banner { aspect-ratio: 3 / 1; } /* Wide banner */
.c-thumbnail { aspect-ratio: 4 / 3; } /* Classic photo ratio */

/* Combined with width — height is calculated automatically */
.c-card__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover; /* Fill the ratio box without distortion */
}

/* Aspect ratio box pattern (no explicit height needed) */
.c-video-embed {
width: 100%;
aspect-ratio: 16 / 9;
background: var(--color-surface);
}

/* Legacy fallback if needed (rare in 2026) */
@supports not (aspect-ratio: 1) {
.c-card__image::before {
content: '';
display: block;
padding-bottom: 56.25%; /* 9/16 = 0.5625 = 56.25% */
}
}

6. object-fit and object-position — Controlling Images Inside Boxes

/* object-fit: how an <img> or <video> fills its box */
img {
width: 100%;
height: 200px;
object-fit: cover; /* Fill box, crop excess — most common for cards */
}

/* object-fit values */
object-fit: fill; /* Default — stretches to fill (distortion) */
object-fit: cover; /* Fill box, maintain ratio, CROP to fit */
object-fit: contain; /* Fit inside box, maintain ratio, NO cropping — letterbox */
object-fit: none; /* Image at natural size — may overflow or underflow */
object-fit: scale-down; /* smaller of: none or contain */

/* object-position: where to focus the crop */
object-position: center center; /* Default */
object-position: top center; /* Show top of image (portrait photos) */
object-position: 30% 20%; /* Fine-tune crop position */
object-position: left; /* Left edge stays in view */

7. overflow Control

/* overflow: what happens when content exceeds its container */
overflow: visible; /* Default: content shows outside the box */
overflow: hidden; /* Clips content at container edge */
overflow: scroll; /* Always shows scrollbar */
overflow: auto; /* Scrollbar only when needed (recommended) */
overflow: clip; /* Like hidden but no scroll context created */

/* Axis-specific overflow */
overflow-x: auto; /* Horizontal scrollbar if needed */
overflow-y: hidden; /* Clip vertical overflow */

/* The overflow:hidden + border-radius combo */
.c-card {
border-radius: var(--radius-xl);
overflow: hidden; /* Clips image corners to match card radius */
}

/* Scrolling containers */
.c-dropdown { max-height: 300px; overflow-y: auto; }
.c-code-block { overflow-x: auto; } /* Code that may be wide */

8. box-sizing — The Most Important Global Rule

/* The most critical global CSS rule — always include in your reset */
*, *::before, *::after {
box-sizing: border-box;
}

/* content-box (browser default — the bad one): */
/* width = content only. border + padding ADDED on top → element larger than you set */
.box { width: 300px; padding: 20px; border: 1px solid; }
/* Actual rendered width: 300 + 40 + 2 = 342px — NOT 300px */

/* border-box (what you want): */
/* width = content + padding + border. Total stays at declared width */
.box { box-sizing: border-box; width: 300px; padding: 20px; border: 1px solid; }
/* Actual rendered width: 300px — exactly what you declared */

9. Sizing Quick Reference

ValueWhat It DoesUse Case
100%100% of parentFull-width containers inside parent
100vw100% viewport widthFull-bleed sections (careful with scrollbar)
100dvhDynamic viewport heightHero sections on mobile
autoBrowser calculatesDefault — block elements fill width
fit-contentShrinks to content, respects parentInline-block feel with block display
min-contentSmallest without overflowTight grid columns
max-contentAll content in one lineGrid labels, nav items
min-width: 0Allow shrinking past contentFlex children with text overflow
aspect-ratioLocks ratioImages, videos, card thumbnails
max-width: 100%Never wider than parentResponsive images
clamp(min, ideal, max)Fluid with limitsResponsive containers and text

10. Real-World Sizing Patterns

/* Responsive container */
.o-container {
width: 100%;
max-width: 1200px;
margin-inline: auto;
padding-inline: clamp(1rem, 4vw, 2rem);
}

/* Card image that always fills and crops */
.c-card__image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
object-position: center;
}

/* Avatar: perfect circle at any size */
.c-avatar {
width: 3rem;
height: 3rem; /* or: aspect-ratio: 1; with width only */
border-radius: 50%;
object-fit: cover;
}

/* Sidebar doesn't grow or shrink */
.c-sidebar {
width: 280px;
flex: 0 0 280px; /* flex shorthand: no-grow, no-shrink, basis=280px */
min-width: 0;
}

/* Full viewport hero section */
.c-hero {
min-height: 100dvh; /* At least full viewport, grows with content */
display: flex;
align-items: center;
}