6

I'd like to create a web page layouts with flexible columns that may be bounded to certain maximum widths. For example a sidebar menu that takes 30% of the available horizontal space but shouldn't grow wider than 200px.

With CSS flexbox, I would go with a solution like this:

.flexbox-layout {
  display: flex;
}
.flexbox-sidebar {
  flex: 1 1 30%;
  max-width: 200px;
  background-color: lightblue;
}
.flexbox-content {
  flex: 1 1 70%;
  background-color: lightgreen;
}
<p>Layout based on CSS flexbox:</p>
<div class="flexbox-layout">
  <div class="flexbox-sidebar">
    <ol>
      <li>Menu item 1</li>
      <li>Menu item 2</li>
      <li>Menu item 3</li>
    </ol>
  </div>
  <div class="flexbox-content">
    <p>Content</p>
  </div>
</div>

This is obviously a minimal example - the real layouts would be far more complex and I want to take advantage of CSS grid features like column/row spanning and auto columns, combined with media queries for responsiveness. Until now, I didn't manage to achieve the same effect of the above flexbox sample with CSS grid:

.grid-layout {
  display: grid;
  grid-template-columns: 30% 70%; /* Max. width for 1st column? */
  grid-template-rows: auto;
}
.grid-sidebar {
  background-color: lightblue;
}
.grid-content {
  background-color: lightgreen;
}
<p>Layout based on CSS grid:</p>
<div class="grid-layout">
  <div class="grid-sidebar">
    <ol>
      <li>Menu item 1</li>
      <li>Menu item 2</li>
      <li>Menu item 3</li>
    </ol>
  </div>
  <div class="grid-content">
    <p>Content</p>
  </div>
</div>

The titles of the following existing questions seemed promising, but in the end address other problems:

Can't use max-width to limit content width in css grid column

How to set the maximum width of a column in CSS Grid Layout?

The minmax(...) function of CSS grid isn't helping either because it doesn't account for relative column widths - at least as far as I tried.

Is there a way to do this with CSS grid at all?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Gyro
  • 61
  • 4
  • You may need to set the container to `grid-template-areas: 30% 70%`. Then set `max-width: 200px` on the grid item itself. Unfortunately, Grid doesn't appear to provide a cleaner method. The `minmax()` function is useless in this case because *max* is ignored when it is less than *min*, computing to *min* in such cases. – Michael Benjamin Nov 21 '17 at 11:58
  • I tried this, too - unfortunately, this doesn't completely work because the grid column itself still continues to grow and pushes the following column and its contents (the green area in my snippets) further to the right. – Gyro Nov 21 '17 at 14:59
  • Ah, yes. That makes sense. Then what about setting the first column to `auto` in the container, and defining both min and max lengths on the item? (And, btw, I think the 2nd column can just be `1fr` on the container.) – Michael Benjamin Nov 21 '17 at 15:02
  • Where would the ratio of 30:70 for the to columns appear in this scenario? And what value would you propose for the item's min-width exactly? – Gyro Nov 22 '17 at 07:24

1 Answers1

2

Feels a bit like a hack, but you can achieve this with:

grid-template-columns: auto minmax(calc(100% - 200px), 70%);


Explanation (https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax)

‘minmax(min, max)’
Defines a size range greater than or equal to min and less than or equal to max. If max < min, then max is ignored and minmax(min,max) is treated as min. As a maximum, a value sets the track’s flex factor; it is invalid as a minimum.

This means, the browser will first try to apply the 30% - 70% values. If the calculation of 100% - 200px is larger then 70% of the whole width it stops growing, which lets the first column exactly take up the space of 200px.

chrona
  • 1,853
  • 14
  • 24
  • 1
    Thank you! With a little tweak, your code seems to work for my specific 2-column-layout from the snippets: `grid-template-columns: minmax(0, 30%) minmax(calc(100% - 200px), 70%);` It now behaves exactly like the flexbox variant. I will try to adapt your solution to an arbitrary number of grid columns with maximum widths and then report back. – Gyro Nov 21 '17 at 15:01