It's been quite a while now since CSS Grid Layout Module Level 1 was released. It's been almost two years since that time all the major browsers so...
For further actions, you may consider blocking this person and/or reporting abuse
Were CSS tables not enough for the job?
display: table
,table-cell
, etc., that is. I know they can't span across rows and columns so they're not as powerful as HTML table layout. :/You know, being completely honest, I hadn't thought of it. But I did just spend a few minutes playing around with it, and my initial impression is that it wouldn't get the job done without requiring a few layers of wrapper
<div>
s and a lot of finicky margin, padding, and border styles, and at that point it's basically just HTML tables, but implemented with<div>
s and a huge amount of CSS.But take this with a grain of salt, because I admittedly have very little experience using
display: table
and its ilk. If you have more experience, please give it a shot, fork one of my pens up there and see what you can do! I'd love to learn about it, I really haven't seen it used very oftenHm. Do you have the HTML
<table>
implementation as a pen? It does let you skip setting anything todisplay:table-row
so at the very least it could skip one nesting level.I used CSS tables more back when I had to fully support IE8, but other than that, they’re mostly obsolete.
So, funny story, I played around with it a bit more, and it tickled my memory enough to remember (because I encountered the same problems again) that I actually had tried to use the
display-table
method when I was implementing basically the same layout for my job. There are a few different ways to approach this, and each has a fatal problem. In all cases, I'm usingdisplay: table
for the<main>
element (so that the table includes all the cards) anddisplay:table-cell
for the counts.If you don't use
display: table-row
anywhere, it sort of just doesn't work. The problem seems to be that the.article-card
element, which isdisplay: block
by default, gets in the middle and breaks the CSS table. Looks like it's true that you can skip explicit table rows in a CSS table, but only if the table cells are direct children of the table element. penIf you make give cards
display: table-row
, the browser wants to put all children on the same line. Which, honestly, produced kind of an interesting layout that I'll keep in mind for future experiments, but doesn't match the mockup. Another issue is that the cards now inherit a lot of the same issues that make working with HTML table rows hard, mainly that rules like margins, borders, and padding aren't supported. penJust to see if I could make it work, I tried giving the article cards
display: contents
and adding wrapper elements around different parts of the card withdisplay: table-row
. Ignoring the problems I mentioned in thedisplay: contents
part of the article, I also ran the problem you mentioned earlier: the absence of acolspan
type rule. The problem is that the header is wider than any count, but ends up in the same column as one of the counts. penCSS Tables are cool, and might even be a valid solution to this sort of situation if the contents of the card could be a single line, using the cards-as-rows approach with some tweaking for style. But if you need multiple rows within your cards with different sized elements on the different rows, the lack of a
colspan
is gonna be a problem 😕Wow, super in-depth follow-up. Thanks for your time!
The lack of borders and padding might/could be fixed with
display:table-row-group
andborder-spacing
.Making the headers full-width might work by leaving them out of the table layout algorithm — leave ’em as
block
, and reorient where the cells start by abusingwriting-mode
. (I’ve done things I’m not proud of.)…but all that’s definitely deep in the weeds of hackiness. (And let’s not talk about
display:table-caption
, which hoists the child box out of the border-box of its parent.)If the CSS Table Layout specification had equivalents to
colspan
androwspan
, we would have been halfway to Grid in 2009. But I can’t blame them for underspecifying the weirdest, most browser-specific layout system ever accidented.Good idea, forgot about
display: table-row-group
, that does make the borders somewhat work again.But leaving the header and
.top
wrapper as a block doesn't fix thecolspan
problem, which is now manifesting in a really weird way... Without checking the spec, it feels like the children of atable-row-group
are in some sort of all-or-nothing pact, where if any one of them is givendisplay: table-row
(and has at least onetable-cell
child?), they all act liketable-row
s withtable-cell
children. But if none of them have a table display type, they act likeblock
s, even if one hastable-cell
children...table-row
: pen.counts
hastable-row
: penYeah, I have mixed feelings about CSS Tables. I almost think it's better that it was kept small and arguably incomplete; maybe its holes helped motivate CSS Grid? Maybe if it had been more complete, people would have continually pointed to tables whenever someone brought up Grid, the same way some currently point to
display: contents
when someone mentions subgrids. But on the other hand, if we're going to have a table layout system anyway, might as well make it fully functional. Maybe they could augment it now to complete the picture.By the way, thanks for the replies, it's been very interesting! I forget that CSS Tables are a thing, and they're worth remembering for those odd corner cases
Thanks for the write-up and for not flaming someone for mentioning CSS tables. Open inquiry has not been the norm and you're doing good work here.
Ken, thanks for giving a great and detailedwrite-up on the need for subgrid.
I've been frustrated by the lack of subgrid on grid frameworks for a while now.
Based on Rachel's post, it looks like 2 dimensional Sub-Grids are coming to Grid level 2. 😁
smashingmagazine.com/2018/07/css-g...
You know, you're right, and the current Working Draft seems to support that as well:
I must be out of date. The last I had heard was from Rachel's article from April, where she said:
But there have been at least 3 versions of the Working Draft released since then, and maybe it's changed back again? If so, that would be incredible!
Turns out you're right! I apparently have been missing the words "able to be" in Rachel's quote above! I've updated the article accordingly. Thanks a zillion for pointing that out to me!
Fabulous writeup. Is it just me or is CSS coming out of a bit of an "awkward phase". Flex-box has been an advancement in a sense, but also sort of seems more like a stepping stone towards these sort of features you're describing.
Yeah, CSS has definitely matured in the last few years. Flexbox was a big step out of the darkness, but I think Grid is what we've all been waiting for since 1996.
That said, Flexbox is an absolutely critical layout method in and of itself, I just think too many people got used to using it for 2D layouts when it's really specifically designed for complex 1D layouts, because it was still so much better than float-based methods.
I recently read something by Rachel Andrew (I forget what) where she says that she wishes Flexbox and Grid had been ready at the same time and released simultaneously, so that people understood that they're meant to be complementary to each other and used in different circumstances. There are lots of things that Flexbox can do very easily that Grid just can't, and obviously the reverse is true as well.
Edit: She says it in the intro to this Smashing article: "What Happens When You Create A Flexbox Flex Container?"
Ken, thanks for giving a detailed write-up on the need for subgrid! I have been frustrated by the lack of subgrid on grid frameworks for a while now.
This caused me to make Grid Wiz. Grid Wiz makes a CSS Grid framework with specified browser support and includes subgrids. The next minor update will probably happen when Grid Level 2 is released so that the code is smaller, but the visual output is the same.
grid-wiz.now.sh/
I think what I really want is the ability to set constraints, like XCode's Interface Builder. Not sure what that would look like in CSS, but it feels simpler and more powerful than needing to create all these different display extensions.
Yeah, I know what you mean. I think we're getting closer to that, especially with the positioning rules that have been added recently, the
align-*
andjustify-*
stuffAmazing post Ken. Coming from WPF background , I am not well versed with CSS yet. I was totally unaware about the grid system of CSS. As recommended in some comment, I started playing with gridgarden and I just loved it. I can relate many of CSS grid concepts to WPF grid control (perks of knowing different systems 😊) Thanks.
What's
grid
? I'm still riding theflexbox
train off into the sunset 🚂Oh my friend, if you've never tried grid, get ready to have your mind blown. IMO, Grid is hands down the single greatest improvement to CSS in a decade, and that includes Flexbox. I mean, don't get me wrong, Flexbox was a huge step forward and is still a great tool and a critical piece of the layout puzzle. But Grid is just... hoo, it's amazing.
The TL;DR is that Grid gives us native support for that thing we've been hacking into our HTML and CSS for like 20 years: proper Grid layout. It's incredibly powerful, and it's literally changing the way we write HTML+CSS. It's hard to overstate the effect it's having.
My recommendation to quickly see the power of Grid:
I've always used Flexbox for the subgrid. Would that solve your problem?
No, the problem is that you can't use Flexbox to align the children of two different parent elements, which is what subgrids allow you to do
Oh I see, you can't do it on any sort of equal widths or percentage widths or anything, it has to flex but be the same. Got ya. An interesting concept. They should invent height = width whilst they are doing it :D
If you plan from the very beginning for a layout without pixel-based wrappers, you can kind of achieve this behavior.
Use the viewport width measurement: vw.
Width: 50vw; Height:50vw;
That works if it's okay to base your container size on the viewport, but I've more often wanted to base the container on its dynamic content, while maintaining a fixed aspect ratio.
There are a few CSS Working Group GitHub issues tracking this feature (#333, #1173), and there's actually a "rough draft" section in the CSS Intrinsic & Extrinsic Sizing Module Level 4 Editor's Draft of a proposed aspect-ratio property to fix this, which I'm pretty excited about.
In the meantime, there is a popular ugly hack that works in certain circumstances (but not all) that relies on the fact that percentages in padding, even top and bottom padding, are always based on the width of an element, so that for example you could make a square with:
...and then a bunch of gross stuff involving absolute positioning and hidden overflows to get the content to sit in the right place... it works, but it's a bit fragile, so use it with caution. CSS Tricks has a great article on it: "Aspect Ratio Boxes"
CSS Layout API Level 1 is also worth a mention: if browser does not provide a layout mode you need, just make/polyfill your own.
Couldn’t you just add another parent grid element inside the card to hold the three icon/number elements?
Nope, you'd have the same problem you have with floats or flexbox: there's nothing tying the columns of those separate child grids together, so their column widths won't stay aligned. If one card had 190 likes, 5 unicorns, and 2 bookmarks, but another had 9 likes, 3 unicorns, and 500 bookmarks, the bookmarks in the second card would end up being much wider than the bookmarks in the first card, and would cross underneath at least the unicorns of the first card, if not the likes.
The whole point is that we need a way to link the columns of two separate grids, and the way to do that is to subgrid them to a shared parent grid
I'm all for subgrids, but for this card example, isn't it possible specify the width of the likes, unicorns, and bookmarks inside its own grid. You wrap those three elements in a div. Give the div a display: grid and grid-template-columns: 1fr 1fr 1fr;. Then wrap each individual icon/ number element in a div and give each of them their respective grid-column property. That would give each column the same width regardless of the content inside. For your card example, you only need a grid on the icon/numbers line, don't you?
The point isn't to give the three counters in the same card the same width, it's to give all counters of the same type across all cards the same width. E.g., all unicorn counters should be as wide as the widest unicorn in any card, but have no affect on the width of any of the bookmarks.
A few people have been confused about what I was trying to accomplish, which makes me think I've explained it poorly... I guess take a look at the mockup at the top of the article to see what I mean. I'll read things over again and see if I can find a way to reword something to make it clearer.
Fantastic article! Can't wait. Quick question, can a child of a subgrid be a grid too? eg: multiple nested grids?
I don't see why not! AFAIK, there's no rules about how deeply you can nest grids.
Remember that
subgrid
is not a new display type or anything; subgrids are still grids withdisplay: grid
, they just have a special value for theirgrid-template-rows
and/orgrid-template-columns
. So anything you can do with regular grids still applies, and grids can clearly have other grids as children, since that's what subgrids are in the first place! 😁It's pretty much the layout system we all need when subgrid arrives. Just nest nest nest all your grids and things should line up beautifully!
I definitely agree, but let me add an addendum: the most amazing thing I have found in using CSS Grid, especially with the addition of
display: contents
, is how much less I find that I actually need to nest things at all.In my experience, if a page implemented with, say, a Bootstrap grid winds up with 10 levels of nesting, it can usually be re-implemented with CSS Grid in like 3 levels of nesting. Templates can be flattened into these clean documents that require nesting only when the semantics call for it, rather than adding a bunch of extra nesting purely in service of layout!
So yes, nested grids with subgrid are basically the final layout puzzle piece the web has been waiting on for 30 years (though IMHO Flexbox is equally as important). But I guess my headline is, don't nest unnecessarily; try to keep everything as flat as possible, because man does it improve readability and maintainability!
This is really well written!
I just love CSS and the last few years have been great. We get to lean on the platform more and more.
Thanks for the compliment!
I agree, I'm very optimistic about the future of the platform!