We’ve got this pattern on the Set Studio website. It’s three summaries with headings that render in a three column grid which as the viewport reduces in space, automatically stack.
The three column grid part is pretty straightforward, we’re first using this little layout composition.
- Code language
- css
.grid { display: grid; grid-template-columns: repeat( var(--grid-placement, auto-fill), minmax(var(--grid-min-item-size, 16rem), 1fr) ); gap: var(--gutter, var(--space-l)); }
Then we’re hinting the browser to make it a three column grid, where it can, using a CUBE CSS exception.
- Code language
- css
.grid[data-layout='thirds'] { --grid-placement: auto-fit; --grid-min-item-size: clamp(16rem, 33%, 20rem); }
If we just leave the CSS like that (with a little help from our base styles), its looks ok, but the differing heading lengths at narrower viewports creates an awkward reading line. Ideally, each of those summaries will be on a consistent, horizontal reading line.
Demo
We’re using CSS grid already for our layout, so to achieve that consistent horizontal reading line, we can leverage subgrid
.
- Code language
- css
.grid > div { display: grid; grid-template-rows: subgrid; gap: 0; grid-row: span 2; }
Each direct child of our outer grid
layout is a <div>
element so we directly select those with the >
combinator.
Next, we apply display: grid
and set a value of subgrid
to our grid-template-rows
property, instructing this element to inherit the row structure from the parent .grid
. For subgrid
to work, we have to make it a grid element first.
There’s no row structure defined on our outer .grid
layout — it only defines columns — and we’re instructing this child element to inherit the row structure, so we need to define what that row structure looks like with grid-row: span 2
. In human language, that is “take up two consecutive rows in the parent grid, wherever you get placed”.
Now, you might be thinking “we don’t need subgrid
to do that” and you’re right, we don’t need it for a row structure, but what we do need is all of our headings and all of our summaries to participate in the same layout structure as each other to achieve our goal of everything being nice and level.
Let me show you what this looks like without our row structure definition.
Demo
Not great, right? With the row definition though, we’re looking good here.
Demo
The last part of this inner layout to touch on is that we need to remove gap
because there’s a bit too much space here. This is because the parent grid
’s gap
is inherited via subgrid
. Setting in inner layout’s gap
to 0
levels that out for us.
That’s the layout sorted, so let’s add a nice bit of decoration with a border on our summary:
- Code language
- css
.grid p { border-block-start: 1px solid; padding-block-start: var(--space-m); }
We’re only defining the border-width
and border-style
(via the border-block-start
shorthand) because we want the colour to be inherited. Try setting the color
property in your dev tools to see that in action.
Lastly, we’re setting a bit of space above our border with padding-block-start
to keep things nice and neat, visually. With that, we are done.
Demo
Wrapping uppermalink
I’ll be honest, I don’t often find many uses for subgrid
in the work I do, but it’s really handy when I need this level of visual control!
This sort of pattern would have required all sorts of calculations and nasty, specific code in years gone by, but subgrid
has removed the need for all of that now.
Enjoyed this article? You can support us by leaving a tip via Open Collective?