This week I’ve had a couple of scenarios where I’ve needed to build a hero section with a full-width image, a large heading and a translucent sidebar overlaying the image – where the sidebar bleeds to the edge of the viewport but (crucially) the content of the sidebar aligns to what I like to call the “wrapper” grid columns – i.e. the columns of the grid where we actually want to place our content. (I have a whole other post almost written on this!)

This seems to be a fairly common occurrence with the designs that are coming my way these days, and it seems like a prime case for using pseudo-elements (::before or ::after) as child items of the grid.

The markup for my grid looks like this:

  <div class="grid">
    <div class="grid__fig">
    </div>
    <div class="grid__heading">
        <h1>CSS Layout News</h1>
    </div>
    <div class="grid__btn">
        <a href="#0">Subscribe</a>
    </div>
    <aside class="grid__sidebar">
        <ul class="sidebar__list">
            <li class="sidebar__item">...</li>
            <li class="sidebar__item">...</li>
            <li class="sidebar__item">...</li>
        </ul>
    </aside>
</div>

The div with a class of .grid is, unsurprisingly, our parent grid container, which we need to give the property attribute display: grid.

  .grid {
    @media (min-width: 800px) {
        display: grid;
        grid-template-columns: [start] minmax(20px, 1fr) [wrapper-start] repeat(8, var(--col)) [sidebar-start] repeat(4, var(--col)) [wrapper-end] minmax(20px, 1fr) [end];
        grid-template-rows: minmax(3em, 1fr) auto minmax(auto, 1fr);
        grid-gap: var(--gutter);
        min-height: 100vh;
    }
}

Here I’m using CSS Variables to make the code more flexible and maintainable – if you need a primer I wrote a bit about them here. I’m also naming my grid lines to make it easy to place my items.

We have three direct children of the grid container: The background image (.grid__fig), the heading and the sidebar, which can all be placed on the grid. The grid line wrapper-end is where I want the content of the sidebar to end, but the sidebar background needs to end at the the very edge of the viewport – the end grid line. Rather than placing the sidebar like this:

  .grid__sidebar {
    grid-column: sidebar-start / end;
}

I can place it where I want the content to go:

  .grid__sidebar {
    grid-column: span 3 / wrapper-end;
}

(Rather than adding another named grid line, which might make the grid-template-columns property start to get a bit long-winded and confusing – particularly if we have even more items we want to place – I’m just using span 3 to indicate I want it to always span 3 columns, and wrapper-end as the line where I want it to end. It’s really useful to be able to switch the syntax around this way.)

Now I just need to create a pseudo-element for the sidebar background and place it on the grid. In order to act as a grid child item it needs to be a pseudo-element of the grid container, not of a grid child:

  .grid::after {
    content: '';
    display: block;
    grid-column: sidebar-start / end;
    grid-row: 1 / 4;
    background-color: rgba(#f405ed, 0.5);
}

The sidebar background is now in front of the sidebar content, so we just need to tweak the z-index a little:

  .grid__sidebar {
    grid-column: span 3 / wrapper-end;
    ...
    z-index: 1;
}

Here’s the end result (a homage to the magnificent CSS Layout News!):

Resources

As always, there are super smart people who have written about this stuff in-depth: