I mentioned that Grids are ‘block-like’ by default – with a layout layer defined on the parent. In many ways, Flexbox is more inline-like – not describing a layout, but allowing items to negotiate their own space.
Items flow on a primary axis, that optionally wraps at the edge of the container.
-flow (-direction & -wrap) & gap.container { display: flow-root; }
.item {
float: left;
width: 23.7288136%;
margin-right: 1.6949153%;
}
If you were around for the old days of floated grid layouts, flexbox is a pretty direct 1-to-1 mental model –
.container {
display: flex;
gap: 1em;
}
.item { flex: 1 1 25%; }
but with more flexible boxes. Like floated layouts, any resulting structure on the page comes from each element being individually sized and positioned.
We can revisit the same layout from yesterday, and get a similar result – but this time there’s no internal layout structure and no parental controls. Children have to define their own position in space.
The difference is not intrinsic and extrinsic sizing – both grid and flexbox can mix explicit and fluid sizes. The difference is grid has an internal layout structure that is separate from the size of individual elements.

There is no layout in a flexbox layout, but a layout grid lays out.
With flexbox, there’s no structure, just items taking up space.
Because of that difference, flexbox has fewer alignment options than grid.
align-items or align-self on the cross-axisjustify- against.defaults {
flex-basis: auto; /* starting width */
flex-shrink: 1; /* distribution factor */
flex-grow: 0; /* distribution factor */
}
We get what we asked for: flexible boxes.
auto content basis
We can see what’s happening most clearly in the Firefox flex inspector.
Other browsers provide an overlay on the parent, but only Firefox explains where each item gets its size.
flex
Shorthand Values
initial | auto | none | 1 (any number)
I find that complex flex settings often mean
I should be using grid instead.
That’s not universal,
just a hint to reconsider.
In fact, flexbox was designed with
four special shorthands to cover most common cases.
I especially rely on auto and 1.
initial
Shrink, If Necessary
Same as 0 1 auto
auto
Shrink or Grow
Same as 1 1 auto
none
Don’t Flex
Same as 0 0 auto
Instead of adding growth to the initial value, we can remove shrinking – so boxes don’t flex in either direction.
<number>
Share Space Equally
Same as <number> 1 0
1)0 basisNote that values less than 1 are also useful! Items can stretch to take up half the remaining space, for example.
<grow>Not a strict rule, just a hint!
Andy Bell makes a case for ‘automatic’ layouts using flex-basis as a sort of container-query. It’s very clever, but… if we know the sizes, I prefer clarity. I would only use this if we don’t know the sidebar size in advance.
Otherwise, we might want a container query. So let’s look at them.
All of these tools are designed to handle change and uncertainty in various ways, responding to different conditions, like the size of the viewport…





NO.
Not Ever.
Stop Asking.

Container queries will never be possible on the web. They would cause infinite layout loops.


If we can query the size of the container, and you use that information to change the size of the content…

That would change the size of the container again, and we’re stuck in a loop! But then some folks pointed out…
We’re not dealing with fluid dynamics here. We know that inline elements use the contents for inline size –
And block elements only rely on contents for the block axis. So web layouts generally get their width externally, and allow content to resize the height. Maybe we can measure one axis, and change the other?
Container Size Queries


contain: size | layout | style | paint;
inline-size
For Most Containers
size
For Scroll Containers
container-type: inline-size;
contain: inline-size layout style;main {
container: layout main / inline-size;
}
container-name [/ container-type]?@container layout (min-width: 40em) {
.conditional { /* … */ }
}
@container main (min-width: 40em) {
.conditional { /* … */ }
}
(That would introduce loops!)
(can’t change what you measure!)
No element to measure…

body > :is(header, main, nav, footer) {
container: layout / inline-size;
}
cqw | cqh | cqi | cqb | cqmin | cqmax


Name-Only Container Queries
Container Style Queries
* for now **
** but maybe forever?
Range Syntax in Style Queries
@container scroll-state(stuck) { … }
@container scroll-state(snapped) { … }
@container scroll-state(scrollable) { … }
@container scroll-state(scrolled) { … }
Container Scroll-State Queries


