Expandable Sections Inside a CSS Grid
I like CSS Grid. I like how, with just some traces of code, we will obtain totally responsive grid layouts, usually with none media queries in any respect. I’m fairly snug wrangling CSS Grid to supply attention-grabbing layouts, whereas conserving the HTML markup clear and easy.
However lately, I used to be introduced with a singular UI conundrum to unravel. Basically, any given grid cell might have a button that might open up one other, bigger space that can also be a part of the grid. However this new bigger grid cell wanted to be:
- proper under the cell that opened it, and
- full width.
Seems there’s a good resolution to it, and within the spirit of CSS Grid itself, it solely entails a few traces of code. On this article, I’ll mix three one-line CSS Grid “methods” to unravel this. No JavaScript wanted in any respect.
An evidence of the particular downside I want to unravel
Right here’s a minimalist UI instance of what I wanted to do:
That is our precise product card grid, as rendered in our Storybook element library:

Every product card wanted a brand new “fast view” button added such that, when clicked, it could:
- dynamically “inject” a brand new full-width card (containing extra detailed product info) instantly under the product card that was clicked,
- with out disrupting the prevailing card grid (i.e. retain the DOM supply order and the visible order of the rendered playing cards within the browser), and
- nonetheless be totally responsive.
Hmmm… was this even doable with our present CSS Grid implementation?
Certainly I would want to resort to JavaScript to re-calculate the cardboard positions, and transfer them round, particularly on browser resize? Proper?
Google was not my buddy. I couldn’t discover something to assist me. Even a search of “fast view” implementations solely resulted in examples that used modals or overlays to render the injected card. In any case, a modal is normally the one selection in conditions like this, because it focuses the person on the brand new content material, without having to disrupt the remainder of the web page.
I slept on the issue, and in the end got here to a workable resolution by combining a few of CSS Grid’s strongest and helpful options.
CSS Grid Trick #1
I used to be already using the primary trick for our default grid system, and the product card grid is a particular occasion of that method. Right here’s some (simplified) code:
.grid { show: grid; hole: 1rem; grid-template-columns: repeat(auto-fit, 20rem);}
The “secret sauce” on this code is the grid-template-columns: repeat(auto-fit, 20rem);
which supplies us a grid with columns (20rem
vast on this instance) which can be organized robotically within the accessible area, wrapping to the subsequent row when there’s not sufficient room.
Inquisitive about auto-fit
vs auto-fill
? Sara Soueidan has written a wonderful explanation of how this works. Sara additionally explains how one can incorporate minmax()
to allow the column widths to “flex” however, for the needs of this text, I needed to outline mounted column widths for simplicity.
CSS Grid Trick #2
Subsequent, I needed to accommodate a brand new full-width card into the grid:
.fullwidth { grid-column: 1 / -1;}
This code works as a result of grid-template-columns
in trick #1 creates an “specific” grid, so it’s doable to outline begin and finish columns for the .fullwidth
card, the place 1 / -1
means “begin in column 1, and span each column as much as the final one.”
Nice. A full-width card injected into the grid. However… now now we have gaps above the full-width card.

CSS Grid Trick #3
Filling the gaps — I’ve accomplished this earlier than with a faux-masonry method:
.grid { grid-auto-flow: dense;}
That’s it! Required structure achieved.
The grid-auto-flow
property controls how the CSS Grid auto-placement algorithm works. On this case, the dense
packing algorithm tries to fills in holes earlier within the grid.
- All our grid columns are the similar width. Dense packing additionally works if the column widths are versatile, for instance, through the use of
minmax(20rem, 1f)
. - All our grid “cells” are the similar peak in every row. That is the default CSS Grid conduct. The grid container implicitly has
align-items: stretch
inflicting cells to occupy 100% of the accessible row peak.
The results of all that is that the holes in our grid are crammed — and the gorgeous half is that the authentic supply order is preserved within the rendered output. That is essential from an accessibility perspective.
See MDN for an entire clarification of how CSS Grid auto-placement works.
The entire resolution
These three mixed methods present a easy structure resolution that requires little or no CSS. No media queries, and no JavaScript wanted.
However… we do nonetheless want JavaScript?
Sure, we do. However not for any structure calculations. It’s purely purposeful for managing the press occasions, focus state, injected card show, and many others.
For demo functions within the prototype, the full-width playing cards have been hard-coded within the HTML of their right areas within the DOM, and the JavaScript merely toggles their show properties.
In a manufacturing setting, nonetheless, the injected card would in all probability be fetched with JavaScript and positioned within the right location. Grid layouts for one thing like merchandise on an eCommerce web site are inclined to have very heavy DOMs, and we need to keep away from unnecessarily bloating the web page weight additional with a lot of further “hidden” content material.
Fast views needs to be thought-about as a progressive enhancement, so if JavaScript fails to load, the person is solely taken to the suitable product particulars web page.
Accessibility concerns
I’m keen about utilizing right semantic HTML markup, including aria-
properties when completely needed, and making certain the UI works with only a keyboard in addition to in a display reader.
So, right here’s a rundown of the concerns that went into making this sample as accessible as doable:
- The product card grid makes use of a
<ul><li>
assemble as a result of we’re displaying an inventory of merchandise. Assistive applied sciences (e.g. display readers) will due to this fact perceive that there’s a relationship between the playing cards, and customers might be knowledgeable what number of objects are within the record. - The product playing cards themselves are
<article>
components, with correct headings, and many others. - The HTML supply order is preserved for the playing cards when the
.fullwidth
card is injected, offering a superb pure tab order into the injected content material, and out once more to the subsequent card. - The entire card grid is wrapped in an
aria-live
area in order that DOM adjustments are introduced to display readers. - Focus administration ensures that the injected card receives keyboard focus, and on closing the cardboard, keyboard focus is returned to the button that initially triggered the cardboard’s visibility.
Though it isn’t demonstrated within the prototype, these further enhancements may very well be added to any manufacturing implementation:
- Make sure the injected card, when targeted, has an applicable label. This may very well be so simple as having a heading as the primary ingredient contained in the content material.
- Bind the ESC key to shut the injected card.
- Scroll the browser window in order that the injected card is totally seen contained in the viewport.
Wrapping up
So, what do you assume?
This may very well be a pleasant different to modals for after we need to reveal further content material, however with out hijacking all the viewport within the course of. This may be attention-grabbing in different conditions as effectively — assume photograph captions in a picture grid, helper textual content, and many others. It would even be an alternative choice to some circumstances the place we’d usually attain for <particulars>
/<abstract>
(as we all know these are solely finest utilized in certain contexts).
Anyway, I’m excited about the way you may use this, and even the way you may method it otherwise. Let me know within the feedback!
Checkout extra Articles on Sayed.CYou
Comments
Post a Comment