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>
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>
In a nutshell I can have the following positioning of the elements with the flex above:
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.
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:
200px