A reader wrote in asking specifically how to build this layout in CSS Flexbox:
My answer: That’s not really a layout for CSS Flexbox. You could pull it off if you had to, but you’d need some kind of conceit, like grouping the nav and article together in a parent element (if not more grouping). CSS Grid was born to describe this kind of layout and it will be far easier to work with, not to mention that the browser support for both is largely the same these days.
What do you mean by “Holy Grail”?
See, kids, layout on the web used to be so janky that the incredible simple diagram above was relatively difficult to pull off, particularly if you needed the “columns” there to match heights. I know, ridiculous, but that was the deal. We used super weird hacks to get it done (like huge negative margins paired with positive padding), which evolved over time to cleaner tricks (like background images that mimicked columns). Techniques that did manage to pull it off referred to it as the holy grail. (Just for extra clarity, usually, holy grail meant a three-column layout with content in the middle, but the main point was equal height columns).
CSS is much more robust now, so we can use it without resorting to hacks to do reasonable things, like accomplish this basic layout.
Here it is in CSS Grid
This grid is set up both with grid-template-columns
and grid-template-rows
. This way we can be really specific about where we want these major site sections to fall.
I slipped in some extra stuff
- I had another question come my way the other day about doing 1px lines between grid areas. The trick there is as simple as the parent having a background color and using
gap: 1px;
, so I’ve done that in the demo above. - It’s likely that small screens move down to a single-column layout. I’ve done that at a media query above. Sometimes I use
display: block;
on the parent, turning off the grid, but here I’ve leftgrid
on and reset the columns and rows. This way, we still get the gap, and we can shuffle things around if needed. - Another recent question I was asked about is the subtle “body border” effect you can see in the demo above. I did it about as simple as possible, with a smidge of padding between the body and the grid wrapper. I originally did it between the body and the HTML element, but for full-page grids, I think it’s smarter to use a wrapper div than use the body for the grid. That way, third-party things that inject stuff into the body won’t cause layout weirdness.
Hey, I don’t get this:
grid-column: 2 / 3;
You’ve only defined two columns. Is that a typo or am I missing something about the template syntax? Thanks!
Two columns create three grid lines!
Imagine these pipes as the three grid lines in a 2-column layout.
Starting at column line 2 and ending at column line 2 means “put in the 2nd column.
I know the CSS conventions are different, but I wish they were counting from 0 here.
That way, having 2 columns:
0 – the far left line
1 – middle
2 – far right line
Seems more intuitive.
Would it be possible to put the aside below the article on small screens?
Totally – and ya know what – I just updated the demo to do that. Really, the aside should come after the main content in the markup, and just moving that there worked fine, because of how explicit we were being on desktop about where things go.
Wow, coloring the parent and leaving a gap…. Sounds like we’re back to the peek-a-boo table era, about 20 years ago. I left that behind when it came to printing because browsers had their own settings to control whether or not to print background colors. But I can’t really argue if it works. The containers don’t share a border like two table columns so getting one pixel between them some other way would likely be a chore.
One thing I wish CSS grid could do is shift an article headline centered and full-width, place the article content on the left panel, then the aside on the right panel.
So, in your example, the article’s H1 would somehow be positioned about where the header is, while the article content and aside would be side-by-side.
If you’re trying to stay semantic, I don’t see how that works. You’d have to take the H1 out of the article tag, then place it… where?
edit
Hey Chris,
Thanks for this article!
Question about scrolling in grid.
How would each column scroll overflow content independently (without declaring height) in a full page grid layout? No scroll bar for the or tags, just the column that has overflowing content. How would you do that in grid or would flex be better option for that?
Thanks again!
In order for overflow/scrolling to happen (and make sense) something has to limit the height/width. I’m picturing the parent grid itself taking up the full page, the sections filling the area the best they can with
fr
units, and then you tell those individual sections to scroll as needed.In this example, it would be natural to only have support for scrolling in the main and aside sections. Then you could just add
overflow-y:auto
for those (and only on large display)@media (min-width: 600px) {
.page-main,.page-sidebar {
overflow-y:auto;
}
}
Hi Chris, in which cases do you use negative values, example:
grid-column: 1 / -1;
A hug from Perú
That means: Start on the first Grid Line, and end at whatever the very last Grid Line is.
Thanks a lot!!! I wont’t need to count lines :D
In context of using CSS GRID for layout, is there compatibility, flexibility, and or strategic value/advantage in using classes over HTML elements as selectors, as you did here?
Thanks for your great work!
Very nice article. But how do you make this work in IE11 (sorry, I had to ask). Thanks
Nice, but I’m not really with you in the “support for CSS-grid and Flexbox is about the same”. Caniuse.com tells me prefixed it’s 4.55% resp. 0.66% unsupported — that’s 7x more problematic events!
How did you make the clickable part that expands and collapse the article.
I cant understand what is doing that.
That’s the default behavior of details tag
check this https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details
Hello, Mr. Coyier — I like your design, but I cannot get it to validate on the W3C Validator (https://validator.w3.org). After working on the code, I am down to a single CSS parsing error at the three braces under the “@media” rule. Is there any way to reformat this design so that it can pass a parsing check? Whenever I tried to make changes by moving the braces, the entire appearance of the design fell apart, which is not a criticism. Thank you for reviewing this comment.