Width, Height and Sizing

▶ Try It Yourself

Controlling the size of elements precisely — while keeping layouts flexible and responsive — is one of the most practical skills in CSS. The width and height properties are only the start; min-width, max-width, min-height, and modern functions like min(), max(), and fit-content give you fine-grained control over how elements resize across screen sizes. In this lesson you will master all sizing properties and build a robust container pattern used on real production sites.

Sizing Properties

Property Description Common Value
width Sets the width (content area in content-box; full box in border-box) 300px, 50%, 100%
height Sets the height — avoid on text containers; let content define height 200px, 100vh
min-width Element never shrinks below this value 200px, 0 (flex item fix)
max-width Element never grows beyond this value — essential for readability 1200px, 65ch
min-height Element grows with content but never below this 100vh for full-page sections
max-height Caps height — combine with overflow: auto for scrollable areas 400px

Intrinsic Sizing Keywords

Keyword Behaviour Use Case
fit-content Shrinks to content width but never exceeds parent Buttons that don’t stretch full width
min-content Shrinks to the smallest possible width (longest word) Table columns, auto-sizing labels
max-content Grows to fit all content on one line — ignores container Measuring natural element width

Modern Sizing Functions

Function Returns Example
min(a, b) The smaller of two values width: min(100%, 600px)
max(a, b) The larger of two values width: max(300px, 50%)
clamp(min, val, max) val clamped between min and max width: clamp(200px, 50%, 800px)
Note: Avoid setting a fixed height on elements that contain text. Fixed heights clip content when the user zooms in, increases font size, or views the page at a different screen size. Use min-height instead — the element grows with content but never shrinks below the minimum.
Tip: The most useful single line for any page container: width: min(90%, 1200px); margin-inline: auto;. It is fluid below 1200px (90% of viewport), capped at 1200px on large screens, and always centered — all without a single media query.
Warning: width: 100% means 100% of the containing block’s content area. If the parent has padding and you set box-sizing: content-box, a child with width: 100% can still overflow. Always use the border-box reset to avoid this.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Sizing</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; padding: 32px; background: #f8fafc; margin: 0; }

    /* The standard responsive container pattern */
    .container {
      width: min(90%, 1100px);
      margin-inline: auto;
    }

    /* Fixed width — never changes */
    .fixed { width: 240px; background: #fee2e2; padding: 12px 16px; border-radius: 8px; margin-bottom: 12px; }

    /* Fluid width — fills parent */
    .fluid { width: 100%; background: #d1fae5; padding: 12px 16px; border-radius: 8px; margin-bottom: 12px; }

    /* Constrained: fluid up to a max */
    .constrained {
      max-width: 480px;
      background: #ede9fe;
      padding: 12px 16px;
      border-radius: 8px;
      margin-bottom: 12px;
    }

    /* Readable text — max 65ch */
    .readable {
      max-width: 65ch;
      background: #fef9c3;
      padding: 16px 20px;
      border-radius: 8px;
      line-height: 1.7;
      margin-bottom: 12px;
    }

    /* min-height — grows with content, never collapses */
    .min-h {
      min-height: 100px;
      background: #e0f2fe;
      padding: 16px;
      border-radius: 8px;
      margin-bottom: 12px;
    }

    /* Scrollable max-height box */
    .scroll-box {
      max-height: 120px;
      overflow-y: auto;
      background: #f1f5f9;
      border: 1px solid #e2e8f0;
      padding: 12px 16px;
      border-radius: 8px;
      margin-bottom: 12px;
      line-height: 1.6;
      font-size: 0.875rem;
    }

    /* fit-content button — width matches its text */
    .btn-fit {
      display: block;
      width: fit-content;
      padding: 10px 20px;
      background: #4f46e5;
      color: white;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      font-size: 0.9rem;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="fixed">width: 240px (fixed)</div>
    <div class="fluid">width: 100% (fills container)</div>
    <div class="constrained">max-width: 480px (fluid up to 480px)</div>
    <div class="readable">max-width: 65ch — ideal reading line length. This text demonstrates how the character unit creates a comfortable measure that adapts to the current font size automatically.</div>
    <div class="min-h">min-height: 100px — grows with content, never below 100px</div>
    <div class="scroll-box">
      max-height: 120px with overflow-y: auto.
      Line 1. Line 2. Line 3. Line 4. Line 5. Line 6.
      Line 7. Line 8. Line 9. Line 10. Line 11. Line 12.
      Scroll to see more content inside this fixed-height box.
    </div>
    <button class="btn-fit">fit-content button</button>
  </div>
</body>
</html>

How It Works

Step 1 — min() Picks the Smaller Value

width: min(90%, 1100px) evaluates both values and applies the smaller one. On a 800px viewport: 90% = 720px, which is less than 1100px, so width = 720px. On a 1400px viewport: 90% = 1260px, which exceeds 1100px, so width = 1100px. This single declaration replaces width: 90%; max-width: 1100px;.

Step 2 — max-width Prevents Unreadably Long Lines

max-width: 65ch constrains the container to 65 “zero” characters wide in the current font. As the user increases their font size, this limit scales proportionally — always maintaining the ideal reading measure regardless of font size.

Step 3 — min-height Prevents Collapse Without Fixing Height

min-height: 100px ensures the element is at least 100px tall even when empty. As content is added, the element grows beyond 100px naturally. A fixed height: 100px would clip content; min-height grows to accommodate it.

Step 4 — max-height with overflow Creates Scrollable Areas

max-height: 120px; overflow-y: auto caps the visible height at 120px and adds a vertical scrollbar only when content exceeds that limit. This is the pattern for chat boxes, log viewers, and expandable content areas.

Step 5 — fit-content Sizes to Content

width: fit-content on a block-level button makes it shrink to the width of its text content, while still respecting padding. The button does not stretch to fill the parent — it behaves like an inline element’s width while remaining block-level for flow purposes.

Real-World Example: Responsive Page Layout System

/* layout-system.css */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* ── Container variants ── */
.container    { width: min(90%, 1200px); margin-inline: auto; padding-inline: 16px; }
.container-sm { width: min(90%, 720px);  margin-inline: auto; padding-inline: 16px; }
.container-md { width: min(90%, 960px);  margin-inline: auto; padding-inline: 16px; }
.container-lg { width: min(95%, 1440px); margin-inline: auto; padding-inline: 24px; }

/* ── Full-page hero section ── */
.hero {
  min-height: 100vh;         /* at least full screen; grows with content */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 80px 24px;
  background: linear-gradient(135deg, #1e293b, #312e81);
  color: white;
}

.hero h1 {
  font-size: clamp(2rem, 5vw, 4rem);
  max-width: 20ch;           /* prevent super-wide headings */
  margin: 0 auto 24px;
  line-height: 1.1;
}

.hero p {
  font-size: clamp(1rem, 2vw, 1.25rem);
  max-width: 55ch;
  margin: 0 auto 32px;
  opacity: 0.85;
  line-height: 1.7;
}

/* ── Scrollable sidebar panel ── */
.sidebar-panel {
  width: 280px;
  height: 100vh;
  max-height: 100vh;
  overflow-y: auto;
  background: #f8fafc;
  border-right: 1px solid #e2e8f0;
  padding: 24px 0;
  flex-shrink: 0;
}

/* ── Constrained article ── */
.article-body {
  max-width: 72ch;
  margin-inline: auto;
  font-size: 1.05rem;
  line-height: 1.8;
  padding: 48px 24px;
}

/* ── Responsive image ── */
img {
  max-width: 100%;          /* never overflow container */
  height: auto;             /* preserve aspect ratio */
  display: block;
}

Common Mistakes

Mistake 1 — Fixed height on text containers

❌ Wrong — content overflows or gets clipped when text wraps:

.card { height: 200px; overflow: hidden; }
/* When user zooms or font increases, text clips */

✅ Correct — use min-height and let content define the height:

.card { min-height: 200px; } /* grows beyond 200px if content requires */

Mistake 2 — width: 100% causing overflow with padding

❌ Wrong — without border-box, child can overflow parent:

/* No box-sizing reset */
.parent { padding: 20px; }
.child  { width: 100%; padding: 16px; }
/* Child = 100% + 32px padding = overflows parent */

✅ Correct — the global border-box reset prevents this:

*, *::before, *::after { box-sizing: border-box; }
.parent { padding: 20px; }
.child  { width: 100%; padding: 16px; } /* stays within parent */

Mistake 3 — Using max-width without centering

❌ Wrong — constrained to max-width but stuck to the left edge:

.container { max-width: 1200px; }
/* Content is left-aligned — no centering */

✅ Correct — always pair max-width with margin-inline: auto:

.container { max-width: 1200px; margin-inline: auto; }

▶ Try It Yourself

Quick Reference

Property / Function Use Example
width Set element width width: 300px / 100%
max-width Cap maximum width max-width: 65ch
min-width Prevent shrinking below min-width: 0 (flex fix)
min-height Grow with content; never below min-height: 100vh
max-height Cap height; use with overflow max-height: 400px; overflow: auto
min(a, b) Fluid up to a cap width: min(90%, 1200px)
fit-content Size to content, respect parent width: fit-content

🧠 Test Yourself

Which CSS declaration makes a container fluid on small screens but capped at 1200px on large screens, and is centered — all without a media query?





▶ Try It Yourself