In CSS, an element has width: 400px, max-width: 300px and min-width: 500px. What is its used width, and what is the resolution order between the three properties?
answer
- three properties, one fixed order
- tentative value, then two clamps
- the floor is applied last
- a minimum outranks a maximum
- max-width cannot save an unbreakable string
basics
~20 sThe used width is 500px. CSS computes a tentative width from width, clamps it down to max-width if it exceeds it, then clamps it up to min-width if it falls below — so min-width always wins over max-width, which always wins over width.
solid answer
~40 sThe answer is 500px, and the order is what makes it so. The algorithm computes a tentative size from `width` first. If that exceeds `max-width`, it recomputes with `max-width` as the width. If the result is then smaller than `min-width`, it recomputes again with `min-width`. Because the minimum clamp is applied *last*, it overrides everything, and a `min-width` larger than `max-width` simply wins — this is stated in the spec, not a browser quirk. The practical consequence is that `max-width: 100%` cannot protect you from a `min-width` floor or from an intrinsic minimum, which is the usual reason a box refuses to shrink inside a narrow container. The same order applies to `min-height` and `max-height` in the block axis.
code
css · 6 lines.box {
width: 400px;
max-width: 300px;
min-width: 500px;
}
/* used width: 500px — the minimum clamp is applied last */go deeper
Remember the precedence: min-width beats max-width, and max-width beats width. Be able to read three conflicting declarations and give the used value without hesitating.
Describe the three-step algorithm — tentative value from width, clamp down to max, clamp up to min — and explain that the minimum is applied last so it always wins, by specification rather than by browser quirk.
Use the order to diagnose real overflow: a box that ignores max-width: 100% has a floor, either declared in the cascade or imposed by unbreakable content, and you know to hunt for that floor rather than adding more caps.
Set the convention for how minimums are used across a codebase, since an over-eager min-width in a shared component becomes an un-overridable floor for every consumer and every narrow viewport.
## The algorithm CSS does not treat `width`, `min-width` and `max-width` as three competing opinions to be reconciled. It runs them in a fixed sequence: 1. Compute a **tentative used width** from `width` (which may itself be `auto`, a length, a percentage, or an intrinsic keyword). 2. If that tentative width is **greater than `max-width`**, redo the computation with `max-width` substituted for `width`. 3. If the result of the previous step is **less than `min-width`**, redo the computation with `min-width` substituted for `width`. Each step re-runs the whole width computation, which matters when auto margins are involved — the margins are recalculated against the new width rather than kept from the earlier pass. So for `width: 400px; max-width: 300px; min-width: 500px`: tentative 400, clamped down to 300, then clamped up to 500. Used width: **500px**. The declared `width` never appears in the result at all. ## Why min beats max Applying the minimum last is a deliberate safety choice. A minimum usually exists to keep content from becoming unusable — a control too small to hit, text squeezed to one character per line, an image crushed to nothing. A maximum is usually cosmetic, a readability cap. When the two conflict, CSS protects legibility over aesthetics. ```css .box { width: 400px; max-width: 300px; min-width: 500px; /* wins: used width is 500px */ } ``` This is spec-mandated and identical in every engine, so "different browsers do different things here" is a wrong answer. ## Where it bites in practice **The container-overflow puzzle.** A card sits in a 320px column and spills out. The author reaches for `max-width: 100%` and nothing improves. The reason is nearly always a floor beating the cap: an explicit `min-width` somewhere in the cascade, or an intrinsic minimum imposed by unbreakable content such as a long URL, a wide table, or a `white-space: nowrap` run. Since the floor is applied last, no maximum can override it. You have to remove the floor or lower it — for example `min-width: 0`, or introducing break opportunities in the content. **Percentage caps and the containing block.** `max-width: 100%` resolves against the containing block's width, so it only helps when that block is itself narrow enough. If the containing block is the one overflowing, capping the child at 100% of it changes nothing. **The auto default.** For ordinary block boxes `min-width`'s initial value is `auto`, which resolves to 0, so there is no invisible floor to blame by default. Any floor you hit was declared by someone — check the cascade before assuming a browser bug. ## The block axis `min-height` and `max-height` follow the same three-step order in the block direction: tentative height from `height`, clamp down to `max-height`, clamp up to `min-height`. That is why `min-height: 100vh; max-height: 400px` yields a viewport-tall box, and why `min-height` is the right tool for "at least this tall, taller if the content needs it" while `height` is the wrong one. ## How to say it in an interview Give the number first (500px), then the three-step order, then the reason the order exists, then one real symptom it explains. Naming the intrinsic-minimum case — where the floor is not declared at all but imposed by unbreakable content — is what separates a memorised rule from understanding.
- An element has max-width: 100% but still overflows its container. What are the likely causes?Either a floor beating the cap or a cap resolving against the wrong box. Check for an explicit `min-width` in the cascade, since the minimum clamp is applied last and no maximum can override it. Otherwise the content imposes an intrinsic minimum — a long unbreakable URL, a wide table, a `nowrap` run — or the containing block that the 100% resolves against is itself the one overflowing.
- Does the same ordering apply to height?Yes, symmetrically. A tentative height is computed from `height`, clamped down to `max-height` if it exceeds it, then clamped up to `min-height` if it falls below. That is why `min-height: 100vh` combined with `max-height: 400px` produces a viewport-tall box, and why `min-height` is the right property for "at least this tall, grow if needed".
- Why does the spec re-run the whole width computation at each clamping step rather than just capping the number?Because other parts of the computation depend on the width. Auto margins, in particular, distribute whatever space is left over; if you clamped the width without recomputing, the margins would still reflect the discarded tentative value and the box would sit off-centre. Re-running the step keeps margins, and anything else derived from the used width, consistent with the final value.
saying these in an interview costs you the question
- Says max-width always wins because it is a hard cap
- Claims browsers disagree on which of the three wins
- Thinks the declared width is averaged with the constraints
- Believes min-width defaults to something other than zero for block boxes
- Assumes max-width: 100% guarantees the box never overflows