Flexbox gotchas and how to debug them. Flexbox is straightforward until it is not – usually when items refuse to shrink, alignment looks wrong, or gaps appear for no obvious reason. The intro series covered the basics; here are the failures you will meet weekly.
The min-width default (flex blowout)
Flex items have an implicit min-width: auto (or min-height: auto in column direction). They will not shrink below their content size unless you override it:
.toolbar {
display: flex;
gap: 1rem;
}
.toolbar__search {
flex: 1;
min-width: 0; /* allow shrinking below content width */
}
.toolbar__search input {
width: 100%;
}
Without min-width: 0, a flex child with long text or a wide input pushes siblings off screen. This is the most common Flexbox bug in the wild.
flex shorthand vs longhand
flex: 1 expands to flex: 1 1 0% – grow, shrink, basis zero. flex: auto uses flex-basis: auto, which sizes from content first. They behave differently:
.equal-columns {
display: flex;
gap: 1rem;
}
.equal-columns > * {
flex: 1 1 0; /* true equal width regardless of content */
}
.content-sized {
flex: 1 1 auto; /* grow to fill, but start from content width */
}
When columns look uneven despite flex: 1, check whether something set flex-basis: auto elsewhere or a child is preventing shrink.
align-items vs align-self vs align-content
Three similarly named properties, three jobs:
align-items– cross-axis alignment of all flex items in the containeralign-self– override for one itemalign-content– spacing between flex lines when the container is taller than one line (multi-line flex only)
.card-row {
display: flex;
flex-wrap: wrap;
align-items: stretch; /* default - cards same height per row */
align-content: flex-start; /* packed to top when extra vertical space */
gap: 1rem;
}
.card-row .card--centred {
align-self: center;
}
People often set align-items: center on the container and wonder why wrapped rows look spaced oddly. Check whether align-content is the property you wanted.
justify-content and margin auto
justify-content: space-between pushes first and last items to the edges. If the last item should sit on the right alone, margin-inline-start: auto on that item is often clearer:
.nav-bar {
display: flex;
align-items: center;
gap: 1rem;
}
.nav-bar__links {
display: flex;
gap: 1rem;
}
.nav-bar__account {
margin-inline-start: auto;
}
Gap vs margin on flex items
gap on flex containers is well supported now. Prefer it over margin hacks on first/last children. If you still support very old browsers, margin on children with a negative margin on the container was the old pattern – you probably do not need it anymore.
Nested flex and height 100%
A flex child with height: 100% only works if every ancestor up the chain has a defined height. Often the fix is making the flex container fill available space:
.page {
display: flex;
flex-direction: column;
min-height: 100dvh;
}
.page__main {
flex: 1; /* grows to fill remaining viewport */
}
100dvh accounts for mobile browser chrome better than 100vh. Use it for full-height shells.
Order and accessibility
order changes visual order without changing DOM order. Screen readers and keyboard tab order follow the DOM. Do not use order to fix a markup problem – fix the markup, or use Grid grid-template-areas with sensible source order.
A debugging checklist
When a flex layout looks wrong, walk through this list:
- Is the container actually
display: flex? - Row or column? Check
flex-direction. - Any item need
min-width: 0ormin-height: 0? - Are you fighting
flex-basisor fixed widths on children? - Multi-line? Consider
align-contentandflex-wrap. - Inspect in DevTools with the flex overlay – see computed flex values per item.
The next tutorial covers logical properties and writing-mode aware UI – the same flex and grid skills, but for layouts that are not strictly left-to-right.

