Is it possible to explicitly make a grid item appear always on the last row or last column? - html

I want to place a grid item to be always on the last row and / or on the last column of a grid. Even if I don't know how many rows or columns the grid might have. Is something like that possible?
This would be my grid:
.columns {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min-content, 16.5rem));
grid-gap: 1rem;
}
I only found placement by explicit rows or columns:
MDN

Following my comment; from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Line-based_Placement_with_CSS_Grid#Counting_backwards
We can also count backwards from the block and inline end of the grid, for English that would be the right hand column line and final row line. These lines can be addressed as -1, and you can count back from there – so the penultimate line is -2.

You can use a pseudo element :after to place an element at the end of the grid - see demo below:
.columns {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min-content, 16.5rem));
grid-gap: 1rem;
}
.columns div {
border: 1px solid;
height: 100px;
}
.columns:after {
content:'';
display: block;
border: 1px solid red;
height: 100px;
}
<div class="columns">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Or you can use order property to place the element to the end - if any other grid item has order property, just give a large value. See demo below:
.columns {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min-content, 16.5rem));
grid-gap: 1rem;
}
.columns div {
border: 1px solid;
height: 100px;
}
.columns .last {
order: 1;
border: 1px solid red;
}
<div class="columns">
<div></div>
<div></div>
<div></div>
<div class="last"></div>
<div></div>
<div></div>
<div></div>
</div>

Related

How can I make grid-item take the whole line?

I'm learning grid-system and wondering how I can make some grid-item take remaining cells?
I have this 3 states:
Desktop
Mobile
Mobile without green one
I just set for the desktop:
grid-template-columns: repeat(3, 1fr)
Works fine.
For the mobile, I reset the above code and do for the first element
grid-column: 1 / span 2
And receive what in the second option
But when it comes to the optional appearance of the green block, I get something like this:
So not the third option
The blue block takes only the half.
And I tried lots of grid things but didn't get the result I wanted.
With flexbox I could easily just use flex-basis and flex-grow properties, but with grid I'm doomed to pass some extra class, for example, block__elem--without-green and set grid-column: 1/span2 by the blue block
This snippet takes advantage of the CSS grid-template-areas property.
The three divs are set to be in grid areas A, B, C respectively.
Their container has different layout depending on whether option 1, 2 or 3.
For the third layout the second div is just not displayed.
.container {
width: 100vmin;
height: 30vmin;
display: grid;
}
.container.one {
grid-template-areas: 'A B C' 'A B C';
}
.container.two {
grid-template-areas: 'A A' 'B C';
}
.container.three {
grid-template-areas: 'A' 'C';
}
.container :nth-child(1) {
border: red solid 1px;
grid-area: A;
}
.container :nth-child(2) {
border: green solid 1px;
grid-area: B;
}
.container :nth-child(3) {
border: blue solid 1px;
grid-area: C;
}
.container.three :nth-child(2) {
display: none;
}
<h2>ONE</h2>
<div class="container one">
<div></div>
<div></div>
<div></div>
</div>
<h2>TWO</h2>
<div class="container two">
<div></div>
<div></div>
<div></div>
</div>
<h2>THREE</h2>
<div class="container three">
<div></div>
<div></div>
<div></div>
</div>

Is it possible to place all the items in grid in one row when I don't know the number of columns?

I'm trying to make a grid container that has undefined number of columns and I want it to be one row. Is there any way to do this in CSS?
.grid {
display: grid;
grid-gap: 5px;
}
.grid > div {
background: #ccc;
min-height: 100px;
}
<div class="grid">
<div></div>
<div></div>
<div></div>
</div>
There is two ways actually.
Using grid-template-columns: repeat(auto-fit, minmax(1px, 1fr));. Fits new columns automatically and determines it's mimimum and maximum width. More about Grid Template Columns and auto-fit/auto-fill.
Using grid-auto-flow: column;. Determines automatically placement behavior of grid cells. More about Grid auto flow.
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(1px, 1fr));
grid-gap: 5px;
margin-bottom: 5px;
}
.grid2 {
display: grid;
grid-auto-flow: column;
grid-gap: 5px;
margin-bottom: 5px;
}
.grid > div, .grid2 > div {
background: #ccc;
min-height: 100px;
}
<div class="grid">
<div></div>
<div></div>
<div></div>
</div>
<div class="grid2">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

CSS Grid gap not the same size for column and row

I have the following elements:
<body>
<div class="parent">
<div class="grid">
<!--...-->
</div>
</div>
</body>
.parent {
margin: 30px 30px 0 30px;
display: block;
}
.grid {
display: grid;
grid-template-rows: 55% 45%;
grid-template-columns: 20% 48% 30%;
gap: 1%;
}
As you can see, the size of the cells are based on the parent element size (percentual size), and so are the gap size.
The problem is that while the column gap size is just the way I want, the row gap is very thin.
I understand that this is caused because the gap is equal to 1% of the heigth of the parent element, but i wanted it to be the same size as the column gap.
Is there a way to make the row gap the same size as the column gap?
First, it's better to use fr instead of percentage then you can rely on vw unit like below:
.parent {
margin: 30px 30px 0 30px;
display: block;
}
.grid {
display: grid;
border: 1px solid;
grid-template-rows: 55fr 45fr;
grid-template-columns: 20fr 48fr 30fr;
grid-gap: calc((100vw - 60px)/100);
}
.grid>div {
min-height: 100px;
height:100%;
background: red;
}
<div class="parent">
<div class="grid">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
below to compare
<div class="grid" style="grid-gap:1%;">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
Try using the rem unit. For example, gap: 2rem;
This will make both row and column size equal to the root element's font size.

How to align half div with css grid?

I have four divs. How do I align the second and third in one line? (50% each)
I have tried to do the following:
.wrap { display:grid; grid-template-columns:1fr; grid-template-rows:1fr "auto auto" 1fr; }
.wrap > div {border:1px solid; background:#4472C4;}
<div class="wrap">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
But chrome doesn't apply this style. maybe I am doing this wrong.
How do I fix it?
grid-template-rows:1fr "auto auto" 1fr;
This is nonsense. grid-template-rows provides a template for the size of each column in every row.
It doesn't describe each row one by one.
"auto auto" is not a valid size.
Create a 2x3 grid, then make the first and last elements span multiple cells in it.
div {
border: solid #aaa 1px
}
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "Top Top" "Left Right" "Bottom Bottom";
}
.Top {
grid-area: Top;
}
.Left {
grid-area: Left;
}
.Right {
grid-area: Right;
}
.Bottom {
grid-area: Bottom;
}
<div class="grid-container">
<div class="Top">Top</div>
<div class="Left">Left</div>
<div class="Right">Right</div>
<div class="Bottom">Bottom</div>
</div>
You can specify a grid of two columns, and set grid-column: span 2 for the items you want to have full width.
.wrap {
display: grid;
grid-template-columns: 1fr 1fr;
}
.wrap>div {
border: 1px solid;
background: #4472C4;
min-height: 2em;
margin:0.3em;
}
.wrap>div:nth-child(3n+1) {
grid-column: span 2;
}
<div class="wrap">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Keep flex items in proper columns after wrapping

I'm trying to use justify-content to properly justify divs inside my container, but this option is not working the way I expected. I want my div's inside the container to keep order in the second row of my example like so:
1 2 3
4 5
and not like:
1 2 3
4 5
.container {
display: flex;
width: 1100px;
justify-content: space-between;
flex-wrap: wrap;
}
.container > div {
width: 330px;
height: 125px;
background-color: rgba(18, 28, 41, 0.50);
border: 1px solid #325E82;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Codepen: https://codepen.io/anon/pen/pryWYZ
One solution would be to make use of the pseudo-selector ::after in order to create a fake 'invisible' element that occupies the same width as the other elements. In combination with justify-content, this causes the existing final element to be moved to the center:
.container {
display: flex;
width: 1100px;
justify-content: space-between;
flex-wrap: wrap;
}
.container > div {
width: 330px;
height: 125px;
background-color: rgba(18, 28, 41, 0.50);
border: 1px solid #325E82;
}
.container::after {
content: '';
width: 332px; /* .container > div 'width' plus .container > div 'border' */
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
I've also created a CodePen of this here.
Hope this helps! :)
Flexbox is not designed to create perfect grids. That's why aligning the flex items on the last row has no natural solution. You need hacks to make it work.
This is explained in detail in these posts:
Is it possible for flex items to align tightly to the items above them?
Targeting flex items on the last row
Properly sizing and aligning the flex item(s) on the last row
The ideal way to solve this problem would be to switch from flex layout to grid layout. With CSS Grid Layout, there is more control over the placement and sizing of content items.
.container {
display: grid;
grid-auto-rows: 125px;
grid-template-columns: repeat(auto-fill, 330px);
grid-gap: 10px;
width: 1100px;
}
.container>div {
background-color: rgba(18, 28, 41, 0.50);
border: 1px solid #325E82;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
For more details about CSS Grid, including an explanation of the properties above and browser support data, see this post: CSS-only masonry layout but with elements ordered horizontally
Another way around it is to have justify-content: flex-start; on the .Container and specify margin on correct Child Items depending upon desired number of columns and restricting size on childs.
For a 3-Column grid, something like this:
.container {
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
}
.item {
background-color: gray;
width: 100px;
height: 100px;
flex: 0 0 32%;
margin: 1% 0;
}
.item:nth-child(3n-1) {
margin-left: 2%;
margin-right: 2%;
}
<div class="container">
<div class=item></div>
<div class=item></div>
<div class=item></div>
<div class=item></div>
<div class=item></div>
</div>