My favourite line of CSS
Tags: css, cssgrid, grid, webdev
Published: 2020-05-23 04:51:00

---
title: My favourite line of CSS
published: true
description: Space-conscious automatic tiling in one line
tags: css, css-grid, grid, webdev
---

Hey folks.

## This is my favourite line of CSS:

```
  grid-template-columns: repeat( auto-fill, minmax(min(calc(180px + 12vmin), 100%), 1fr));
```

## Here's what it does:

{% codepen https://codepen.io/thedamon/pen/oNjVbVR %}

Not a big deal, eh? just a bunch of squares. But try resizing the codepen window like a weirdo and see how they all just fit! Oooooh.

## Here's why I like it:

It (along with a lil `display: grid`) is a fully responsive grid written with no media queries that keeps a good amount of content on screen for everyone no matter their screen size. 

The design goal solved here is basically: "I want all these things to be about yay big, but I want them to tile evenly into a row, and I want them to get a little smaller as there's less room on the screen".

It's to my brain a simple need but the mathy reality of it is pretty complicated. I really like that I can express it with one line of CSS.

There's a lot of cool stuff in this one line, so let's take it apart to let it shine.

### Vmin?

The black sheep/vermin of the css unit family, but, `vmin` is, in fact, the bomb, diggity.

> 1% of the smaller of the height or width of the viewport

Because here's the problem with sizing everything based on the _width_ of the viewport:

![A large horizontal rectangle with barely any of a large square fitting inside of it. The rest falls off the bottom.](https://dev-to-uploads.s3.amazonaws.com/i/tzfxu4a3x09lllvsj511.png)

Most people do it this way, and it's why the landscape view of a mobile website is usually a bit garbage. Don't forget to be responsive when you're being responsive!

I'm not saying always use `vmin`, but it does elegantly allow you to consider tall narrow windows _and_ short wide windows as similarly restricted space-wise, which we usually forget to do on the internet.

Another cool thing you try at home: a `vmean` unit: `calc({n/2}vh + {n/2}vw)`. This gives you 1% of the _average_ of the viewport height + width — the overall amount of screen space available (This is actually cooler than vmin, but I _mainly_ want to rant about height queries so I'm just tucking it in here.)

### calc(vsomething + pixies)?

The above assumes you're doing some 'responsive scaling' of an object in order to make best use of the screen real estate. Combining a base `px` or `em` size with a percentage of the viewport allows you to make things smoothly scale up as the window gets bigger (and just got super snazzy with [`clamp()`](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp).

This is often used with `font-size` to quickly achieve slightly bigger text on bigger screens that have room for it. [Here's a great overview from a couple days ago](https://css-tricks.com/simplified-fluid-typography/)

How do you choose how many of each unit to use? The higher the `v*`, the more it will scale with the screen. Other than that I do some real sloppy head math as a starting point, then try different values and drag the corner of my screen around all over the place like a weirdo until it looks right. Do you have a better way? 

_(🔥 hot tip: compared to copy, give headings more of the v-units so they scale more dramatically as the screen size changes)_

### min() ?

Min (along with his friend Max Clamp) is new but very handy. (I also edited this article to add it when I realized that it _does_ work inside minmax, and the trick is just _not to have syntax errors_ 🤦‍♂️).

The trick with minmax is that it favors the minimum, so if your value is wider than the screen (say if you want to base it on 400px, but your container is 300px wide) it will stretch outside its bounds.

![The same image of squares from before, but rotated so that the inner square is escaping out the side of the outer square](https://dev-to-uploads.s3.amazonaws.com/i/p2kenfj9xftnw851b4r6.png)

This is a weird decision to me—I never want something to stretch outside its container—but you would have to choose one of min or max to win in a fight and The CSS Lobby chose minimum.

the `min()` function allows us to request the smallest of two values. Inside minmax feels redundant, but it will let you make sure the element never gets too big for its britches, hence `minmax( min(calc(180px + 12vmin), 100%), 1fr)` (the result of the calc but not more than the size of the container).

Great writeup on this [here](https://css-tricks.com/intrinsically-responsive-css-grid-with-minmax-and-min/).

This part is honestly pretty weird and needing it almost makes this _not_ my favourite line of CSS anymore (you don't need it if your base size is small enough. _Technically_ we don't need it here, but it's an important feature to know if you wanna try this at home).

### repeat ( auto-fill ( minmax ( ?

There are probably a bunch of blog posts about this one already. To me it was kinda the most exciting part of grid: not needing to mess around with media queries to just put em in a row and let em wrap when they ought to.

Usually they tell you:

```
repeat(auto-fill, minmax(300px, 1fr))
```

It makes the thing be _at least_ 300px but stretches it out to fill the rest of the row.

Which is pretty cool. But cmon that responsive scaling just dopens it up that extra bit doesn't it? Bigger screens want bigger stuff!

## The old ways

(a.k.a. if you still need to support IE11 😟)

So you could also still do

```css
.tile {
  width: 100%;
}

@media screen and (min-width: 620px){
  width: 50%;
}

@media screen and (min-width: 920px){
  width: calc(100% / 3);
}

@media screen and (min-width: 1150px){
  width: calc(25%);
}
```

(continued up to 4 more times depending on what sizes we're dealing with)

Or you could do

```html
<div class="container">
  <div class="row">
    <div class="tile col-sm-6 col-md-4 col-lg-3">
      ...
    </div>
  </div>
</div>
```

But they have their own problems

 - You have to define potentially arbitrary breakpoints, or arbitrarily use your already existing ones.
 - You would have to buy into the idea of a 12 column grid system even if you don't want to. (Which also means you can only have a number of items per row that is divisible by 12) 
 - Basically, you have to fill your brain with a lot of stuff that isn't "I want em to fit, and be about this size".

My fav line of css is a bit intense (4 nested functions??) but look at it again:

```
  grid-template-columns: repeat( auto-fill, minmax(min(calc(180px + 12vmin), 100%), 1fr));
```

A bit of a mouthful, but it represents the actual task it's solving a lot more directly than the other methods. I know we take grids for granted and many of us live and breathe dividing things into 12, but the fact that you go "this is 6" when you want to have 2 things per row has always felt unnecessarily circuitous to me.

## In the wild

[Peruse my real-world usecase](https://www.radioslipstream.com/covers/) if you want.

## What's missing?

This is great, but I still lament some things about laying things out in CSS Grid that I couldn't figure out a way to do here:

1. I want to have grid-lines between items instead of just gap, and you kinda just can't do that (you'll see this not really working on the codepen).
2. I want to be able for the last line's items to be centered instead of left or right aligned, and you kinda just can't do that.

Let me know if there's a way to do those things and thanks for dropping by!

And since we can nest declarations 4 functions deep in CSS now, is it time to introduce a [pipe operator](https://www.arthurconandoyle.com/sherlockholmes.html)? Sorry wrong link try again. [Pipe operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator)