We’ve covered techniques before for when you want a full-width element within a constrained-width column, like an edge-to-edge image within a narrower column of text. There are loads of techniques.
Perhaps my favorite is this little utility class:
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
That works as long as the column is centered and you don’t mind having to hide overflow-x
on the column (or the body) as this can trigger horizontal overflow otherwise.
There was a little back and forth on some other ideas lately…
Josh Comeau blogged that you could set up a three-column grid, and mostly place content in the middle column, but then have the opportunity to bust out of it:
.wrapper {
display: grid;
grid-template-columns:
1fr
min(65ch, 100%)
1fr;
}
.wrapper > * {
grid-column: 2;
}
.full-bleed {
width: 100%;
grid-column: 1 / -1;
}
I think this is clever. I’d probably use it. But I admit there are bits that feel weird to me. For instance…
- Now everything within the container is a grid element. Not a huge deal, but the elements will behave slightly differently. No margin collapsing, for one.
- You have to apply the default behavior you want to every single element. Rather than elements naturally stacking on top of each other, you have to select them and tell them where to go and let them stack themselves. Feels a little less like just going with the web’s grain. Then you still need a utility class to do the full bleed behavior.
What I really like about the idea is that it gives you this literal grid to work with. For example, your left spacer could be half the width of the right and that’s totally fine. It’s setting up that space to be potentially used, like Ethan talked about in his article on constrained grids.
Kilian Valkhof responded to the article with this idea:
body > *:not(img):not(video) {
position: relative;
max-width: 40rem;
margin: auto;
}
Also very clever. This constrains the width of everything (in whatever container, and it wouldn’t have to be the body) except the elements you want to bust out (which could be a utility class there too, and not necessarily images and videos).
Again, to me, this feeling that I have to select every single element and provide it this fundamental information about layout feels slightly weird. Not like “don’t use it” weird, just not something I’m used to doing. Historically, I’m more comfortable sizing and positioning a container and letting the content in that container lay itself out without much further instruction.
You know what I like the most? That we have so many powerful layout tools in CSS and we have conversations about the pros and cons of pulling off exactly what we’re going for.
One nifty container-busting nugget I discovered a couple of days ago:
I had to create a full-width border on a not-full-width container. Also there was an element inside said container with sticky positioning, precluding using overflow: hidden on the container’s container. I found that instead of using border to create the border (which would give us a horizontal scroll bar), if I used outline the horizontal scroll bar wouldn’t show!
That generally feels like a useful critique (caution) while falling well short of “don’t use this.”
That made me think of one thing to add. It does feel very similar to how I increasingly use the lobotomized owl selector, where I really only want it for direct descendants for specific containers.
Sometimes that’s just applied to a bunch of classes:
Other times, I’ll do it as a utility class:
I wonder if these techniques deserve inclusion in the small niche of “when you actually really do want a universal element selector”.
The issue of everything being a grid child is a bigger concern though. Among other things, no floats.
Very interesting ideas! The first method has the additional bonus that you don’t have to go full bleed. You could also have an image that’s
80vw
wide with a left margin of-40vw
. (you would have to put this in a media query or the image would be actually narrower than the content on screens that aren’t wider than the container though.I recently ended up using the same approach. The downside for me is that there might be elements with inline margins (like lists) which will break, and you’ll have to add exceptions.
Also had to add a hack to the float utility classes:
The first example could benefit from using % instead of vw since vws do include the width of the scrollbar while %s do not. So % will not trigger scrollbars by horizontal overflow.
Interesting technique. I tend to use something similar to the last technique but with a utility class on an extra parent. It basically constrains what you want to constrain (= probably most of your layout) and leave everything else on the default (width: auto), so it fills the container.
The example in this article doesn’t take into account the scrollbar on Windows. To get around this issue please read this comment https://stackoverflow.com/a/66615422/15389306