Thought I’d share a little layout technique I’m using in this latest version of my site. It’s nothing earth-shattering, mind, but I haven’t seen it written up anywhere else, and I’ve found it pretty helpful. Maybe you’ll think so, too.

I’ll start here: most of the responsive layouts I’ve worked on have had a maximum width, a point beyond which the flexible layout stops scaling. And this site’s layout is no exception. Here’s a simplified version of how this new design started, when I first began prototyping:

.layout { display: grid; grid-template-columns: repeat( 8, 1fr ); max-width: 72rem; }

It’s a Grid-powered layout with ten columns: eight columns in the middle, each sized with the fr unit. And the whole grid’s capped to an upper width of 72rem .

And that’s fine! But when I started setting up my portfolio with the new layout, I had a problem: the individual project pages, like this page on the work I did with ProPublica, had a hero graphic at the top that was meant to span the full width of the viewport. In other words, it needed to be wider than the max-width I’d defined.

This isn’t a wildly difficult problem. I could have created a separate block to sit atop the grid, a new layout that wouldn’t share the same constraint. But I realized there was a different way to limit the grid’s upper width—by removing max-width , and creating a constraint column on the right-hand edge:

.layout { display: grid; grid-template-columns: repeat( 8, 1fr ) calc( 100vw - 72rem ) ; }

Inspired in part by CSS Locks, I’m basically using calc() to define a column that’s set to 100vw —the full width of the viewport—minus 72rem , which is the maximum width for my design. This acts as a flexible buffer for my grid: if my grid’s eight columns have a total width of 72rem , then the constraint column will lock into place, and prevent the “main” part of my grid from getting any wider.

Now, this is for a grid that’s left-aligned. But as Mark Llobrera noted, what if you wanted a centered layout that had a constraint column on both sides? In that case, something like this might help:

.layout { display: grid; grid-template-columns: calc( 50vw - 36rem ) repeat( 8, 1fr ) calc( 50vw - 36rem ) ; }

On the left and on the right, I’m using 50vw instead of 100vw , and subtracting 36rem from it—that is, half of our target 72rem maximum width—to provide the buffer I need.

I should note that if the “main” part of your grid has any irregularly-sized columns, or uses grid-gap , you’ll want to account for those values by subtracting them from the maximum width specified in your calc() function. For example, my grid actually has two “gutter” columns on the left and the right, which looks something like this:

.layout { display: grid; grid-template-columns: 1rem repeat( 8, 1fr ) 1rem ; }

To define a constraint column for this grid, I’ll subtract those 2rem from my target maximum width of 72rem :

.layout { display: grid; grid-template-columns: 1rem repeat( 8, 1fr ) 1rem calc( 100vw - 70rem ); }

I’ve found this technique pretty handy, primarily because it gives me the option of creating grid items that extend into that constraint column, creating full-bleed layouts as I need them.