Posts from 2025

Masonry, Item Flow, and… GULP?

Published 2 weeks, 6 days past

There’s a layout type that web designers have been using for a long time now, and yet can’t be easily done with CSS: “masonry” layout, sometimes called “you know, like Pinterest does it” layout.  Masonry sits sort of halfway between flexbox and grid layout, which is a big part of why it’s been so hard to formalize.  There are those who think of it as an extension of flexbox, and others who think it’s an extension of grid, and both schools of thought have pretty solid cases.

So that’s been a lot of the discussion, which led to competing blog posts from Google (“Feedback needed: How should we define CSS masonry?”) and Apple (“Help us choose the final syntax for Masonry in CSS”).  Brian and I, with special guest star Rachel Andrew, did an Igalia Chats episode about the debate, which I think is a decent exploration of the pros and cons of each approach for anyone interested.

But then, maybe you don’t actually need to explore the two sides of the debate, because there’s a new proposal in town.  It’s currently being called Item Flow (which I can’t stop hearing sung by Eddie Vedder, please send help) and is explained in some detail in a blog post from the WebKit team.  The short summary is that it takes the flow and packing capabilities from flex and grid and puts them into their own set of properties, along with some new capabilities.

As an example, here’s a thing you can currently do with flexbox:

display: flex;
flex-wrap: wrap;
flex-direction: column;

If the current Item Flow proposals are taken as-is, you could get the same behavior with:

display: flex;
item-wrap: wrap;
item-direction: column;

…or, you could more compactly write it as:

display: flex;
item-flow: wrap column;

Now you might be thinking, okay, this just renames some flex properties to talk about items instead and you also get a shorthand property; big deal.  It actually is a big deal, though, because these item-* properties would apply in grid settingsas well.  In other words, you would be able to say:

display: grid;
item-flow: wrap column;

Hold up.  Item wrapping… in grid?!?  Isn’t that just the same as what grid already does?  Which is an excellent question, and not one that’s actually settled.

However, let’s invert the wrapping in grid contexts to consider an example given in the WebKit article linked earlier, which is that you could specify a single row of grid items that equally divide up the row’s width to size themselves, like so:

display: grid;
grid-auto-columns: 1fr;
item-wrap: nowrap;

In that case, a row of five items would size each item to be one-fifth the width of the row, whereas a row of three items would have each item be one-third the row’s width.  That’s a new thing, and quite interesting to ponder.

The proposal includes the properties item-pack and item-slack, the latter of which makes me grin a little like J.R. “Bob” Dobbs but the former of which I find a lot more interesting.  Consider:

display: flex;
item-wrap: wrap;
item-pack: balance;

This would act with flex items much the way text-wrap: balance acts with words.  If you have six flex items of roughly equal size, they’ll balance between two rows to three-and-three rather than five-and-one.  Even if your flex items are of very different sizes, item-pack: balance would do always automatically its best to get the row lengths as close to equal as possible, whether that’s two rows, three rows, four rows, or however many rows.  Or columns!  This works just as well either way.

There are still debates to be had and details to be worked out, but this new direction does feel fairly promising to me.  It covers all of the current behaviors that flex and grid flowing already permit, plus it solves some longstanding gripes about each layout approach and while also opening some new doors.

The prime example of a new door is the aforementioned masonry layout.  In fact, the previous code example is essentially a true masonry layout (because it resembles the way irregular bricks are laid in a wall).  If we wanted that same behavior, only vertically like Pinterest does it, we could try:

display: flex;
item-direction: column;  /* could also be `flex-direction` */
item-wrap: wrap;         /* could also be `flex-wrap` */
item-pack: balance;

That would be harder to manage, though, since for most writing modes on the web, the width is constrained and the height is not.  In other words, to make that work with flexbox, we’d have to set an explicit height.  We also wouldn’t be able to nail down the number of columns.  Furthermore, that would cause the source order to flow down columns and then jump back to the top of the next column.  So, instead, maybe we’d be able to say:

display: grid;
grid-template-columns: repeat(3,1fr);
item-direction: row;
item-pack: dense balance;

If I’ve read the WebKit article correctly, that would allow Pinterest-style layout with the items actually going across the columns in terms of source order, but being laid out in packed columns (sometimes called “waterfall” layout, which is to say, “masonry” but rotated 90 degrees).

That said, it’s possible I’m wrong in some of the particulars here, and even if I’m not, the proposal is still very much in flux.  Even the property names could change, so values and behaviors are definitely up for debate.

As I pondered that last example, the waterfall/Pinterest layout, I thought: isn’t this visual result essentially what multicolumn layout does?  Not in terms of source order, since multicolumn elements run down one column before starting again at the top of the next.  But that seems an easy enough thing to recreate like so:

display: grid;
grid-template-columns: repeat(3,1fr);
item-direction: column;
item-pack: dense balance;

That’s a balanced set of three equally wide columns, just like in multicol.  I can use gap for the column gaps, so that’s handled.  I wouldn’t be able to set up column rules — at least, not right now, though that may be coming thanks to the Edge team’s gap decorations proposal.  But what I would be able to do, that I can’t now, is vary the width of my multiple columns.  Thus:

display: grid;
grid-template-columns: 60% 40%; /* or 3fr 2fr, idc */
item-direction: column;
item-pack: dense balance;

Is that useful?  I dunno!  It’s certainly not a thing we can do in CSS now, though, and if there’s one thing I’ve learned in the past almost three decades, it’s that a lot of great new ideas come out of adding new layout capabilities.

So, if you’ve made it this far, thanks for reading and I strongly encourage you to go read the WebKit team’s post if you haven’t already (it has more detail and a lovely summary matrix near the end) and think about what this could do for you, or what it looks like it might fall short of making possible for you.

As I’ve said, this feels promising to me, as it enables what we thought was a third layout mode (masonry/waterfall) by enriching and extending the layout modes we already have (flex/grid).  It also feels like this could eventually lead to a Grand Unified Layout Platform — a GULP, if you will — where we don’t even have to say whether a given layout’s display is flex or grid, but instead specify the exact behaviors we want using various item-* properties to get just the right ratio of flexible and grid-like qualities for a given situation.

…or, maybe, it’s already there.  It almost feels like it is, but I haven’t thought about it in enough detail yet to know if there are things it’s missing, and if so, what those might be.  All I can say is, my Web-Sense is tingling, so I’m definitely going to be digging more at this to see what might turn up.  I’d love to hear from all y’all in the comments about what you think!


CSS Naked Day 2025

Published 2 months, 1 day past

I’m a little (okay, a lot) late to it, but meyerweb is now participating in CSS Naked Day  —  I’ve removed the site’s styles, except in cases where pages have embedded CSS, which I’m not going to do a find-and-replace to try to suppress.  So if I embedded a one-off CSS Grid layout, like on the Toolbox page, that will still be in force.  Also, cached files with CSS links could take a little time to clear out.  Otherwise, you should get 1990-style HTML.  Enjoy!

(The site’s design will return tomorrow, or whenever I remember [or am prodded] to restore it.)


CSS Wish List 2025

Published 5 months, 1 day past

Back in 2023, I belatedly jumped on the bandwagon of people posting their CSS wish lists for the coming year.  This year I’m doing all that again, less belatedly! (I didn’t do it last year because I couldn’t even.  Get it?)

I started this post by looking at what I wished for a couple of years ago, and a small handful of my wishes came true:

Note that by “came true”, I mean “reached at least Baseline Newly Available”, not “reached Baseline Universal”; that latter status comes over time.  And more :has() isn’t really a feature you can track, but I do see more people sharing cool :has() tricks and techniques these days, so I’ll take that as a positive signal.

A couple more of my 2023 wishes are on the cusp of coming true:

Those are both in the process of rolling out, and look set to reach Baseline Newly Available before the year is done.  I hope.

That leaves the other half of the 2023 list, none of which has seen much movement.  So those will be the basis of this year’s list, with some new additions.

Hanging punctuation

WebKit has been the sole implementor of this very nice typographic touch for almost a decade now.  The lack of any support by Blink and Gecko is now starting to verge on feeling faintly ridiculous.

Margin and line box trimming

Trim off the leading block margin on the first child in an element, or the trailing block margin of the last child, so they don’t stick out of the element and mess with margin collapsing.  Same thing with block margins on the first and last line boxes in an element.  And then, be able to do similar things with the inline margins of elements and line boxes!  All these things could be ours.

Stroked text

We can already fake text stroking with text-shadow and paint-order, at least in SVG.  I’d love to have a text-stroke property that can be applied to HTML, SVG, and MathML text.  And XML text and any text that CSS is able to style.  It should be at least as powerful as SVG stroking, if not more so.

Expanded attr() support

This has seen some movement specification-wise, but last I checked, no implementation promises or immediate plans.  Here’s what I want to be able to do:

td {width: attr(data-size em, 1px));

<td data-size="5">…</td>

The latest Values and Units module describes this, so fingers crossed it starts to gain some momentum.

Exclusions

Yes, I still want CSS Exclusions, a lot.  They would make some layout hacks a lot less hacky, and open the door for really cool new hacks, by letting you just mark an element as creating a flow exclusions for the content of other elements.  Position an image across two columns of text and set it to exclude, and the text of those columns will flow around or past it like it was a float.  This remains one of the big missing pieces of CSS layout, in my view.  Linked flow regions is another.

Masonry layout

This one is a bit stalled because the basic approach still hasn’t been decided.  Is it part of CSS Grid or its own display type?  It’s a tough call.  There are persuasive arguments for both.  I myself keep flip-flopping on which one I prefer.

Designers want this.  Implementors want this.  In some ways, that’s what makes it so difficult to pick the final syntax and approach: because everyone wants this, everyone wants to make the exactly perfect right choices for now, for the future, and for ease of teaching new developers.  That’s very, very hard.

Grid track and gap styles

Yeah, I still want a Grid equivalent of column-rule, except more full-featured and powerful.  Ideally this would be combined with a way to select individual grid tracks, something like:

.gallery {display: grid;}
.gallery:col-track(4) {gap-rule: 2px solid red;}

…in order to just put a gap rule on that particular column.  I say that would be ideal because then I could push for a way to set the gap value for individual tracks, something like:

.gallery {gap: 1em 2em;}
.gallery:row-track(2) {gap: 2em 0.5em;}

…to change the leading and trailing gaps on just that row.

Custom media queries

This was listed as “Media query variables” in 2023.  With these, you could define a breakpoint set like so:

@custom-media --sm (inline-size <= 25rem);
@custom-media --md (25rem < inline-size <= 50rem);
@custom-media --lg (50rem < inline-size);

body {margin-inline: auto;}
@media (--sm) {body {inline-size: auto;}}
@media (--md) {body {inline-size: min(90vw, 40em);}
@media (--lg) {body {inline-size: min(90vw, 55em);}

In other words, you can use custom media queries as much as you want throughout your CSS, but change their definitions in just one place.  It’s CSS variables, but for media queries!  Let’s do it.

Unprefix all the things

Since we decided to abandon vendor prefixing in favor of feature flags, I want to see anything that’s still prefixed get unprefixed, in all browsers.  Keep the support for the prefixed versions, sure, I don’t care, just let us write the property and value names without the prefixes, please and thank you.

Grab bag

I still would like a way to indicate when a shorthand property is meant for logical rather than physical directions, a way to apply a style sheet to a single element, the ability to add or subtract values from a shorthand without having to rewrite the whole thing, and styles that cross resource boudnaries.  They’re all in the 2023 post.

Okay, that’s my list.  What’s yours?


Browse the Archive