I have 4 columns. The actual content for columns 1 and 4 is 150px, column 2 is 250px and column 3 is 370px. I want to wrap the columns when the browser width changes. When I decrease the width of the browser, I want each column to shrink down to their lowest width before wrapping. So I imagine the 4th column would fall to the next row with a 100% width after it fell below 150px width.
Here's what I thought should've done the trick:
repeat(auto-fit, minmax(max-content, 1fr))
Is there a way to achieve this without passing a fixed width where 'max-content' is?
Here's my solution using media queries and hard widths
https://jsfiddle.net/9hjb5qv8/
Here's the html/css I used in the fiddle above:
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(370px, 1fr));
grid-gap: 8px;
}
#media (max-width: 799px) {
.container {
grid-template-columns: minmax(max-content, 1fr);
}
}
#media (min-width: 800px) {
.container .p2,
.container .p3 {
grid-column: auto / span 2;
}
}
.container > div {
background-color: gray;
text-align: center;
}
<div class="container">
<div class="p1">
<img src="https://via.placeholder.com/150x150">
</div>
<div class="p2">
<img src="https://via.placeholder.com/250x150">
</div>
<div class="p3">
<img src="https://via.placeholder.com/370x150">
</div>
<div class="p4">
<img src="https://via.placeholder.com/150x150">
</div>
</div>
I had a similar question when playing around with grid:
grid-template-columns: repeat(auto-fit, minmax(max-content, 1fr))
If we take a look at the documentation we can see that minmax command is valid:
https://developer.mozilla.org/en-US/docs/Web/CSS/minmax
But in a repeat documentation on csswg, it states one simple rule that disallows all of this from happening;
https://drafts.csswg.org/css-grid/#funcdef-repeat
The generic form of the repeat() syntax is, approximately,
repeat( [ <positive-integer> | auto-fill | auto-fit ] , <track-list> )
The first argument specifies the number of repetitions. The second
argument is a track list, which is repeated that number of times.
However, there are some restrictions:
The repeat() notation can’t be nested.
Automatic repetitions (auto-fill or auto-fit) cannot be combined with
intrinsic or flexible sizes.
Whats an intrinsic or flexible sizes ?
An intrinsic sizing function (min-content, max-content, auto, fit-content()).
So the command wont work in grid because each column/row will be different sizes and wrapping cannot take place. See bellow picture as example.
This behavior should be executed using flex-box instead.
#kivylius has a great answer to why max-content, min-content or other intrinsic sizing wouldn't work with auto-fit. He also suggested using flexbox to achieve what you are after. So, I am just extending on his answer leaving the flexbox way of doing it.
.flex-auto-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
}
.flex-auto-wrap > * {
flex: 1; /* this is to make elements/columns in each row have equal width and fill up all available space in the row, similar to auto-fit in grid */
/* flex-grow: 1; this can be used to make elements/columns in each row maintain their individual width but stretch to fill up all available space in the row */
}
div {
color: #ddd;
background-color: #222;
padding: 5px;
text-align: center;
}
<section class="flex-auto-wrap">
<div>1</div>
<div>11</div>
<div>111</div>
<div>1111</div>
<div>11111</div>
</section>
PS: I used to think grid came as an alternative to flexbox so I would try to do everything using the newer grid technology. But as it turned out, even though you can do most things with grid, it still doesn't replace flexbox. In fact, flexbox is one dimensional whereas grid is two dimensional. So, they were meant to do things differently. That's why there are some things like this one that can only be done with flexbox but not grid and there are many things that can only be done with grid but not flexbox.
Related
Im using flexboxgrid library to create easy responsive layout, I have a parent div styled like so
display: flex;
flex-wrap: wrap;
gap: 2rem;
children have flexboxgrid styling
col-xs-12 col-md-6 col-lg-4
and it works otherwise well, except when I put that 'gap: 2rem' on parent, then div's start overflowing and push last item to another row.
To illustrate problem:
How can I fix it ?
EDIT: Link to CodePen, with gap there is 2 rows, without gap 1 row.
How to keep gap, stay on 1 row ?
https://codepen.io/ShinigamiZ/pen/YzezgwE
If you want to spread them out over the whole width, don't set a flex-basis for the elements. Rather set flex-grow: 1. This means, that the elements will grow to be as big as possible.
If you want to wrap them to a new line, you need to alter your calculation for flex-basis to also incorporate the gap.
.parent {
display: flex;
flex-wrap: wrap;
gap: 2rem;
background-color: yellow;
}
.sib {
background-color: gray;
flex-grow: 1;
}
<div class='parent'>
<div class='sib'>
123
</div>
<div class='sib'>
123
</div>
<div class='sib'>
123
</div>
</div>
Column classes (col-xs-12 col-md-6 col-lg-4) means it's percentage width and that's where the issue is because the gap is not included in percentage calculation.
My take on this is to allow the columns shrink and grow but only by the amount of gap you define. With your example that would be something like:
.col-md-6 {
flex: 1 0 calc(50% - 2rem);
max-width: 50%;
}
The only issue is a slight inconsistency with columns width if there's a empty space left or if it's the only column and not fullwidth as the elements have their own original percentage width and not one reduced by gap.
https://codepen.io/Erehr/pen/jOxYadW
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to have a grid as shown below. The problem is that I don't know how to combine the responsiveness and the auto generated columns with items that should have different widths.
I know that I can create a responsive grid with
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr))
or an implicit grid with different sizes like
grid-template-columns: minmax(300px, 1.5fr)) minmax(300px, 1fr)) minmax(300px, 1fr)) minmax(300px, 1.5fr))
But that does not auto wrap on smaller screens.
How can I combine these? Can I use the grid-column attribute on an individual item to achieve this?
or is this a wrong approach and it would be better to use the flex system in this case?
You can't use differently sized cells and also use auto-fit or auto-fill to define their behavior upon resizing.
However, to get precisely what your diagrams show, you can enclose your first two and last two divs in their own div, since taken together they are the same size, and use auto-fill on the outer divs:
.container {
padding: 5px;
border: 3px solid green;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
gap: 5px;
}
.cell {
display: flex;
justify-items: stretch;
gap: 5px;
}
.cell div {
border: 3px solid black;
}
.large {
flex-grow: 3;
}
.small {
flex-grow: 2;
}
<div class="container">
<div class="cell">
<div class="large">One</div>
<div class="small">Two</div>
</div>
<div class="cell">
<div class="small">Three</div>
<div class="large">Four</div>
</div>
</div>
So again, this wraps the first two cells and last two cells in their own respective divs, which creates two equivalent cells in the grid. You can then use an auto-fill on these outer divs.
You can make each of the two grid cells a flex display to format the two internal divs. Use flex-grow to size the internal divs by a 3:2 and 2:3 ratio, respectively.
It isn't a very flexible solution, because the outer divs still have to be sized in a repeatable pattern. But in your case, they are, so it solves this specific problem — assuming that you can change your HTML.
I have a CSS grid layout with four columns and I need the first two and the second two to take 50% of the container width each. But I don't know the width of the odd columns.
So basically something like grid-template-columns: auto calc(50% - auto) auto calc(50% - auto); I know this doesn't work but I was wondering if this is possible at all. Has anyone ever been in a similar situation and have any suggestions?
edit: so the green columns should fit to the content and the blue ones take the remaining space. The red line is at 50% of the container width.
.container {
display: grid;
grid-template-columns: auto 1fr auto 1fr;
width: 300px;
}
.container > div {
border: 1px solid black;
}
.fit {
background-color: lime;
}
.container > div:not(.fit) {
background-color: lightblue;
}
#helper1 {
grid-column: 1/3;
background-color: orange;
}
#helper2 {
grid-column: 3/5;
background-color: orange;
}
<div class="container">
<div class="fit">ABC</div>
<div>0</div>
<div class="fit">A</div>
<div>1<br>2<br>3</div>
<div class="fit">A</div>
<div>4<br>5</div>
<div class="fit">ABCDEFG</div>
<div>6</div>
<div class="fit">B</div>
<div>7</div>
<div class="fit">D</div>
<div>8</div>
<div id="helper1">50%</div>
<div id="helper2">50%</div>
</div>
So, what values to use for grid-template-columns, so that the blue colums don't have equal width but sum up with their left adjacent to 50% of the container's width.
It's definitely possible, but what you have your hands on is a case of nesting grids. I'd recommend looking into using flexbox as an alternative for situations like these, but here's a stackblitz that may give some grid-related inspiration https://stackblitz.com/edit/angular-vsaato?embed=1&file=src/app/app.component.ts
The reason revolves around the 'auto' sizing of columns is used to fill available space, similar to how flexbox works, but it can't be segmented within a single grid. Thus, we make like a bird and nest!
Hope it's what you're looking for, happy coding!
I am using the following CSS Grid layout:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
}
This tries to fit as many 500px columns as possible then dispatches the remaining space evenly amongst the columns.
The problem is that when there is only one column left (grid width < 1000px) the column will shrink until it reaches 500px and will not shrink more than that, even if the grid gets smaller, causing the column to overflow.
I've tried many combinations, including nesting minmax functions, but could not solve this issue.
You can consider max-width on your elements using vw unit. Simply pay attention to maring/padding/border in order to identify the correct value.
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
}
.grid>span {
border: 2px solid red;
height: 50px;
max-width:100vw;
box-sizing:border-box;
}
body {
margin:0;
}
<div class="grid">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
grid-template-columns: repeat(auto-fit, minmax(min(100%,500px), 1fr));
The min(100%, ...) should allow your grid-item to be smaller than 500px when the parent of the grid-container is smaller than that.
I think this will help
grid-template-columns: repeat(5,500px);
Currently I try to create an "image gallery" with flex box.
This is what I currently have: https://jsfiddle.net/neu28Lnc/2/
The width of the images are always 50% - meaning I will always have 2 images next to each other.
Height of the page is not fixed - you should be able to scroll / add more images.
The problem I have, is that I want to remove the gaps between those images.
Like this: https://jsfiddle.net/neu28Lnc/1/ (hard coded with margins).
Usually I would use flex-direction: column; but since I have a no height, it will never wrap to a 2nd column.
Maybe some of you can help me with my issue / have a better solution.
Thanks in advance.
Syllz
You can do something with css Grid, but after all, css grid is more for grids, of course.
A grid is made of lines which supports each other. Each rectangular form drawn by those lines inevitably share a common horizontal and vertical line.
Flexbox is another option, but you have to set a height to your container so that columns wrap with the flex-direction: column.
If you have a lot of elements, and they exceed the space given by the height we have established, the container will break, with the remaining elements showing up on one side.
The best option here is Multi-column. Example
Cons:
- We can't have an item span more than 1 column.
- The items aren`t listed horizontally.
For me is the best "css only" solution.
W3C - CSS Multiple Columns
You can use masonary using grid layout. Hope this is helpful to you.
.container {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 20px;
}
.image {
height: 50px;
background: #ddd;
}
.image2 {
height: 150px;
background: #abc;
}
.image3 {
height: 180px;
background: #def;
}
.image4 {
height: 30px;
background: #fad;
}
.image5 {
height: 150px;
background: #ddd;
}
<div class="container">
<div class="image img">img1</div>
<div class="image2 img">img2</div>
<div class="image3 img">img3</div>
<div class="image4 img">img4</div>
<div class="image5 img">img5</div>
<div class="image img">img1</div>
<div class="image2 img">img2</div>
<div class="image3 img">img3</div>
<div class="image4 img">img4</div>
<div class="image5 img">img5</div>
</div>