A participant row had a wide empty gap on the right. The name and the buttons huddled on the left of a card that was clearly wider than they were, and nothing I wrote seemed to make them fill it.
The rule I had written looked correct:
.participant-main { flex: 1 1 100%; }
On a desktop it worked. On a phone it did nothing at all.
flex-basis is on the main axis
flex: 1 1 100% is shorthand for grow, shrink and
flex-basis: 100%. And flex-basis does not
mean width. It means the starting size along the main
axis.
In flex-direction: row the main axis is horizontal, so
flex-basis behaves like width. That is why it is so easy to think
of it as width — for most of us, most of the time, it is.
Somewhere further up the stylesheet was this:
@media (max-width: 480px) {
.participant-row { flex-direction: column; }
}
On a phone the main axis is vertical. My flex-basis: 100%
was setting the starting height to the full height of the
row. Width was left to the cross axis, where
align-items decides, and it was set to
flex-start — which shrinks children to the width of
their own contents.
Hence the gap. Everything was doing precisely what the CSS asked.
Why it is hard to see
Two things hide it.
It fails silently. There is no warning and nothing looks broken. A row whose children are content-width is a perfectly valid layout, just not the one you wanted.
The two rules are far apart. The
flex-direction: column was in a media query hundreds
of lines away, written by somebody else, at a time when nothing was
using flex-basis. Neither rule is wrong. They are only wrong
together, at one screen width.
Use width when you mean width
.participant-main {
flex: 0 0 auto;
width: 100%;
}
width means the same thing whichever direction the
container happens to be running in. It cannot be flipped by a
media query somewhere else in the file.
The same goes the other way. If you want a fixed height in a column
layout, height says so unambiguously, where
flex-basis quietly depends on a property that is not
written next to it.
A rule of thumb
Use flex-basis when the value genuinely is "along the
flow", whatever that turns out to be — flex: 1 1 0 to
share space evenly, flex: 1 1 240px for cards that
wrap. That is what it is for and it is good at it.
Use width or height when you mean that
specific dimension. Especially in any component whose
flex-direction changes at a breakpoint, because that
is exactly where the two meanings come apart.