90

What I want to achieve:

Using CSS Grid Layout, to have a page with a right column which size is derived from its content, but only up to 20% of the window width.

How I thought it would work:

div {
  border-style: solid;
}

#container {
  width: 300px;
  height: 300px;
  display: grid;
  grid-template-columns: 1fr minmax(auto, 20%);
}
<div id="container">
  <div>
    some content
  </div>
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus eu leo ac ultrices. Vivamus ornare, orci sed pretium sollicitudin
  </div>
</div>

It looks good, but then when I remove the content of the second div, the left column does not collapse:

div {
  border-style: solid;
}

#container {
  width: 300px;
  height: 300px;
  display: grid;
  grid-template-columns: 1fr minmax(auto, 20%);
}
<div id="container">
  <div>
    some content
  </div>
  <div></div>
</div>

My question:

I was under the impression that since minmax()

(...) defines a size range greater than or equal to min and less than or equal to max.

it would mean that in my case the width is set from auto (= 0 when the div is empty) to 20%. It however stays at 20%. Why is it so?

2
  • I would like to have a page with a right column there are many other ways to achieve this, Is there any specific reason for using grid-template-columns? Commented Aug 2, 2017 at 11:17
  • 2
    @AbhishekPandey: yes, the whole app is based on CSS Grid (I will clarify that in the question)
    – WoJ
    Commented Aug 2, 2017 at 11:21

4 Answers 4

70
+100

"The fit-content function accepts one param, the maximum value. A grid column/row with this property set will still take up as little space as necessary, according to its content, but no more than the maximum value."

See this article: Becoming a CSS Grid Ninja!

You can solve your case while still making use of percentage-based maximums:

div {
  outline: 1px dotted gray;
}

.container {
  width: 300px;
  height: 300px;
  display: grid;
  grid-template-columns: 1fr fit-content(20%);
}

.container div {
  overflow: hidden; /* this needs to be set so that width respects fit-content */
}
<div class="container">
  <div>
    some content
  </div>
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus eu leo ac ultrices. Vivamus ornare, orci sed pretium sollicitudin
  </div>
</div>

<div class="container">
  <div>
    some content
  </div>
  <div></div>
</div>

3
  • 4
    this will cause that column to shrink to fit the content in it
    – lboyel
    Commented Apr 16, 2020 at 15:30
  • 2
    When this answer was posted, fit-content() had more limited browser support. Today, it still requires a prefix in Firefox. caniuse.com/#search=fit-content Commented Apr 30, 2020 at 17:49
  • 2
    Adding overflow: hidden; to the direct children of the grid which are the columns themselves was the trick for me. Commented Sep 21, 2022 at 8:38
29

You've misunderstood minmax function. It first tries to apply maximum value and when that's not possible, it applies minimum.

So to fix your layout, you just need to calculate 20% of your container width, apply it using max-width property for you grid item, and use auto in your grid-template-columns property definition for the second column. Demo:

div {
  outline: 1px dotted gray;
}

.container {
  width: 300px;
  height: 300px;
  display: grid;
  grid-template-columns: 1fr auto;
}

.container > :nth-child(2) {
  max-width: 60px; /* 20% x 300px */
}
<div class="container">
  <div>
    some content
  </div>
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus eu leo ac ultrices. Vivamus ornare, orci sed pretium sollicitudin
  </div>
</div>

<div class="container">
  <div>
    some content
  </div>
  <div></div>
</div>


Update: More flexible solution will be to use fit-content function from this answer.

1
  • 1
    Ah. I read defines a size range greater than or equal to min and less than or equal to max as a continuum from min to max. Your explanation is way more precise. Thank you. In that case max-width will indeed be the way to go (I was hoping to avoid two entries for the same dimension-setting action on the column)
    – WoJ
    Commented Aug 2, 2017 at 14:06
15

You might need to set the max-width on the container itself and let its column set to auto.

div,
aside {
  border-style: solid;
}

#container {
  width: 300px;
  height: 300px;
  display: grid;
  grid-template-columns: 1fr auto;
}

aside {
  max-width: 60px; /* 60px is 20% of 300px*/
  /* max-width:20%; 20% of window's */
  font-size: 0;
  transition: 0.25s;
}

#container:hover aside {
  font-size: 1em;
}
<div id="container">
  <div>
    Hover it to see aside grow till 20% average width
  </div>
  <aside>lets give a try to resize it from content</aside>
</div>

12

Use clamp()

grid-template-columns: clamp(350px, 40%, 500px) auto;

Wheree clamp take three parameters (min, preferred, max)

Not the answer you're looking for? Browse other questions tagged or ask your own question.