dynamic grid, taking size from child element - html

I want to create an dynamic grid class. For my React application.
I want the grid columns 20% bigger then the item thats inside.
I have this solution below. My Problem is, that i have a hover effect on the items. And the hover effect adds a margin to the item. That forces the grid to resize. Is there any solution to make the grid 20% bigger then its elements but at the same time ignoring margin?
.grid-dynamic {
display: grid;
grid-template-columns: repeat(auto-fill, 20%);
grid-auto-rows: 120%;
place-items: center;
}
<div classname="grid-dynamic">
<div classname="item"></div>
<div classname="item"></div>
<div classname="item"></div>
<div classname="item"></div>
...
</div>

Related

Is there a way to make display grid flexible?

I have a group of items that I want to behave like display: flex but in a display: grid layout. What I mean by this is that they are in a grid but the sizes of each grid box are flexible to allow more space for larger titles.
I tried to get the display: grid elements to be more flexible with the css selector grid-auto-columns
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>
#grid {
height: 100px;
display: grid;
grid-template-areas: "a a";
gap: 10px;
grid-auto-columns: 200px;
}
But I would prefer teat the sections remain rigid in size once they are set instead of being truly flexible

How to make a responsive css grid with margins using auto-fit?

I don't NEED to use auto-fit. I just want the code to work.
I want a left margin of 89px, a right margin of 89px, and two items in the middle. So I originally had something like this:
.container3 {
grid-template-columns: repeat(1, 89px 1fr 1fr 89px);
}
The above works, but is not responsive. I need these to break into separate rows when the screen goes smaller. This is the best I can come up with and it doesn't work...
.container3 {
height: 800px;
/* background-color: pink; */
display: grid;
grid-template-columns: repeat(
auto-fit,
89px minmax(300px, 1fr) minmax(300px, 1fr) 89px
);
If you want them to break into separate rows, you can make use of grid breakpoints.Bootstrap Grid options
You can try something like this:
<div class="container3">
<div class="row">
<div class="col-12 col-md-4">First row in xs screen / left column in medium and higher devices</div>
<div class="col-12 col-md-4">Second row in xs screen / middle column in medium and higher devices</div>
<div class="col-12 col-md-4">Last row in xs screen / Right column in medium and higher devices</div>
</div>
</div>

Two equal width columns (where the width is set by the longest one) and a third one fills the remaining space

I want to make a layout like this, using CSS Grid if possible but open to other possibilities:
Basically, I want to have a container .grid that contains 3 elements (input, btn1, btn2). Firstly, btn1 and btn2 width should be the same and is determine by whichever element needs more space (i.e longer content). After that, the remaining element (input) should take all what is left. I came up with this snippet but for sure it cannot work.
.grid {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
<div class="grid">
<input />
<button>Foo</button>
<button>Bar Bar Bar</button>
</div>
What is a good way to achieve this using CSS only?
Use a nested grid container for the buttons.
.grid {
display: grid;
grid-template-columns: 1fr auto; /* see note 1 */
}
.button-container {
display: grid;
grid-template-columns: 1fr 1fr; /* see note 2 */
}
<div class="grid">
<input />
<div class="button-container">
<button>Foo</button>
<button>Bar Bar Bar</button>
</div>
</div>
<br>
<div class="grid">
<input />
<div class="button-container">
<button>Foo</button>
<button>Bar Bar Bar Bar Bar Bar</button>
</div>
</div>
<br>
<div class="grid">
<input />
<div class="button-container">
<button>Foo</button>
<button>Bar Bar Bar Bar Bar Bar Bar Bar Bar</button>
</div>
</div>
Notes:
1fr on the first column consumes all available horizontal space, pinning the second column to the right as much as possible.
1fr 1fr on the nested columns causes the horizontal space in the sub-container to be equally divided, regardless of content width.
Here is a hack (yes a hack!) that relies on the fact that you know the container width.
In the below, I will consider a full-page container (width defined using 100vw)
.grid {
display: grid;
margin:50px 5px;
grid-template-columns:1fr auto;
}
/* they will overlap so the longest one will define the size of auto*/
button {
grid-column:2;
grid-row:1;
}
/* we translate the first one to disable the overlap*/
button:first-of-type {
transform:translateX(-100%);
}
input {
/* 100vw - 10px = width of the grid container
100% is the width of the 1fr
((100vw - 10px) - 100%) will be the width of the buttons
*/
width:calc(100% - ((100vw - 10px) - 100%));
box-sizing:border-box;
}
body {
margin:0;
}
<div class="grid">
<input >
<button>Foo</button>
<button>Bar Bar Bar</button>
</div>

css grid max-width when number of items doesnt fill the page [duplicate]

I'm working with CSS grids to achieve a card grid layout.
But I don't quite know how to tweak the minmax() statement to handle use cases where there aren't enough items to fill a row but still need them to look like cards!
If I replace the max 1fr value with a static 100px or I use a fractional 0.25fr it upsets the scaling at smaller media sizes.
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-column-gap: 17px;
grid-row-gap: 25.5px;
padding-bottom: 25.5px;
}
.card {
background-color: #000;
height: 100px;
}
<div class="wrapper">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
And then if there are only a couple items
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-column-gap: 17px;
grid-row-gap: 25.5px;
padding-bottom: 25.5px;
}
.card {
background-color: #000;
height: 100px;
}
<div class="wrapper">
<div class="card"></div>
<div class="card"></div>
</div>
The key is to use auto-fill instead of auto-fit.
When the repeat() function is set to auto-fit or auto-fill, the grid container creates as many grid tracks (columns/rows) as possible without overflowing the container.
Note that as the grid container is being rendered, the presence of grid items is irrelevant. The container just lays out the columns and rows as instructed, creating grid cells. It doesn't care if the cells are occupied or unoccupied.
With auto-fit, when there are not enough grid items to fill the number of tracks created, those empty tracks are collapsed.
Taking your code as an example, when there aren't enough grid items to fill all the columns in the row, those empty columns are collapsed. The space that was used by the empty columns becomes free space, which is then evenly distributed among existing items. By absorbing the free space, the items grow to fill the entire row.
With auto-fill, everything is the same as auto-fit, except empty tracks are not collapsed. They are preserved. Basically, the grid layout remains fixed, with or without items.
That's the only difference between auto-fill and auto-fit.
Here's an illustration of three grid items with auto-fill:
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
Here's an illustration of three grid items with auto-fit:
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
spec reference: https://www.w3.org/TR/css3-grid-layout/#auto-repeat
In Short,
Auto-fit: Fit entire length of container.
Auto-fill: Doesn't fit entire length of the contaier.
When using minmax() function, the auto-fit keyword will expand the grid items to fill the available space. While auto-fill will keep the available space reserved without altering the grid items width.

Why is auto-fill property of CSS Grid not working in column direction

I am practicing auto-fill property with rows, however, it is not doing what I desire. I want to create rows with height minmax(140px, 200px), but instead get one row with 200px height and the rest are 18px. Why is it happening?
body,
html {
height: 100%;
margin: 0;
}
.wrapper {
display: grid;
grid-template-rows: repeat(auto-fill, minmax(140px, 200px));
}
.wrapper>div:nth-child(odd) {
background-color: red;
}
<div class="wrapper">
<div class="one"> 1 </div>
<div class="one"> 1 </div>
<div class="one"> 1 </div>
<div class="one"> 1 </div>
<div class="one"> 1 </div>
</div>
To wrap grid in vertical direction you have to do a bit more:
specify a height for the grid container so that the grid items know when to wrap,
also specify grid-auto-flow: column (overriding default grid-auto-flow: row)
See demo below (have set height: 100% for illustration):
body,
html {
height: 100%;
margin: 0;
}
.wrapper {
display: grid;
grid-template-rows: repeat(auto-fill, minmax(140px, 200px));
grid-auto-flow: column; /* added */
height: 100%; /* adjust this*/
}
.wrapper>div:nth-child(odd) {
background-color: red;
}
<div class="wrapper">
<div class="one"> 1 </div>
<div class="one"> 2 </div>
<div class="one"> 3 </div>
<div class="one"> 4 </div>
<div class="one"> 5 </div>
</div>
Why specify a height?
Because auto-fill or auto-fit requires a definite dimension in that axis:
7.2.3.2. Repeat-to-fill: auto-fill and auto-fit repetitions
When auto-fill is given as the repetition number, if the grid
container has a definite size or max size in the relevant axis, then
the number of repetitions is the largest possible positive integer
that does not cause the grid to overflow the content box of its grid
container (treating each track as its max track sizing function if
that is definite or as its minimum track sizing function otherwise,
and taking gap into account); if any number of repetitions would
overflow, then 1 repetition. Otherwise, if the grid container has a
definite min size in the relevant axis, the number of repetitions is
the smallest possible positive integer that fulfills that minimum
requirement. Otherwise, the specified track list repeats only once.
Auto-fill in row direction is simpler
Note that here, you don't need to specify a width as display: grid is a block element and block elements have the width of the viewport. You can just use grid-template-columns: repeat(auto-fill, minmax(140px, 200px)) here:
body,
html {
height: 100%;
margin: 0;
}
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 200px));
/*grid-auto-flow: row; --> default (so not needed) */
}
.wrapper>div:nth-child(odd) {
background-color: red;
}
<div class="wrapper">
<div class="one"> 1 </div>
<div class="one"> 2 </div>
<div class="one"> 3 </div>
<div class="one"> 4 </div>
<div class="one"> 5 </div>
</div>
Why grid-auto-flow: column?
See the relevant excerpts from its definition - this property controls how grid items flow in a grid container if they are not explicitly placed:
grid-auto-flow
The grid-auto-flow CSS property controls how the auto-placement
algorithm works, specifying exactly how auto-placed items get flowed
into the grid.
The default value of grid-auto-flow is row which is why you need to override it to column:
row
The auto-placement algorithm places items by filling each row in turn,
adding new rows as necessary. If neither row nor column is provided,
row is assumed.