css-grid column-gap property makes it easy to create space between elements. However, it's not so easy to overlay elements and target the edge of the gap. With a 12 column Grid with 16px gaps between the columns and 16px columns on the edges my solution is to have 26 columns, like this:
.wrapper {
grid-template-columns: repeat(12, 16px 1fr) 16px ;
}
Then, if you want to target the gap edge (see images), you can use normal grid-column spacing, you only must keep in mind you have now 26 columns.
div {
grid-column: 1/3;
background-color:blue;
}
Of course the grid-gap, gap, or column-gap property should simplify this, only it doesn't. Using column gaps instead of columns you can't target the edge of the gap unless you enlarge the overlaid div beyond 100% of the columns containing it.
Here are three images to explain what I mean:
Image 1:
In the image above is a blue div overlaying column 1 of a 12 column layout with 16px gap.
.wrapper {
grid-template-columns: repeat(12, 1fr);
column-gap:16px;
}
.div-1 {grid-column:1; background-color:pink;}
.div-2 {grid-column:2; background-color:pink;}
etc..
.div-overlay {grid-column: 1/2; background-color:blue;}
Image 2:
In the second image above everything is the same except the blue div overlaying the pink 12 column grid spans to the third column instead of the second (it looks like the end of the second column, because it's before the first gap, but actually the first gap is included in the third column and line number three is the start of the third column).
.div-overlay {grid-column: 1/3; background-color:blue;}
Image three:
In the third image, above, if you want to target the start of the second column and the end of the first gap, you need to change the width of the overlaying blue div, you can't use the grid-column property with spans to get it done.
.div-overlay{
grid-column:1/2;
width:111%;
background-color:blue;
}
One would think with gap, column-gap, and grid-gap properties you would be able to span just the gap using a key word such as in this ficticious example:
.div-overlay{
grid-column: col 1 / span gap 1;
background-color:blue;
}
Am I missing something, or should I stick with 26 column grids to get it done?
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;
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 need to do suitable css for: creating a boxes that can be splitted to one or more columns depend on the screen size. (for example: if I have 7 boxes it can appear in big screen in 7 columns and 1 row, or it can appear in smaller screen in 2 rows and 4 columns, and etc.
Now I am doing in the div container:
display: flex;
flex-wrap: wrap;
overflow-y: auto;
overflow-x: hidden;
and in the box class:
height: 166px;
width: 320px;
I want that if I have a small screen and I have enough place to only one column, for example: if the div parent have 600 px width, I will have just one column of boxes but a lot of extra space, I will want that the boxes will shrink in that case to width 250px (minimum width), and that I will have 2 columns..
I want to use flex-shrink only when I have one column that created from the display flex.
How can I do it? (I want it to work in all browsers, that is why I didn't use grid)
Thanks
I am trying to replicate the behavior of tables using flexbox, for greater predictability and control. Here's a codepen of what I have currently.
Here's the SCSS:
.flex-table
display: flex
flex-direction: column
flex-wrap: nowrap
.flex-table-row
display: flex
flex-direction: row
flex-wrap: nowrap
.flex-table-item
flex-basis: 0
flex-grow: 1
.flex-table-item > :nth-child(3n + 3)
border: 1px solid red
flex-grow: 0
white-space: nowrap
My question is, how can I get the width of the each element in a column to take up the width of its content or the width of the largest element in the column, whichever is greater?
Here's an image of what I have:
I would like the box of Header 3 to equal the width of the other two elements. Also, if Content 2-2 or Content 3-2, grows, I want all columns to expand to have an equal width of the largest column, similar a table. I know I can partially do this with min-width, but I want an approach which works with dynamic content of any width.
At the end of the day, to do this (with flexboxes) the header and the content below will need to be grouped in columns instead of the way you have it now in which all headers are in the same row. I believe the way I mention makes more sense anyways, but maybe you need something different.
Here is a JSFiddle of what I am describing. As you can see, in each column each element will dynamically resize to the width of the largest element in that column. In addition, the flex-basis: 0 makes sure that every column resizes to the same width as the largest column. If the width of one column resizes, they all do.
Really all I did is switch from row to column:
.flex-table-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
}
Let me know if you have questions on this or if I missed the mark.
Try to imagine a situation
there is a div and inside the container there are three divs ,
and sometimes we need to let the inside divs self-adaption.
like this
css:
.a{display:-webkit-box;width:300px;height:100px;background:#222}
.a div{-webkit-box-flex:1;height:100px}
.a-1{background:red}
.a-2{background:yellow}
.a-3{background:blue}
html:
<div class="a">
<div class="a-1">abc</div>
<div class="a-2">abcdddd</div>
<div class="a-3">abcdddddddde</div>
</div>
but a-1 ,a-2 , a-3 do not self-adaption .i mean a-1 a-2 a-3 do not equal in length. it seems also depends on the text length.
how solve?
Looks like you have misunderstood the purpose of the flexible box layout. It works by taking the unused space in the containing element and adding into its children. So for example if your containing box is 300px, and you have three elements originally 80px, 100px, and 60px, then you have 300-80-100-60 = 60px. Then if your three child elements all have a flex value of 1 then it allocates 60/(3*1) = 20px to each. So the child sizes are now 100px, 120px, and 80px.
For your example, as you want them equal sizes, you should make the -webkit-box-flex to 0 for all three children, but set their width (or height if appropriate) to 33.33% each.
I have occasions where I do not know the number of elements that will be within an element, but I still want them to be layed out evenly. For instance if I had 3 elements their width would be 33%, but for 4 elements the width would be 25%. To get around this I set the width to 1% first, then set flex to 1.
.flex-container {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
}
.flex-element {
-webkit-box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
box-flex: 1;
width: 1%;
}
I think you need to add display: -webkit-box to .a div{-webkit-box-flex:1;height:100px}