Intrinsic sizing and the flex algorithm

CSS · Expert · 14 min

Mysterious overflow in flex and grid layouts is almost always an intrinsic-size rule at work.

Boxes have intrinsic sizes derived from their content:

  • min-content: the narrowest the box can be without overflowing, roughly its longest word or widest image.
  • max-content: its width if nothing wrapped.
  • fit-content: max-content, but capped at the available space (and at least min-content).

These keywords work in width, grid-template-columns and elsewhere. width: fit-content shrink-wraps a block, and grid-template-columns: max-content 1fr sizes a label column to its longest label.

The flex algorithm. Each item starts at its flex-basis (or its width, or content size when the basis is auto). Free space is then distributed in proportion to flex-grow, or, if space is negative, removed in proportion to flex-shrink × basis. That's why flex: 1 (basis 0) gives equal columns while flex: auto (basis auto) gives columns proportional to their content.

The automatic minimum. Flex items have min-width: auto by default, which resolves to their min-content size. An item containing a long URL, a <pre> block or a wide table refuses to shrink below that and overflows the container. The fix is min-width: 0 on the flex item (or overflow: hidden, which also sets the automatic minimum to 0). Grid has the same issue: 1fr means minmax(auto, 1fr), so use minmax(0, 1fr) for tracks that must be able to shrink.

Percentages in heights only resolve when the parent has a definite height; flex and grid stretching usually provide one, which is why height: 100% works in some layouts and not others.

Example

/* <div class="row"><aside>Nav</aside><main><pre>very long code line...</pre></main></div> */
.row { display: flex; }
.row aside { flex: 0 0 200px; }
.row main {
  flex: 1;
  min-width: 0;            /* without this, the long <pre> forces overflow */
}
.row pre { overflow-x: auto; }

/* grid: same trap with 1fr = minmax(auto, 1fr) */
.layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); }

/* intrinsic keywords */
.tag { width: fit-content; }                          /* shrink-wrap a block */
.form { display: grid; grid-template-columns: max-content 1fr; gap: 0.5rem 1rem; }

Remember

  • min-content, max-content and fit-content size boxes from their content
  • flex: 1 (basis 0) gives equal columns; flex: auto doesn't
  • Flex items default to min-width: auto; set min-width: 0 to let them shrink
  • Use minmax(0, 1fr) for grid tracks that must shrink

Watch out for

  • Debugging flex overflow by adding overflow: hidden on the container instead of min-width: 0 on the item.

Check yourself

  1. A flex: 1 item contains a wide code block and overflows the row. What is the usual fix?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/min-content

Builds on

Unlocks

Nothing builds on this yet.