Is there a way to have repeating columns that shrink to fit content in CSS Grid?

Viewed 760

Is there a CSS Grid configuration that will repeat (wrap) cells but dynamically shrink columns based on the size of the content, instead of using uniformly sized columns?

For example, here is a configuration using the following rules:

display: grid;
grid-template-columns: repeat(auto-fit, 186px);
grid-auto-columns: min-content;

grid example 1

notice that though the last column has narrower content, it uses the same width as the other columns (186px)

I'd like the columns to shrink to the width of the content, while still wrapping as screen size collapses.

grid example 2

notice the last column is now narrower that the others.

It seems grid-template-columns: repeat(); takes two arguments. The first of which can be auto-fit or auto-fill, but the second must be a specific width. Is there any way to allow this to be automatically computed based on content width?

Here is the codepen I've been playing with to try to achieve this.

Here is the real world scenario as well:

real world example

notice the first column should be wider to fill the content, and the second column should shrink to the content.

I'm familiar with flexbox, but I'm not super familiar with grid yet. Any guidance here would be much appreciated.

1 Answers

You can create repeating columns that to fit content, but for fixed a amount columns. When you use auto-fit, auto-fill grid generates all cells the same width.

In your case in look like 3x3.

display: grid;
grid-template-columns: repeat(3, min-content);

*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: grid;
  place-items: center;
  background-color: hsl(215, 100%, 98%);
  position: relative;
  overflow-x: hidden;
}

.container {
  background-color: lightgray;
  width: 760px;
  display: grid;
  grid-template-columns: repeat(3, min-content);
  resize: horizontal;
  overflow: hidden;
  gap: 5px;
  justify-items: center;
  align-items: center;
}

.child {
  background-color: gray;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

p {
  text-align: center;
}
<div class="container">
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
</div>

It seems grid-template-columns: repeat(); takes two arguments. The first of which can be auto-fit or auto-fill, but the second must be a specific width. Is there any way to allow this to be automatically computed based on content width?

In repeat() function you can use another function minmax() as the second property. But this will not solve your problem, because the first parametr defines minimal width, example 186px and the second how large it will extend.

display: grid;
grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));

*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: grid;
  place-items: center;
  background-color: hsl(215, 100%, 98%);
  position: relative;
  overflow-x: hidden;
}

.container {
  background-color: lightgray;
  width: 760px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));
  resize: horizontal;
  overflow: hidden;
  gap: 5px;
  justify-items: center;
  align-items: center;
}

.child {
  background-color: gray;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

p {
  text-align: center;
}
<div class="container">
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/80x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/120x75" alt="" />
  </div>
  <div class="child">
    <p>title</p>
    <img src="https://via.placeholder.com/160x75" alt="" />
  </div>
</div>

Related