The Minimum Content Size In CSS Grid

Ahmad recently encountered an issue where a CSS Grid column grew too large:

.wrapper {
    display: grid;
    grid-template-columns: [main] 1fr [aside] 16em;
    grid-gap: 2em;
}

The main column has a 1fr value. That means it will take the available space minus the sidebar and the gap. However, the minimum content size of a grid item is auto. That means a grid item can expand its width due to long content (In our case, a nested scrolling container).

Coincidentally, this is exactly what Chris wrote about on CSS-Tricks earlier this week. The fix is to use minmax(0, 1fr), so that the minimum content size won’t be auto, preventing this “Grid Blowout”.

The Minimum Content Size In CSS Grid →
You want minmax(10px, 1fr) not 1fr

Sticky CSS Grid Items

Melanie Richards:

If you’ve ever tried to put a sticky item in a grid layout and watched the item scroll away with the rest of the content, you might have come to the conclusion that position: sticky doesn’t work with CSS Grid. Fear not! It is possible to get these two layout concepts working together. All you likely need is one more line of CSS.

The solution is to make it so that the item you want to stick does not stretch out vertically. You can do this by applying align-self: start; on said element, which is the same approach I took when implementing that Smooth Scrolling Sticky ScrollSpy Navigation earlier this year 🙂

Sticky CSS Grid Items →

A Calendar in Three Lines of CSS

Here’s a little CSS Grid use case where a list of days is transformed into a calendar:

See the Pen
Simple Calendar With CSS Grid
by Calendar Tricks (@calendartricks)
on CodePen.

My choice for this CSS calendar tutorial is a list. Why? Because it’s the easiest way to show the amazing capabilities of CSS grid.

With a little CSS extra you can easily make Sunday the last day of the week — a format we prefer here in Europe:

.weekday:nth-child(1) {
  grid-column: 7;
  grid-row: 1;
}

.first-day {
  grid-column-start: 2;
}

See the Pen Simple Calendar With CSS Grid by Bramus (@bramus) on CodePen.

Additionally I’d further adjust the code to have the first day be set by use of a CSS Custom Property. That way the calendar would be able to display any month, without needing any CSS adjustments at all.

A Calendar in Three Lines of CSS →

☝️ If you haven’t by now, you really should learn CSS Grid and read up on its best practices.

A Lightweight Masonry Solution

With Masonry being specced in Grid Layout Module Level 2 – and already being implemented in Firefox – Ana Tudor looked into whipping up a lightweight fallback for browsers that don’t support it.

🤔 Masonry Layout?

Masonry is a grid layout based on columns, as popularized by Pinterest. Unlike other grid layouts, it doesn’t have fixed height rows. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall.

It became easy to implement thanks to the Masonry JavaScript Library.

After first laying out all images in columns, she then calculates the vertical gaps between all items. Each gap is adjusted – using a negative top margin – so that the items shift upwards, after which them end up at their wanted positions.

A Lightweight Masonry Solution →

Modern CSS grid solutions to common layout problems

Kevin Pennekamp (Vycke):

With the addition of grids, we can overcome media-query fatigue. Not only make our CSS more maintainable, but they also improve the user experience. We can let CSS handle the available space. In this article, I will describe three layout implementations that can improve your (personal) website.

The addition of Grid Layout to CSS indeed has changed the way I lay out web pages quite a lot. I don’t event want to go back to using floats (or tables, before that) 😅

Modern CSS grid solutions to common layout problems →

Simple Image Gallery with display: grid; and object-fit: cover;

On the Full Stack Belgium Slack channel, user @Brammm recently asked how to create a simple image gallery.

Anyone have a favorite way of making an image grid with CSS? I’d like one of those “fancy” ones where no matter the aspect ratio of the image, they all have the same gap between them.

While some suggested existing solutions such as React Photo Gallery or photo-stream, I focussed on only the layout-question and suggested a DIY solution using display: grid; and object-fit: cover;.

Using only those those two props it’s really easy to create a grid based gallery.

  • Using display: grid; you create a grid layout. I decided to create a grid of square cells/tiles.
  • As I stretch out each image inside a tile, the images can get deformed. Using object-fit: cover; this can be prevented. Note that you will visually lose some data, as the edges will get clipped, but that was not a concern to @Brammm.

~

Proof Of Concept

Using photos from the birth of my son Noah I knocked up a small small proof of concept in about 10 minutes. Tweaking it a bit more – by adding some CSS Variables into the mix – I eventually landed on this:

See the Pen
Simple Gallery (display: grid; + object-fit: cover;) V1
by Bramus (@bramus)
on CodePen.

💁‍♂️ To create a consistent gap between all items I used the CSS gap property, which replaces grid-gap.

~

Making it feel more dynamic

To make things visually more interesting, and also since some photos are portrait and some landscape, the size of the tiles must differ a bit. With CSS Grid in place it’s really easy to stretch out cells so that they span more than one column or row:

ul.gallery > li.wide {
    grid-column: span 2;
}

ul.gallery > li.wider {
    grid-column: span 3;
}

ul.gallery > li.high {
    grid-row: span 2;
    height: auto; /* to undo the height */
}

With these in place, my gallery started to look like this:

There, looks good, right? 🙂

😋 I know, I cheated a bit as I added the .wide/.high classes onto carefully selected tiles, leaving no gaps in my grid. To workaround potential gaps, one can always use grid-auto-flow: dense;, or use the (still under development) Grid Masonry from the Grid Level 2 spec. Note that in those cases the order of the images will differ from their source order.

~

Going further: Zoom / Lightbox functionality

Where I had originally stopped working on the gallery after that, today I wondered if I could adjust it a bit further and give it the ability to show the images at full screen, in some sort of Lightbox. Still using only CSS it’s possible to show an overlay while pressing+holding a tile.

  • Using the :active pseudo-selector you can know which element is currently being pressed
  • Using position: fixed; you can put content on top of the entire viewport

Combining the two as follows …

ul.gallery > li:active > img {
    position: fixed; /* Position the image on top of the viewport contents */
    z-index: 11;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    object-fit: contain; /* Make sure the image isn't distorted */
    padding: 1vw; /* Add some padding to make it breathe a bit */
    background: rgba(0, 0, 0, 0.8); /* Dim the background */
}

… will get you this:

See the Pen
Simple Gallery (display: grid; + object-fit: cover;) V3 (WIP)
by Bramus (@bramus)
on CodePen.

While the version above does work (on Desktop), there’s a huge problem with it: it’s not (keyboard) accessible at all. In order to give the browser – and therefore user – hints about stuff being clickable we could add a truckload of ARIA attributes or simply use … links. An extra benefit of this approach is that we then start using CSS :target, and eventually create Pure CSS Lightbox.

See the Pen
Simple Gallery (display: grid; + object-fit: cover;) V4b
by Bramus (@bramus)
on CodePen.

It’s not entirely perfect though, when using only the keyboard to navigate, you have to do some trickery to close the Lightbox: after zooming in on an image you’ll have to hit TAB to focus the close link and then hit ENTER to activate it — If only autofocus where available on non-inputs …

As an extra I also added some JS to make the , , and ESC keys work, so that it behaves like a “real” Lightbox. There’s plenty more things I could add to it, but that’s something way beyond the original goal of this post so I left it at that.

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Spacing grid/flexbox items in CSS with the gap property

Flexbox layout with CSS gap applied

The gap property for Flexbox about to land in Chromium 85. It allows you to define the size of the gutters between Grid/Flexbox children.

CSS Grid brought a delightful spacing feature called grid-gap, which quickly became a popular way to put space into layouts. It was easy to fall in love with because it took upon itself so much responsibility with such elegance. Starting in Chromium 85 grid-gap is now just gap, and you can use it with Flexbox. 💪

So no more grid-gap, but simply gap:

.layout {
-  grid-gap: 1em;
+  gap: 1em;
}

~

Why use gap (and not margin)?

Margins in flexbox don’t collapse, so when working with margin you’ll have to adjust the value you’re using. Because of this you’ll also get edges on the inside of your container, as the margin applied on the children is pushing the children inwards. Compare the screenshot below (using margin) with the one at the top of this post (using gap).

Flexbox layout with CSS margin applied
A margin of 1em is applied. Note the broader width between items and the extra blue edge on the container, all due to margins not collapsing.

~

Demo

See the Pen
Flexbox Gap
by Bramus (@bramus)
on CodePen.

Sidenote: @supports vs. Flexbox Gap

In the demo above I wanted to show a warning in browsers that don’t support flexbox gap. For that I tried using @supports, which has proven to be successful before.

.warning {
    display: block;
}

/* Hide warning in case browser supports flexbox gap */
@supports (display: flex) and (gap: 1em) { /* DOES NOT WORK AS INTENDED! */
    .warning {
        display: none;
    }
}

But that’s not really working as intended. In Chromium < 85 – which does not support flexbox gap – the warning is hidden, this because both conditions are evaluated separately:

  • Does Chromium < 85 support display: flex? Yes
  • Does Chromium < 85 support gap: 1em? Yes (from CSS Grid)

This makes me wonder whether re-using property names remains a good idea or not

Perhaps an extension to css-conditional should be made so that it supports a combination of properties — e.g. @supports (display: flex; gap: 1em)?

I’ve filed an issue for the latter.

~

Shorthand

gap is a shorthand for row-gap and column-gap:

.layout {
   display: flex;
   gap: 1em 2em;
}

The first value targets row-gap, the second value column-gap.

~

Browser Support

Firefox has supported it ever since version 63. Chromium is the first engine to follow its lead.

Data on support for the flexbox-gap feature across the major browsers from caniuse.com

💡 Shown above is a dynamic CanIUse.com image, showing an always up-to-date support table. By the time you are reading this browser support might have become better.

“Designing Intrinsic Layouts” by Jen Simmons

Twenty-five years after the web began, we finally have a real toolkit for creating layouts. Combining CSS Grid, Flexbox, Multicolumn, Flow layout and Writing Modes gives us the technical ability to build layouts today without the horrible hacks and compromises of the past.

In this hour-long talk captured live at An Event Apart DC 2019, Jen Simmons walks you through the thinking process of creating accessible & reusable page and component layouts.

Her YouTube Channel Layout Land, which is mentioned at the start, is worth a closer look if you’re looking for more CSS Grid/Flexbox/etc. related videos.

“Designing Intrinsic Layouts” by Jen Simmons – An Event Apart →