Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shrink grid items just like flex items in css

Is it possible to shrink grid items just like flex items in css?

Grid items

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.child {
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: center;
  padding: 5px;
  border: 3px solid #a07;
}
<div class="container">
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
</div>

jsfiddle

Flex items

.container {
  display: flex;
  margin-left: -10px;
  flex-flow: row wrap;
}

.child {
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: center;
  padding: 5px;
  border: 3px solid #a07;
  flex: 200px 1 1;
  margin-left: 10px;
  margin-bottom: 10px;
}
<div class="container">
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
</div>

jsfiddle

In a nutshell I can have the following positioning of the elements with the flex above:

enter image description here

While I can not achieve the same behaviour by using a grid layout. Flex layout allows items to shrink on small screen, while grid layout does not allow. At the same time I would like to preserve the behavior that the item will move to the next line with another item only when after such a placement each one of them will be no shorter than a specific size (200px in our case).

I am using grid layout because it allows to preserve the invariant that widths of all the children will be the same. With flex layout the last item will be stretched to the whole line if it will be alone on the line.

like image 943
Yaroslav Trofimov Avatar asked Oct 21 '18 13:10

Yaroslav Trofimov


People also ask

Can a grid item be a Flex container?

You can use them together but not necessarily one the same element. For instance I can place a div in a CSS-Grid parent container (which has display:grid ) but the child div could have display:flex to lay out it's children.

Can CSS Grid replace flexbox?

The main difference is that you can use CSS Grid to create two-dimensional layouts. In contrast, you can only use Flexbox to create one-dimensional layouts. That means you can place components along the X- and Y-axis in CSS Grid and only one axis in Flexbox.

Which is better flex or grid CSS?

CSS grids are for 2D layouts. It works with both rows and columns. Flexbox works better in one dimension only (either rows OR columns). It will be more time saving and helpful if you use both at the same time.

What is the difference between Flex and grids?

Grid and flexbox. The basic difference between CSS Grid Layout and CSS Flexbox Layout is that flexbox was designed for layout in one dimension - either a row or a column. Grid was designed for two-dimensional layout - rows, and columns at the same time.


1 Answers

New solution

An optimized version of the initial solution using min()

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(min(200px,100%), 1fr));
}

.child {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5px;
  border: 3px solid #a07;
}

body {
  margin:0;
}
<div class="container">
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
</div>

Old solution

One solution is to specify a max-width to the child element relying on the viewport unit since percentage values are relative to the size of the track defined by the minmax() and cannot be used. This solution isn't generic and you need to adjust the value depending on each situation.

In you case for example, we can use 100vw since the container is the only element in the body and is taking the whole width:

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.child {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5px;
  border: 3px solid #a07;
  max-width:100vw;
  box-sizing:border-box; /* Don't forget this !*/
}

body {
  margin:0;
}
<div class="container">
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
</div>

In case there is more element or some padding/margin you need to consider them within the max-width calculation:

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.child {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5px;
  border: 3px solid #a07;
  max-width:calc(100vw - 40px); /*we remove the body margin*/
  box-sizing:border-box; 
}

body {
  margin:0 20px; 
}
<div class="container">
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
  <div class="child">
    text
  </div>
</div>

It's like we no more have 2 constraints but 3:

  • The grid cell has a minimum size of 200px
  • The grid cell fill the remain space
  • The element inside the grid cell has a maximum size defined relatively to the screen size. (the shrink constraint we were missing)
like image 162
Temani Afif Avatar answered Oct 14 '22 13:10

Temani Afif