CSS Overflow

โ–ถ Try It Yourself

CSS overflow controls what happens when an element’s content is larger than its box. The default browser behaviour is to let content spill out โ€” but on real sites you need scrollable panels, truncated text, clipped images, and contained layouts. In this lesson you will master all overflow values, the block formatting context they create, text truncation patterns, and the modern overflow: clip option.

Overflow Property Values

Value Behaviour Scrollbar Common Use Case
visible Default โ€” content spills outside the box None Normal flow content; tooltip anchors
hidden Content beyond the box edge is clipped โ€” invisible None Image cropping, containing floats, decorative clips
scroll Content clipped; scrollbar always present Always (even if not needed) Fixed-width sidebars where scrollbar space must be reserved
auto Content clipped; scrollbar appears only when needed On demand Most scrollable panels โ€” preferred over scroll
clip Like hidden but does NOT create a Block Formatting Context None Clip without layout side effects

overflow-x and overflow-y

Pattern CSS Effect
Horizontal scroll only overflow-x: auto; overflow-y: hidden; Wide tables or code blocks scroll sideways
Vertical scroll only overflow-y: auto; overflow-x: hidden; Scrollable panels โ€” most common use case
Both axes overflow: auto; Scrollable in both directions
Clip one, allow other overflow-x: clip; overflow-y: visible; Clip horizontally without affecting vertical

Text Overflow Patterns

Pattern CSS Required Result
Single-line ellipsis overflow: hidden; white-space: nowrap; text-overflow: ellipsis; Long text ends in “โ€ฆ”
Multi-line clamp display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; Clamps to N lines with “โ€ฆ”
Scroll on overflow overflow-x: auto; white-space: nowrap; Content scrolls horizontally
Note: overflow: hidden and overflow: auto both create a Block Formatting Context (BFC) โ€” the same mechanism that makes display: flow-root contain floats. This means overflow: hidden is an alternative to flow-root for containing floats, but at the cost of potentially clipping overflowing content like tooltips and dropdowns.
Tip: For text truncation with ellipsis, all three properties must be present together: overflow: hidden to clip the text, white-space: nowrap to prevent wrapping to a new line, and text-overflow: ellipsis to show the “โ€ฆ” character. Missing any one of these three means the truncation will not work.
Warning: Avoid placing absolutely-positioned tooltips or dropdown menus inside containers with overflow: hidden โ€” they will be clipped. If you need both containment and visible overflow for children, use a different containment strategy: move the positioned element up the DOM tree so it is not clipped by the overflow: hidden ancestor.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Overflow</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; padding: 32px; background: #f8fafc; }
    .label { font-size: 0.75rem; font-weight: 700; text-transform: uppercase;
             letter-spacing: 0.06em; color: #64748b; margin-bottom: 6px; }
    .demo-box {
      width: 260px;
      height: 80px;
      background: white;
      border: 1px solid #e2e8f0;
      border-radius: 8px;
      padding: 12px 16px;
      margin-bottom: 20px;
      font-size: 0.875rem;
      color: #334155;
    }

    /* overflow: visible โ€” spills out (default) */
    .ov-visible { overflow: visible; }

    /* overflow: hidden โ€” clips content */
    .ov-hidden { overflow: hidden; }

    /* overflow: auto โ€” scrollbar on demand */
    .ov-auto { overflow: auto; }

    /* overflow: scroll โ€” always shows scrollbar */
    .ov-scroll { overflow: scroll; }

    /* Single-line truncation */
    .truncate {
      width: 260px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      background: #ede9fe;
      padding: 10px 14px;
      border-radius: 6px;
      font-size: 0.875rem;
      margin-bottom: 12px;
    }

    /* Multi-line clamp */
    .clamp {
      width: 260px;
      display: -webkit-box;
      -webkit-line-clamp: 3;
      -webkit-box-orient: vertical;
      overflow: hidden;
      background: #d1fae5;
      padding: 10px 14px;
      border-radius: 6px;
      font-size: 0.875rem;
      line-height: 1.5;
      margin-bottom: 12px;
    }

    /* Horizontal scroll โ€” code block pattern */
    .code-scroll {
      width: 260px;
      overflow-x: auto;
      white-space: nowrap;
      background: #1e293b;
      color: #e2e8f0;
      padding: 12px 16px;
      border-radius: 8px;
      font-family: 'Courier New', monospace;
      font-size: 0.8rem;
      margin-bottom: 20px;
    }

    /* Image crop with overflow: hidden */
    .img-crop {
      width: 260px;
      height: 120px;
      overflow: hidden;
      border-radius: 12px;
      position: relative;
      background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 50%, #0891b2 100%);
      margin-bottom: 20px;
    }
    .img-crop-inner {
      width: 130%;
      height: 130%;
      position: absolute;
      top: -15%;
      left: -15%;
      background: inherit;
      border-radius: 50%;
    }
  </style>
</head>
<body>

  <div class="label">overflow: visible (default) โ€” content spills outside</div>
  <div class="demo-box ov-visible">This is a lot of content that is much longer than the 80px height of this box. With overflow: visible it spills right outside the border.</div>

  <div class="label">overflow: hidden โ€” content clipped at boundary</div>
  <div class="demo-box ov-hidden">This is a lot of content that is much longer than the 80px height of this box. With overflow: hidden it is clipped at the border edge.</div>

  <div class="label">overflow: auto โ€” scrollbar appears when needed</div>
  <div class="demo-box ov-auto">This is a lot of content that is much longer than the 80px height of this box. With overflow: auto a scrollbar appears โ€” try scrolling!</div>

  <div class="label">Single-line text-overflow: ellipsis</div>
  <div class="truncate">Very long filename: project-design-system-components-v2-final-approved.sketch</div>

  <div class="label">Multi-line clamp to 3 lines</div>
  <div class="clamp">This is a longer description that would normally span more than three lines of text in a card. The -webkit-line-clamp property truncates it at exactly three lines and adds an ellipsis at the end.</div>

  <div class="label">Horizontal scroll โ€” code block</div>
  <div class="code-scroll">const result = await fetch('https://api.example.com/v1/users?filter=active&sort=created_at&limit=50');</div>

  <div class="label">Image crop with overflow: hidden</div>
  <div class="img-crop"><div class="img-crop-inner"></div></div>

</body>
</html>

How It Works

Step 1 โ€” overflow: visible Is the Default (and Often Surprising)

Without any overflow setting, content that exceeds the element’s bounds paints over neighbouring elements. This is usually not a problem for text that wraps, but for absolutely positioned children or injected content it can cause unexpected overlaps.

Step 2 โ€” overflow: hidden Clips and Creates a BFC

The clipping happens at the element’s padding edge. As a side effect, overflow: hidden creates a Block Formatting Context โ€” the same effect as display: flow-root. This is why it contains floated children. The tradeoff is that any descendant with position: absolute or tooltips will also be clipped.

Step 3 โ€” overflow: auto Only Shows Scrollbar When Needed

On systems with overlay scrollbars (macOS, mobile) the scrollbar appears over content and takes no space. On systems with classic scrollbars (Windows) the scrollbar permanently occupies 15โ€“17px of width. Using overflow: auto means this space is only consumed when content genuinely overflows.

Step 4 โ€” Text Truncation Requires All Three Properties

white-space: nowrap prevents the text from wrapping to a new line. overflow: hidden clips the text that extends beyond the element’s width. text-overflow: ellipsis draws the “โ€ฆ” character at the clip point. All three are required โ€” any one alone is insufficient.

Step 5 โ€” -webkit-line-clamp Clamps to N Lines

Despite the vendor prefix, -webkit-line-clamp is now supported in all browsers. The display: -webkit-box changes the element to a deprecated but still functional box model used specifically for line clamping. It requires overflow: hidden to actually clip the content at the clamped line.

Real-World Example: Card Grid with Clamped Text

/* card-grid.css */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #f8fafc; padding: 40px 24px; }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

.article-card {
  background: white;
  border-radius: 16px;
  border: 1px solid #e2e8f0;
  overflow: hidden;           /* clips the hero image to border-radius */
  display: flex;
  flex-direction: column;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  transition: box-shadow 0.2s;
}
.article-card:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); }

/* Hero image โ€” fills card width, fixed height, cropped */
.card-hero {
  width: 100%;
  height: 180px;
  object-fit: cover;          /* crops image to fill the box */
  display: block;
  flex-shrink: 0;
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
}

.card-body {
  padding: 20px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

/* Category tag */
.card-tag {
  display: inline-flex;
  align-items: center;
  background: #ede9fe;
  color: #4f46e5;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 9999px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 10px;
  width: fit-content;
}

/* Title โ€” clamp to 2 lines */
.card-title {
  font-size: 1rem;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.35;
  margin-bottom: 8px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Description โ€” clamp to 3 lines */
.card-desc {
  font-size: 0.875rem;
  color: #64748b;
  line-height: 1.6;
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 16px;
}

/* Horizontal scrollable code block */
.card-code {
  background: #1e293b;
  border-radius: 6px;
  padding: 10px 14px;
  overflow-x: auto;
  white-space: nowrap;
  font-family: 'Courier New', monospace;
  font-size: 0.78rem;
  color: #e2e8f0;
  margin-bottom: 16px;
}

.card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid #f1f5f9;
}

.card-author {
  font-size: 0.8rem;
  color: #94a3b8;
  /* Single-line truncation for author name */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

Common Mistakes

Mistake 1 โ€” Missing white-space: nowrap for ellipsis

โŒ Wrong โ€” text wraps to new lines instead of truncating with ellipsis:

.title { overflow: hidden; text-overflow: ellipsis; }
/* Without white-space: nowrap, text wraps โ€” ellipsis never triggers */

โœ… Correct โ€” all three properties required together:

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

Mistake 2 โ€” overflow: hidden clipping absolutely positioned children

โŒ Wrong โ€” tooltip inside overflow: hidden parent gets clipped:

.card { overflow: hidden; }
.card .tooltip { position: absolute; top: -40px; } /* clipped! */

โœ… Correct โ€” move the tooltip outside the overflow: hidden container:

<div class="card">Card content</div>
<div class="tooltip">Tooltip outside overflow container</div>

Mistake 3 โ€” Using overflow: scroll causing permanent scrollbar space

โŒ Wrong โ€” scrollbar permanently reserves space even when content fits:

.panel { height: 300px; overflow: scroll; }
/* On Windows, scrollbar takes ~17px regardless of content */

โœ… Correct โ€” use overflow: auto for on-demand scrollbars:

.panel { height: 300px; overflow: auto; }

▶ Try It Yourself

Quick Reference

Value / Pattern Scrollbar Creates BFC Best Use
overflow: visible None No Default; tooltips that must spill out
overflow: hidden None Yes Image crop, float containment, decorative clip
overflow: auto On demand Yes Scrollable panels โ€” most common choice
overflow: scroll Always Yes Reserve scrollbar space to prevent layout shift
overflow: clip None No Clip without BFC side effects
Single-line ellipsis N/A N/A hidden + nowrap + ellipsis (all 3 required)
Multi-line clamp N/A N/A -webkit-line-clamp: N with hidden

🧠 Test Yourself

A card title should show “โ€ฆ” when it overflows one line. You set text-overflow: ellipsis and overflow: hidden but nothing happens. What is missing?





โ–ถ Try It Yourself