Counting columns: a couple neat things you can do
Several weeks ago Westbrook Johnson asked whether it was possible to get the number of columns in an auto-fit/auto-fill grid in CSS. The answer is yes, which I demoed and then found that Ana Tudor had done it a few months earlier (because of course she had :) ).
It takes a bit of algebra, but that’s not the point here. (See Ana’s linked post for full details.) The point is that I recently had reason to use this technique at work to achieve two different things.
Limiting column span to the available number of columns
This is a common problem in grid layouts: you have a bunch of cards, each of which is one column wide. But you have some cards, like featured items, say, that you want to span multiple columns.
“No problem,” you think, “I’ll just throw a grid-column: span 3 on there.”
And it works, as long as there are at least 3 columns. But what happens when there are fewer available columns, like when the viewport (or other grid container) is narrow? Any columns beyond the explicit auto-fit columns are added as implicit columns, sticking out past your nice grid.
Oh no.
What if you could simply say, “span 3 columns or all columns, whichever is smaller.” If you know the number of columns you can!
grid-column: span min(3, var(--column-count));
Now, when there are 3 or more columns, it’ll span 3, but when there are only 2 or 1 columns it’ll only span 2 or 1. No container query required!
See the Pen auto-fit span with column counting by Noah (@noleli) on CodePen.
This sort of control over spanning is a long-requested CSS feature. I suggested this approach (assuming there’s also a column-count() function). We’ll see what path the CSSWG takes :)
Limit columns to a multiple of N
Ok, this isn’t something you can do if you simply know the number of columns. Rather, this is something you can do if you’re calculating the number of columns yourself using the same calculation that auto-fill uses under the hood.
I was working on a design that required only an even number of columns. It seemed hard, but I realized I already had this CSS from doing the first trick.
--column-count: round(
down,
calc((100cqi + var(--gap)) / (var(--min-col-width) + var(--gap))),
1
);
round() is saying to round the results of that calculation down to the nearest 1. It’s the nearest 1 because that last argument is the rounding interval. I changed it to 2, and now it gives a number of columns that are every 2. Cool!
--column-count: round(
down,
calc((100cqi + var(--gap)) / (var(--min-col-width) + var(--gap))),
2
);
See the Pen auto-fit span with column counting by Noah (@noleli) on CodePen.
I wasn’t sure that it would handle the single-column case, but it does. Thinking about it more, I realized that it’s because the result is 0, and a grid template with repeat(0, <whatever>) is invalid. Luckily for us, an invalid column template will result in a single column, which happens to be what we want.
But if you want to be absolutely sure, you could wrap the round() in a max() with one of the arguments being 1. That way, if the result of the calculation rounds down to 0, it’ll be forced to 1.
Counting columns. Calculating columns. It’s neat. That’s all.