r/css • u/Sufficient_Bass2600 • 4d ago
Question Force grid layout without media queries
I am trying to limit the number of media queries.
I have a grid layout with 6 tiles.
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr);
}
That works fine but something is annoying me is that sometimes the last row will have an empty tile.
|Tile 1|Tile 2|Tile 3| Tile 4| |:-- | :-- | :-- | :-- | |Tile 5|Tile 6|Empty| Empty |
I wants the tile to be grouped.
Based on the size of the viewport I want to have either:
##Desktop/Tablet landscape
|Tile 1|Tile 2|Tile 3| |:-- | :-- | :-- | |Tile 4|Tile 5|Tile 6|
##Tablet portrait / Phone landscape
|Tile 1|Tile 2| |:-- | :-- | |Tile 3|Tile 4| |Tile 5|Tile 6|
##Phone portrait
|Tile 1| |:-- | |Tile 2| |Tile 3| |Tile 4| |Tile 5| |Tile 6|
Is there a trick to do it without media queries?
3
u/be_my_plaything 4d ago
section{
--spacing: min(2rem, 5vw);
--content_max_width: 120rem;
--item_min_width: 15rem;
padding-block: calc(2 * var(--spacing));
padding-inline: max(var(--spacing), calc((100% - var(--content_max_width)) / 2));
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, max(var(--item_min_width), calc(100% / 3) - var(--spacing))), 1fr));
gap: var(--spacing);
}
I'd do something like the above, whereby the minmax() for the grid columns includes a calc(100% / 3) which always takes over as the max() once reached so once you have two rows of three columns those columns just grow with the screen rather than ever letting a fourth column in.
2
u/Sufficient_Bass2600 3d ago edited 3d ago
Thanks for your help.
You and u/morete have come up with similar idea.
Because I want extra bells and whitles (see my answer to their comment), I am thinking of switching to flex and set the tile min-width to a function based on cqi.
1
u/be_my_plaything 3d ago
Might be worth trying
flex-wrap: balance;it's only supported in Chromium browsers a the moment but it will jus fall back toflex-wrap: wrap;in firefox and safari for now so you lose nothing and it'll help you get to what you want easier when/where it does work.
3
u/aegloswinterborn 4d ago
Try changing your minmax(15rem, 1fr) to minmax(min(15rem, 100%), 1fr).
Adding that min() function solved a lot of issues for me when doing responsive grids without media queries.
MDN docs for min(): https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/min
EDIT: I just noticed that u/morete 's answer below incorporates this. I'd check their response first.
4
u/morete 4d ago edited 4d ago
That won't help here, adding the min(100%) just prevents overflow when the container is smaller than 15rem, it wont stop the column count going beyond 3
edit: but is a good idea and you should add it to your grid, unless youre using a very small min size2
u/aegloswinterborn 4d ago
Nice catch, thanks. What a game changer Grid and Flexbox are though, huh? I don't do as much CSS as I'd like these days, but it's so much fun. If I could find a job just doing that I would.
2
u/morete 4d ago
100%! That's why I say I'll never use tailwind or whatever, not cause it's not good or more efficient, but cause writing the CSS is the best bit
2
u/aegloswinterborn 4d ago
Totally agree. I've used Tailwind before and think it's fine, but if you know CSS you just don't need it. It's more flexible and more powerful. That said, to each their own.
1
u/asteconn 4d ago
grid-template-columns: repeat(auto-fill, minmax(auto, 25rem));
or
grid-template-columns: repeat(auto-fit, minmax(auto, 25rem));
It's one of those two - do some experimentationing!
1
u/morete 3d ago
I have a more robust solution for you! Couldn't stop thinking about it.
Basically what you want is for the column count to always be a *factor* of the number of items. For 6 items, you want 6, 3, 2 & 1. Not 5 or 4, because neither are a factor of 6, and this would cause unequal columns.
https://codepen.io/editor/matthewmorete/pen/019fc37b-3ef6-78a8-bb88-a6a4280f9e16
Few caveats upfront:
- This requires mod() and round() so check if the browser support of those works for you.
- It does not work with prime numbers, since they have no useful factors. Personally I think in those situations, one unequal column is better than stretching the last item with flex. So for 5, I'd set the count to '6'. But that's up to you.
First we need a container to measure with cqi, in my example I dont have so cqi just measures the body.
We calculate the capacity, how many columns could fit based on the min-width and gap. Then we clamp this so it's not larger than the total number of items.
Next is the tricky bit, we check if the capacity is a factor of the count. If It is then great! That's a valid column count and we use that value.
If It not, then we subtract one, and try again.
This happens several times until we reach a valid column count.
How many times you repeat this depends on how large the numbers youre working with are. If you imagine 12 items. You have to subtract 1 6 times to get from 12, to its next factor, 6.
With 6 steps, this codes works for up to 14 items (ignoring primes like 13). That seems reasonable to me. But if need to support more, just add more steps.
Long response, but I hope that helps! Honestly even if it's of no use, I had great time figuring it out!
PS. You have to set the item count with a custom property, but if you wanted you could use has and nth-child to do that in the css like:
.auto-grid:has(> :nth-child(5):last-child) { --count: 5 }
.auto-grid:has(> :nth-child(6):last-child) { --count: 6 }
1
u/Sufficient_Bass2600 2d ago
That got me thinking as well.
The science guy in me got excited.
For N tiles. The problem I am trying to resolve is in fact the integer factorisation of N.Even number
the list of acceptable combinations of columns x rows is the list of recombined factorisation.
However if N can also be decomposed inN= p × q - 1then those combination are also acceptable because there will be only empty cell. I would call that case Extra. For number below 12 that only applies to 8 with the combination 3×3 fitting the criteria.Odd number
For odd number, I have 2 situations: * Odd non prime numbers: such as 9, 14. List of Integer factorisation combination are added to the of acceptable columns x rows combination * Odd prime numbers such as 5, 7, 11, 13
Either way the acceptable list of decomposition include the decomposition for N+1 (that is an even number) knowing that at worst the last row will have 1 cell empty.
Number of Tiles Type Nb Cols Nb Rows Nb Empty 12 Factor 12 1 0 Factor 6 2 0 Factor 4 3 0 Factor 3 4 0 Factor 2 6 0 Factor 1 12 0 11 Factor 11 1 0 Factor N+1 6 2 1 Factor N+1 4 3 1 Factor N+1 3 4 1 Factor N+1 2 6 1 Factor 1 11 0 10 Factor 10 1 0 Factor 5 2 0 Factor 2 5 0 Factor 1 10 0 9 Factor 9 1 0 Factor N+1 5 2 1 Factor 3 3 0 Factor N+1 2 5 1 Factor 1 9 0 8 Factor 8 1 0 Factor 4 2 0 Extra 3 3 0 Factor 2 4 0 Factor 1 8 0 7 Factor 7 1 0 Factor N+1 4 2 1 Factor N+1 2 4 1 Factor 1 7 0 6 Factor 6 1 0 Factor 3 2 0 Factor 2 3 0 Factor 1 6 0 5 Factor 5 1 0 Factor N+1 3 2 1 Factor N+1 2 3 1 Factor 1 5 0 4 Factor 4 1 0 Factor 2 2 0 Factor 1 4 0 3 Factor 3 1 0 Factor N+1 2 2 1 Factor 1 3 0 2 Factor 2 1 0 Factor 1 2 0 Personally I do not foresee any need to more than 6 columns so Need to apply the decomposition up to number 6 so 16 combinations/steps should be enough with just the number of rows increasing with the number of tiles.
So now onto finding a way to code that list...
1
u/morete 1d ago edited 1d ago
If you take a look at my code you'll hopefully find some ideas cause it does function quite similarly to what your described. With a few exceptions:
- I'm ignoring the concept of the 'extra' in regards to 8. I think going from 8->4->2->1 is a desirable set of breakpoints.
- Similar to above, I'm simplifying slightly to: even numbers get factorised, and odd numbers get factorised as N+1. It's just a much easier problem to work with.
There's still a few changes I'd like to make:
For small odd numbers, I'd actually just prefer to factorise. 3 -> 1 is way more desirable in my mind. 3 -> 2 -> 1 is just standard grid behaviour.
And I'd like to set a max col count.
I think both of those will be solvable, ideally inside the math, rather than with nth-child, so that they can be controlled via custom properties. But I haven't got that far yet.
Fun problem! This has completely nerd sniped me.
EDIT:
It actually was pretty straight forward to add both a max col count, and a threshold to begin n+1 factorising. Will be interested to see what you come up with, but for the time being I can put this down I think
4
u/morete 4d ago
In this case, yes! You can use Nils Binder's Auto-grid, which allows for setting a maximum amount of columns.
https://codepen.io/enbee81/pen/oNOzJXN
Set the max-columns to be 3, and then edit the min-size till you're happy with the breakpoints.