The solution is named lines.
.content-grid {
display: grid;
grid-template-columns: 1fr [content-start] 1fr [content-end] 1fr;
}
Now we have a 3 column grid where we can center the content in the middle (from content-start to content-end). And now we can use the empty columns for breakout situations.
.content-grid > * {
grid-column: content;
}
Now the content is in the middle column. ‘content‘ is the key for positioning. You can name it anyway you want.
.content-grid {
display: grid;
grid-template-columns: 100px 100px [content-start] 1fr [content-end] 100px 100px;
}
Now we have 2 100px-cols left and right.
To prepare our breakout situation we change the grid to this:
.content-grid {
display: grid;
grid-template-columns:
100px [breakout-start] 100px [content-start] 1fr [content-end] 100px [breakout-end] 100px;
}
We can use the breakout with the breakout class and the section will be 100px wider on both sides.
.content-grid > .breakout {
grid-column: breakout;
}
To be able to make the background full width we need one more adjustment:
.content-grid {
display: grid;
grid-template-columns:
[full-width-start] 100px [breakout-start] 100px [content-start] 1fr [content-end] 100px [breakout-end] 100px [full-width-end];
}
We can use the full width with the full-width class and the section will go from edge to edge:
.content-grid > .full-width {
grid-column: full-width;
}
To finalize the system and make it maintainable:
.content-grid {
--padding-inline: 2rem;
--content-max-width: 70ch;
--breakout-max-width: 85ch;
display: grid;
grid-template-columns:
[full-width-start] minmax(var(--padding-inline), 1fr)
[breakout-start] 0px
/* Use the smaller between those 2 values */
[content-start] min(100% - (var(--padding-inline) * 2), var(--content-max-width)) [content-end]
0px [breakout-end]
minmax(var(--padding-inline). 1fr) [full-width-end];
}
Usage:
.content-grid > :not(.breakout, .full-width),
.full-width > :not(.breakout, .full-width) {
grid-column: content;
}