DEV Community

Why we need CSS subgrid

Ken Bellows on January 08, 2019

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...
Collapse
 
tigt profile image
Taylor Hunt

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. :/

Collapse
 
kenbellows profile image
Ken Bellows • Edited

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 often

Collapse
 
tigt profile image
Taylor Hunt

Hm. Do you have the HTML <table> implementation as a pen? It does let you skip setting anything to display: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.

Thread Thread
 
kenbellows profile image
Ken Bellows

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 using display: table for the <main> element (so that the table includes all the cards) and display: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 is display: 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. pen

  • If 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. pen

  • Just 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 with display: table-row. Ignoring the problems I mentioned in the display: contents part of the article, I also ran the problem you mentioned earlier: the absence of a colspan 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. pen

CSS 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 😕

Thread Thread
 
tigt profile image
Taylor Hunt

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 and border-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 abusing writing-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 and rowspan, 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.

Thread Thread
 
kenbellows profile image
Ken Bellows

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 the colspan problem, which is now manifesting in a really weird way... Without checking the spec, it feels like the children of a table-row-group are in some sort of all-or-nothing pact, where if any one of them is given display: table-row (and has at least one table-cell child?), they all act like table-rows with table-cell children. But if none of them have a table display type, they act like blocks, even if one has table-cell children...

  • nothing has table-row: pen
  • only .counts has table-row: pen

Yeah, 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.

Thread Thread
 
kenbellows profile image
Ken Bellows

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

Thread Thread
 
sethveale profile image
Seth Veale

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.

Thread Thread
 
hebbybomm profile image
hebbybomm

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.

Collapse
 
dan503 profile image
Daniel Tonon

Based on Rachel's post, it looks like 2 dimensional Sub-Grids are coming to Grid level 2. 😁

smashingmagazine.com/2018/07/css-g...

.parent {
  display: grid;
  grid-template-colums: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
}
.child {
  display: grid;
  grid-column: 1 / 3;
  grid-row: 1 / 3;
  grid-template-rows: subgrid;
  grid-template-columns: subgrid;
}
Collapse
 
kenbellows profile image
Ken Bellows

You know, you're right, and the current Working Draft seems to support that as well:

A grid container that is itself a grid item can defer the definition of its rows and columns to its parent grid container, making it a subgrid.

I must be out of date. The last I had heard was from Rachel's article from April, where she said:

At the CSS Working Group meeting in Berlin we resolved that subgrids should be able to be single axis only, returning them to the original concept rather than the revised one mentioned in my 2016 post.

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!

Collapse
 
kenbellows profile image
Ken Bellows • Edited

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!

Collapse
 
ben profile image
Ben Halpern

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.

Collapse
 
kenbellows profile image
Ken Bellows • Edited

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?"

In my ideal world, CSS Grid and Flexbox would have arrived together, fully formed to make up a layout system for the web. Instead, however, we got Flexbox first and, due to it being better at creating grid-type layouts than floats, we ended up with a lot of Flexbox-based grid systems. In fact, many of the places where people find Flexbox difficult or confusing are really due to this attempt to make it a method for grid layout.

Collapse
 
seejamescode profile image
James Y Rauhut

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/

Collapse
 
joshcheek profile image
Josh Cheek

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.

Collapse
 
kenbellows profile image
Ken Bellows

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-* and justify-* stuff

Collapse
 
nareshravlani profile image
nareshravlani • Edited

Amazing 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.

Collapse
 
johnkreitlow profile image
John Kreitlow

What's grid? I'm still riding the flexbox train off into the sunset 🚂

Collapse
 
kenbellows profile image
Ken Bellows • Edited

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:

  1. Do this: cssgridgarden.com/
  2. Read this: dev.to/kenbellows/css-grid-areas-a...
Collapse
 
uglyeoin profile image
uglyeoin

I've always used Flexbox for the subgrid. Would that solve your problem?

Collapse
 
kenbellows profile image
Ken Bellows

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

Collapse
 
uglyeoin profile image
uglyeoin

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

Thread Thread
 
striptogether profile image
StripTogether

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;

Thread Thread
 
kenbellows profile image
Ken Bellows • Edited

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:

.square {
  width: /* whatever */;
  height: 0;
  padding-bottom: 100%;
}

...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"

Collapse
 
klaster1 profile image
Ilya Borisov

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.

Collapse
 
bwalowitz profile image
Brandon Walowitz

Couldn’t you just add another parent grid element inside the card to hold the three icon/number elements?

Collapse
 
kenbellows profile image
Ken Bellows

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

Collapse
 
bwalowitz profile image
Brandon Walowitz

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?

Thread Thread
 
kenbellows profile image
Ken Bellows

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.

Collapse
 
rctneil profile image
Neil

Fantastic article! Can't wait. Quick question, can a child of a subgrid be a grid too? eg: multiple nested grids?

Collapse
 
kenbellows profile image
Ken Bellows

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 with display: grid, they just have a special value for their grid-template-rows and/or grid-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! 😁

Collapse
 
rctneil profile image
Neil

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!

Thread Thread
 
kenbellows profile image
Ken Bellows

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!

Collapse
 
link2twenty profile image
Andrew Bone

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.

Collapse
 
kenbellows profile image
Ken Bellows

Thanks for the compliment!

I agree, I'm very optimistic about the future of the platform!