I wrote a layout as depicted above. I implemented this with the simple usage of display: inline-block and article elements that have different widths and heights, like so:
width: 50%; /* this is variable*/
height: 160px; /* this is also variable*/
padding: 10px;
box-sizing: border-box;
display: inline-block;
vertical-align: top;
Now this already works quite okish, but: You see the gap above boxes 4 and 5? Can I write a pure CSS layout that makes these boxes fill up the space directly below 1? I saw some flex-box solutions but they seemed to work with a fixed set of columns, ideally I just want to pass boxes 1-6 in the layout and they adjust properly. Is that possible with modern CSS? I have no browser restrictions and can work with any modern feature!
Unfortunately you can't accomplish that with flexbox and I think grid layout would also not do the thing. Pure CSS masonry layout is highly expected, but not yet available.
I see two solutions:
1.
Use external package. I would suggest react-grid-layout which uses JS to control position: absolute and transform: translate values of children. It supports resizing and many other features. In your situation it should work just fine.
2.
You could also use some tiny JS (pen's not mine):
#staypuftman pointed out in a comment to use CSS grids and I accomplished what I wanted to do. This is my code:
On the container:
display: grid;
grid-template-columns: repeat(8, 1fr);
grid-template-rows: repeat(12, 1fr);
grid-gap: 15px;
height: 100vh;
what I do is I use the grid layout, I create 8 columns by writing 1fr 8 times in grid-template-columns and 12 rows with the 12 frs in the grid-template-rows property. Also I set a grid-gap for spacing between each item and a height of 100vh to make my grid span over the whole visible space.
Now within my items I do this:
grid-column-end: span 2;
grid-row-end: span 2;
Where grid-column-end: span X tells the browser to span the item over 2 of my columns (of which I created 8) and the same in regards to rows with grid-row-end.
This is the result:
Related
I have a two column layout in which one column displays a number of images on a grid. The size and number of the images vary. I want the images to either show one a line, or two per line, depending on the size of the image and the screen. I have the below grid set up:
#media (max-width: 2000px) {
.productimg {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(195px, 2fr));
grid-gap: 5px;
grid-auto-flow: row dense;
}
The images are given a class .u-max-full-width to keep them contained within the grid:
.u-max-full-width {
max-width: 100%;
box-sizing: border-box; }
For the most part this works. See below for the ideal layout:
However, at certain screen widths the images break into three columns. This happens with particularly thin images as soon as it is possible to put three 195px width images on the same line. I thought it might be that the images reach their source width and then rather than remain there shrink back to 195px but they are moving down to 195px before reaching their max size.
For example, images with a width of 336, 353, and 390 respectively will switch to a three col. when the container div is only 595px wide, more than small enough for the 336px and 353px images to fill it without forcing a third in.
If I increase the min width this solves the issue, however, the images will not properly fall into two rows at smaller resolutions. I tried using a #media declaration for the range where the container div can hold three 195px images, and declaring an absolute max size.
#media (min-width: 1542px) and (max-width: 2000px){
.productimg {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(195px, 350px));
grid-gap: 5px;
grid-auto-flow: row dense;
}
This does seem to prevent three columns from developing, but now it jumps from two to one columns between 1541 and 1542px in screen width because the max width is being prioritized, which is not what I want at all.
What I want to do is keep the columns to a maximum of two but to fill the row completely as long as the images are not smaller than 195px in width, but I can't seem to find any way to do that simply. I have looked at all of the various formatting declarations for grid, but am struggling to conceptualize their use. I wonder if grid is even the appropriate tool to use in this situation, but I haven't found any better solution.
Any assistance in this issue would be appreciated.
Use max() combined with viewport unit to make the column width always big enough to always have a fixed number of columns on big screen (in your case 2).
grid-template-columns: repeat(auto-fit, minmax(max(195px,Xvw), 2fr));
Adjust the X until you get the result you want.
Example:
.box {
display:grid;
grid-template-columns: repeat(auto-fit, minmax(max(195px, 45vw), 2fr));
margin: 10px;
grid-gap: 40px;
}
.box>* {
height: 100px;
background: red
}
<div class="box">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
Related question: CSS grid maximum number of columns without media queries
You can use like that also...
grid-column: 1 / 2;
.grid-container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100px repeat(3, 1fr);
}
i want the first row to be only 2 columns which will be my navbar, logo and nav links but can't seem to find out how maybe cause im searching the wrong thing.
Use grid-column on your child elements
On your grid child elements (your navbar, for example), you can use the grid-column property. You can set start and end values for where you want the child to be positioned.
For example:
.navbar {
grid-column: 1 / 7;
}
Next level: use grid-areas to label your child elements
You might also want to consider looking into grid-areas, which is a nice way of labelling and referencing areas such as your header and navbar.
References:
MDN: grid-column
MDN: grid areas
I am trying to create a game level select map where I need different sprites from a spritesheet placed on a very specific tile in a grid. I use CSS grid for this and place the tiles on the grid inline with grid-row-start and grid-column-start. Everything works as it should, except for one thing: the tiles have a small gap between them, but gapis set to 0 in the CSS. That small gap is enough to look really jarring (screenshot of map with the gap).
Because this is a mobile game, it is important that the grid is responsive and works on all device sizes. I am therefore working in percentages, and vw in the CSS. I am thinking that the gaps might be caused by decimal rounding errors?
The parent div:
.tilemap {
display: grid;
height: 150vw; /* 15 rows, 10 columns */
grid-template-rows: repeat(15, 1fr); /* 15 rows */
grid-template-columns: repeat(10, 1fr); /* 10 columns */
gap: 0;
place-content: stretch end;
}
The grid is full width (100vw) and each tile is 10vw = 10 columns. The height of the tilemap is 150vw = 15 rows. Each tile is squared (screnshot of CSS grid in devtools).
Common class for all tiles:
.tilemap div {
max-width: 100%;
background-size: 100%;
background-image: url("../images/responsive-spritesheet.png");
}
And each tile has a different background position. Included for completeness:
.tilemap div.road.vertical {
background-position: 0 100%;
}
The problem is not the spritesheet image, because the gaps still appear when I comment this out and replace it with background-color instead (screenshot).
Any help is greatly appreciated.
I know this question was asked forever ago, but I solved a similar issue of my own by dropping fr units, and using exact lengths for my grid cells.
This might help you, because I see you're using repeat() and thus have equal spacing in your grid, like I do.
I am trying to display fields in a row in the following form: Display 3 fields in a row with equal width, and the rest of them, if I have 2 fields to be in a row with equal width, and if there is one field left to be full width
I tried with this CSS:
root: {
width: '100%',
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gridColumnGap: theme.spacing(),
overflow: 'hidden',
},
But this is the result I got:
How can I achieve the expected result(first image) with CSS grid?
I can think of two solutions for this. First instead of dividing the grid to 3 columns, divide to 6 columns and span the grid items into multiple columns by targeting them using nth-child selector. Second Don't use grid at-all, instead create a flex-container that will have another 3 flex-container as child nodes. And make use of flex-basis to get the desired result.
Solution 1
Using a 6 column grid,
You have to target specific grid items and make use of span to span them across n number of columns. For example for the first 3 grid item you need to specify grid-column: span 2;. Example,
.grid-container {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.grid-item:nth-child(1),
.grid-item:nth-child(2),
.grid-item:nth-child(3) {
grid-column: span 2;
}
.grid-item:nth-child(4),
.grid-item:nth-child(5) {
grid-column: span 3;
}
.grid-item:last-child {
grid-column: span 6;
}
See the demo in codesandbox.
Solution 2
Since you asked for a solution using CSS-grid, I don't think it is a good idea to include the code for the solution that uses flex-box instead. Have a look at the codesandbox, for the solution using flex-box.
I love using CSS grid but can’t for the life of me figure this one out – I have a random number of images which will be inserted into a CSS grid container. Rather than left alignment, as below, I would like central alignment of grid items with the 12 columns.
.section-images {
grid-gap: var(--page-margins);
grid-column: span 12;
display: grid;
grid-template-columns: repeat(12, 1fr);
}
.section-image {
grid-column: span 4;
width: 100%;
}
So I would like this below, instead of the above...
Because there may be 5 images, 6 images, 13 etc. it needs to be automatic – I’m sure there’s an easy way to do this?
So if they were multiline, you’d have this:
Many thanks,
Simon