I recently worked on a client website that featured an image-based grid divided into thirds. The design for the page included a call-to-action (CTA) that would fill the remaining space in the grid, which meant it could fill one, two, or three grid spaces. Obviously, the text for the CTA wouldn’t make sense to be stacked the same way in the one space as the three spaces, so I needed a solution where I could determine how many spaces this content-aware call-to-action would fill.
The Magic of :nth-of-type()
The trick here lies in the
:nth-of-type() selector, which allows you to apply CSS only if the element matches the query. Because my grid was divided into thirds, I was able to use this selector to determine which position the CTA, which was the last grid item, fits into. In other words:
:nth-of-type(3n+2)means it falls into one of the 2nd, 5th, 8th, etc. spots. For my grid, this element will fall in the middle of the grid, so it will need to take up the last two grid spots in order to fill the remaining space.
:nth-of-type(3n)means it falls into one of the 3rd, 6th, 9th, etc. spots. For my grid, this element will fall into the last position in the grid, so it will only need to take up one spot.
If it falls outside of those selectors, it will take on the base selector’s style, which I have set to take up 100% of the width, or all three grid spots. This, combined with the flexbox stretch rule, ensured each grid item had the proper width and height.
Making it responsive
How you handle making this responsive depends on where your breakpoints are and how you’re handling grids. In my example, each grid item is set to 100% to start, then 50% starting at 40em, and finally 33.333% starting at 64em. I prefer to have the 50% width in there for tablets so that the grid items don’t look too squished or too stretched, especially when dealing with images. To account for this, I have one additional selector for that middle breakpoint:
:nth-of-type(2n). You can see the example in action below:
Adapting for your needs
It would be pretty easy to adapt this to your own website if you wanted to, but there are a few things to keep in mind:
- In order for this layout to work where the CTA can fit into one grid space, the content for the CTA needs to be relatively simple. Anything too large and it likely won’t fit on smaller resolutions.
- If you want to ensure the height matches the other grid items, you could use flexbox, which is what I did with a float fallback. Be sure to consider the browser support.
- It’s important to note that if you are centering your CTA vertically in its box, you will want to remove any absolute positioning any time the CTA spans 100% width. Otherwise, the box will collapse and no more call-to-action!