minmax behaviour, flexible css grid - html

Currently, using grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
Behaves as follows: If there are more items than fit in a row (based off the min), then new rows are created. If there are fewer items than the row could take then the items expand to fill the remaining space.
But what if you don't want them to fill the space, but have a maximum size? Setting the item's max-width sort of solves the problem, but then spreads the items across the container. Instead of filling the space, or being spaced across the container, I'd like the items to have a max size and sit next to each other if the grid is wider than the total number of items.
Is this behaviour possible?
Snippet showing grid > total items
html {
font-size: 62.5%;
}
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
grid-template-rows: repeat(2, 20rem);
grid-gap: 1rem;
border: 1px solid lightgrey;
padding: 1rem;
}
.item {
background: lightblue;
// max-width: 35rem;
}
<div class="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
</div>

You should use auto-fill instead of auto-fit. The difference is that auto-fill fills the row with as many columns as it can fit and auto-fit expands the columns to fit them in the available space.
I created this jsfiddle with a solution.
grid-template-columns: repeat(auto-fill, minmax(25rem, 1fr));

Related

Creating a grid layout 3 columns, 1 item spans entire height of 1st column

I want to offset 1 columns contents in CSS. I thought would be as simple as doing the following. Now this does offset the top but it makes the second column match the height of the first inclusive of the margin. How else can I offset the first column?
https://jsbin.com/delobaluga/edit?html,css,output
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 20px;
}
.grid .item:first-child {
margin-top: 105px;
}
<div class='grid'>
<div class='item'></div>
<div class='item'></div>
</div>
If you want to offset the first column while keeping the height of the second column unaffected, you can use padding instead of margin on the first column. Padding affects the element's content area, while margin affects the surrounding area, so if you add padding to the first column, it will increase its size and offset the content inside it, but won't affect the height of the second column.
Here your code with this improvement:
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 20px;
}
.grid .item:first-child {
padding-top: 105px;
}
<div class='grid'>
<div class='item'></div>
<div class='item'></div>
</div>

A grid layout with size, defined by size of its cells and gap

I have the following layout:
<div class="mygrid">
<div class="first cell"></div>
<div class="second cell"></div>
<div class="third cell"></div>
<div class="fourth cell"></div>
</div>
The styles are:
.mygrid
{
background-color: gray;
display: grid;
gap: 1px;
grid-template-columns: repeat(2, auto);
grid-template-rows: repeat(2, auto);
grid-template-areas:
'first second'
'third fourth';
}
.cell
{
width: 40px;
height: 40px;
background-color: green;
}
(Here's the sample on CodePen).
I expected the grid container (div.mygrid) would have column width and row height defined by maximal dimensions of the cells, because I set them as repeat(2, auto). So, the total size would be 81px x 81px (40px * 2 + 1px of gap). But it actually has the same width as its parent.
How to achieve the described behavior?
Also, when I explicitly set the size of div.mygrid (width: 200px;), the gap property is ignored and the cells are distributed evenly. Why and how to fix this?

Align overflowing container to right of grid cell, not grid row

I have a 12 column grid. Column 1 is a month number and column 2-12 are a text title.
However, the font of the number is so large that it was forcing the column width to be larger than the other columns. I'm trying to keep equal column width while also not letting the contents of the first column overlap the title text.
To do this, I was hoping I could just align the contents of the first column to the right edge of the column... alas, it's not working.
Codepen
Here is the columns:
and this is the div inside column 1 that is holding the H3 number text:
How can I get the .date-container div to align it's right edge, to the right edge of it's parent column?
and of course, some code:
.month-title-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(2, auto);
column-gap: 10px;
}
.date-container{
position: absolute;
}
.date-container h1{
position: relative;
text-align: end;
}
.col-1
{
grid-column-end: span 1;
}
<div class="month-title-grid">
<div class="col-12"><h3 class="lightbrown">January</h3></div>
<div class="col-1"><div class="date-container"><h1 class="lightbrown">01</h1></div></div>
<div class="col-11"><h2 class="darkbrown">IT'S COMPLICATED</h2>
Now that i understood this really should fix your problem, it works in your codepen for me.
.month-title-grid {
display: grid;
/*this will help to keep the columns even*/
grid-template-columns: repeat( 12, minmax(50px, 1fr) );
grid-template-rows: repeat(2, auto);
column-gap: 10px;
}
.col-1
{
/*this will force the overflow to the left*/
direction: rtl;
grid-column-end: span 1;
}
<div class="month-title-grid">
<div class="col-12"><h3 class="lightbrown">January</h3></div>
<div class="col-1"><div class="date-container"><h1 class="lightbrown">01</h1></div></div>
<div class="col-11"><h2 class="darkbrown">IT'S COMPLICATED</h2>

CSS Grid Template Columns Repeat No More Than X Times

I have a layout in which multiple items will be aligned in a grid. Let's use the following as an example:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
.grid-item {
display: block;
width: 100%;
background-color: purple;
color: white;
text-align: center;
padding: 30px 5px;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
In the above code, the grid will repeat 3 columns per row and each item will expand to 1/3 of the row width. The problem is that in a responsive situation, the grid will always repeat 3 columns.
If I change the repeat value to auto-fit and adjust the column sizing to use minmax I can control how the page scales down and reduce the col width and count to some sane value. So adjusted code would look something like this:
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px,1fr));
grid-gap: 20px;
}
.grid-item {
display: block;
width: 100%;
background-color: teal;
color: white;
text-align: center;
padding: 30px 5px;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
This works well scaling down, but here is where I am having problems - I want to cap the number of cols at 3 when the page scales up. Ideally, I would like to use minmax in the repeat directive like this:
grid-template-columns: repeat( minmax(1, 3), minmax(300px, 1fr) );
but of course this doesn't work. How can I limit repeat to 3 columns while still maintaining my downscale settings with auto-fit?
I don't think you can set a max-limit on the number of columns using auto-fit or auto-fill. By definition, they will create as many tracks as can fit in the container without overflowing:
ยง 7.2.2.2. Repeat-to-fill: auto-fill and auto-fit
repetitions
When auto-fill [or auto-fit] is given as the repetition number ...
then the number of repetitions is the largest possible positive
integer that does not cause the grid to overflow its grid container.
And you can't set the max value of the minmax() function to 30%, because then you run into the same problem you had in your first example:
grid-template-columns: repeat(3, 1fr)
Namely, the column tracks become fixed on all screen sizes, and the layout is not responsive.
I understand that you're looking for a solution that doesn't require media queries. But if you want to use grid layout, I think media queries may be your best bet.
Otherwise, consider flex layout:
jsFiddle demo
.grid-container {
display: flex;
flex-wrap: wrap;
}
.grid-item {
width: 30%;
min-width: 300px;
flex-grow: 1;
background-color: teal;
color: white;
text-align: center;
padding: 30px 5px;
border: 5px solid white;
}
* {
box-sizing: border-box;
}
<div class="grid-container">
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
<div class="grid-item">Item</div>
</div>
If you go the flex route, then read this post, too:
Targeting flex items on the last row
if I understand correctly what you can do is set a media query for larger screens. Lets say you want to show a 3 column grid for screens over 992px you can use something like this
#media only screen and (min-width: 992px){
.grid-container{
grid-template-columns: repeat(3, 1fr);
}
}
Let me know if that helps you! check it here https://codepen.io/anon/pen/Krzbmz
I solved a similar issue by setting max-width to the grid. I had my columns as repeat(auto-fit, 150px). I wanted a max number of columns as x4 with 50px gap. So max-width of grid set to 800px.

Why does grid-gap not work on mobile?

I've been playing around with CSS Grid recently and have noticed something that I can't see to find the answer to. Let's say I split my page out to have 2 columns, and then a row below it, with another column (which spans both columns). On mobile, I'd like them to stack one on top of the other and then go back to layout described above after a certain breakpoint. Here is the markup:
HTML
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>
SCSS
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
background-color:grey;
grid-gap:10px;
#media only screen and (max-width:800px) {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.lower {
grid-template-columns: 1fr;
grid-template-rows:auto;
background-color: green;
grid-gap:10px;
}
I've noticed that on mobile, even though I've defined grid-gap for both of my grid sections, on mobile when the columns stack, the grid-gap is not maintained. So in the fiddle below, when you make the window smaller, you can see that when the columns, stack one on top of the other, the gap between B and C is non existent. Here is the fiddle:
Fiddle
Hope I'm making sense!
EDIT: Bear in mind I'm only testing this in Firefox and Chrome (which support grid).
The grid-gap rule doesn't work between B and C because it doesn't apply.
This rule creates gutters between rows and columns inside a grid container.
But you are declaring grid-gap on .upper and .lower, two siblings in a block container. Their parent (.grid) is not a grid container because it doesn't have display: grid or inline-grid.
Therefore, grid-gap: 10px on .upper is creating a 10px gutter between A and B...
and grid-gap: 10px on .lower is creating a 10px gutter between.... nothing (.lower has only one grid item. grid-gap creates gutters between multiple grid items).
fiddle demo 1
For grid-gap to work among the .upper and .lower siblings you need to apply it to their parent, which must be a grid container.
fiddle demo 2
.grid {
display: grid; /* NEW */
grid-gap: 25px; /* NEW */
}
.upper, .lower {
display: grid;
}
.upper {
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
}
.lower {
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: 10px; /* does nothing unless there are multiple grid items */
}
#media ( max-width:800px ) {
.upper {
grid-template-columns: 1fr;
grid-template-rows: auto;
}
}
.upper > * { border: 1px dashed red; }
.lower > * { border: 1px dashed blue; }
<div class="grid">
<div class="upper">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="lower">
<div class="c">C</div>
</div>
</div>