If you have a limited-width container, say a centered column of text, “breaking out” of that to make a full-width element involves trickery. Perhaps the best trick is the one with left relative positioning and a negative left viewport-based margin. While it has its caveats (e.g. requiring hidden overflow on the body, the container needs to be centered, etc.), at least it’s easy to pull off and everything else in the container just happily goes about its business.
There have been quite a few posts about another way to do this, involving CSS grid:
- Tyler’s “Breaking Out with CSS Grid Layout” which Rachel replied to in a post of her own.
- Rachel covered these full-width elements in another post, “Editorial Design Patterns With CSS Grid And Named Columns”
- Selen Gora’s “Setting the box in container to full width with CSS Grid”
- Bryan Robinson’s “Use CSS Subgrid to layout full-width content stripes in an article template”
The one thing that all these have in common is that they presuppose you have an edge-to-edge grid. I kept thinking to myself, “Do people really use CSS grid for their entire page layout?” Like, essentially body { display: grid; }
ยน? The articles themselves tend to use a class name, but the assumption is that that parent is a full-browser-width container.
I asked around a little, and there was some murmurs of, “yes, I totally do that.” So, cool, it’s a thing people do. My first thought was that that seems like a pain in the butt for a few of reasons:
- A typical “header” and “footer” are full-width, so having to explicitly place them on the grid and stretch them over the correct number of columns and keep that up to date as you fiddle with the columns seems like a lot of work compared to having the header just be a block-level
<header>
sitting at the top (or bottom) of the site. You can still have an edge-to-edge grid in the middle, and have block-level elements above and below. - Having to explicitly place all the items in an “article” into a middle column (e.g.
article > * { grid-columns: 2 / 3; }
just so you can occasionally “stretch” something by spanning more columns just feels weird to me. Like, if 95% of content lives in a centered column, something feels both more robust and relaxed about just putting that content into a parent element that handles the layout, rather than having each individual element needing to place itself onto the grid and the end result is that it appears as if it’s all in a shared parent.
I’m not hating on the technique necessarily, just noting that it makes me feel weird somehow. But I’m probably just old.
-
I’d advise never using
display: grid;
directly on thebody
element. One common problem: browser extensions might place things into the DOM within the body, which would then be placed onto your grid and could screw up your layout. Seen it happen. I’d say it’s just like the React best practice not to bind the whole body, but to use a div child that is effectively the same thing anyway, just scoped to a selector.
As someone who uses this CSS pattern a lot (and is one of the authors mentioned above), I’ll also add one additional drawback to this design pattern. Keep in mind, I LOVE this design pattern ;)
When you use this, you lose access to the
float
property.float
doesn’t work on grid items. Now, you can do some minor workarounds involving adding additional markup, but this design pattern is meant to remove extraneous markup. It’s a trade-off I’m usually willing to make, but I definitely miss floats every once in a while on my blog.The other thing I’ll mention is that I don’t think the articles presuppose a full-width grid container. I actually use this design pattern on my site with a blog post layout where the article content is about 80% on the left with a sidebar on the right. The full-width breakouts only happen inside that 80% which creates some fun design elements.
Regarding the first point, you can automatically span all the columns with:
grid-column: 1/-1;
Ah, yes. We have a designer who gets sick enjoyment from our cries of distress.
Breakouts of all shapes and sizes, she doesn’t descriminate, images/videos that can break from left/right, usually with text or CTA buttons in them that need to remain centred on the main grid.
https://codepen.io/sliver37/pen/eYmjPGj
Requires a browser that supports subgrid for the example. I wish it was more supported.
I tried to build a universal grid structure to allow this very idea, as well as have a centered area. I don’t like trying to mix header/main/footer all in one grid. I see no benefit to that. So I used 3 separate grids.
Here’s the example. It has 6 columns, 2 gutter columns that shrink down to 10px “margin” on each side. The center is then made up of 3 columns.
In retrospect, this is where I should have added 12 columns for a complete layout system, but I never did that.
The –max-content-width is the measurement for making a maximum center column like 1280px or so. Dividing it by 3 gives me an automatic and adjustable column dimensions based on screen width.
I am sure this could be greatly improved, but I found some aspects of it unrefined and I haven’t gotten back to it.
Then to automatically make all the content fit inside this structure.
To make a full width row of content.
I am sure there is something to this, but it did introduce some hurtles, but it sure is easy and fun to use in some circumstances because everything lays out so simply with full width element easy to insert.
Here’s an example:
Always an honor to see one of my articles mentioned on CSS-Tricks!
I’ll admit to being a tad confused by this takeaway from it:
My goal in showing an asymmetric example after introducing the technique was to make it clear this wasn’t the case. Maybe I inadvertently “buried the lede” in terms of what makes the grid-based solution unique?
I simply can’t use Grid for full page layout because it doesn’t work with
height: 100vh;
well on mobile browsers and Flex lets you useflex-grow: 1
on a flex column and it will adjust without using100vh
. I tried to get it work with a Grid inside the Flex column, but there were browser inconsistencies and it only seemed to work in Chrome.I don’t understand why people miss float when you can do the same with
float: left; => justify-self: start;
float: right; => justify-self: end;