How to align grid items vertically using display:grid and fill all vertical empty space? [duplicate] - html

This question already has answers here:
How can I make a div span multiple rows and columns in a grid?
(3 answers)
Closed 1 year ago.
I use display:grid not flex to display some divs.
Here's what my page looks like:
And here is how I would like it to look:
And here's the code:
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
gap: 40px 40px;
grid-auto-flow: row dense;
justify-items: stretch;
align-items: stretch;
grid-template-areas: "left1 center-div right1" "left1 center-div right2" "left2 center-div right3";
width: 100%;
height: 100%;
}
.left1 {
grid-area: left1;
}
.left2 {
grid-area: left2;
}
.center-div {
grid-area: center-div;
}
.right1 {
grid-area: right1;
}
.right2 {
grid-area: right2;
}
.right3 {
grid-area: right3;
}
<div class="container owl-carousel owl-theme">
<div class="grid-item left1">
left image 1
</div>
<div class="grid-item left2">
left image 2
</div>
<div class="grid-item center-div">
center image
</div>
<div class="grid-item right1">
right image 1
</div>
<div class="grid-item right2">
right image 2
</div>
<div class="grid-item right3">
right image 3
</div>
</div>
In short, I want to bring the divs closer so that they appear as they are in the second photo

Using CSS Grid
Following demo shows how you can achieve the desired layout using just the grid layout.
Its a 6 x 3 grid where items on the left span 3 rows each and the items on the right span 2 rows each. The item in the center spans all 6 rows.
Each grid items is adjusted in its place using the grid-row and grid-column properties.
The trick to achieving this layout is having more rows than columns.
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-template-rows: repeat(6, 1fr);
grid-gap: 30px;
height: 100vh;
}
.grid-item {
background: #eee;
width: 100%;
}
.center {
grid-row: 1 / span 6;
grid-column: 2 / span 1;
}
.left1 {
grid-row: 1 / span 3;
grid-column: 1 / span 1;
}
.left2 {
grid-row: 4 / span 3;
grid-column: 1 / span 1;
}
.right1,
.right2,
.right3 {
grid-column: 3 / span 1;
}
.right1 { grid-row: 1 / span 2; }
.right2 { grid-row: 3 / span 2; }
.right3 { grid-row: 5 / span 2; }
<div class="container">
<div class="grid-item left1">left1</div>
<div class="grid-item left2">left2</div>
<div class="grid-item center">center</div>
<div class="grid-item right1">right1</div>
<div class="grid-item right2">right2</div>
<div class="grid-item right3">right3</div>
</div>
Using CSS Grid along with Flexbox
Another option is to have a 1 x 3 grid and make each grid column a flex container.
You will need to change the structure of the HTML if you use this approach.
:root {
--spacing: 30px;
}
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-gap: var(--spacing);
height: 100vh;
}
.grid-item {
display: flex;
}
.grid-item div {
background: #eee;
flex-basis: 100%;
}
.col-1,
.col-3 {
flex-direction: column;
justify-content: space-between;
}
.margin-bottom {
margin-bottom: var(--spacing);
}
<div class="container">
<div class="grid-item col-1">
<div class="margin-bottom">left1</div>
<div>left2</div>
</div>
<div class="grid-item col-2">
<div>center</div>
</div>
<div class="grid-item col-3">
<div class="margin-bottom">right1</div>
<div class="margin-bottom">right2</div>
<div>right3</div>
</div>
</div>

Related

How to make second column be the largest but also able to shrink?

I am new to CSS grid and trying to implement the second row only in the below picture.
I've tried to create six sections but have the second section spread out longer. For example I've tried:
grid-column: 2 / span 5;
But it seems to push the last four section to the next line cause it to wrap which I do not want.
my unsuccessful code:
.container {
border: solid black 3px;
height: 100px;
display: grid;
grid-template-columns: repeat(6, 1fr);
}
.item {
border: solid skyblue 1px;
}
.item:nth-of-type(2) {
/* grid-column: 2 / span 5; */
}
<div class="container">
<div class="item"></div>
<div class="item">Totals</div>
<div class="item">6000</div>
<div class="item">-</div>
<div class="item">194</div>
<div class="item">12.5%</div>
</div>
Try auto on the columns, with 1fr on the flexible one.
.container {
border: solid black 3px;
height: 100px;
display: grid;
grid-template-columns: minmax(100px, auto) 1fr repeat(4, minmax(100px, auto));
}
.item {
border: solid skyblue 1px;
}
<div class="container">
<div class="item"></div>
<div class="item">Totals</div>
<div class="item">6000</div>
<div class="item">-</div>
<div class="item">194</div>
<div class="item">12.5%</div>
</div>
jsFiddle demo
Try adding grid-auto-flow: column; to your .container and change grid-column: 2 / span 5; to grid-column: 2 / span 3;

Make a grid as big as the screen

I need the grid ad big as the page (it should touch the top the bottom and both sides) and I'd like it to be non-scrollable.
HTML:
<div class="wrapper">
<div class="prova">One</div>
<div class="prova"> </div>
<div class="prova">Three</div>
<div class="prova">Four</div>
<div class="prova"> five </div>
<div class="prova">Six</div>
<div class="prova">Seven</div>
<div class="prova">Eight</div>
<div class="prova">Nine</div>
<div class="prova">Ten</div>
<div class="prova">Eleven</div>
<div class="prova">Twelve</div>
</div>
CSS:
.wrapper {
padding-top: 10%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
}
.prova{
border: 1px solid;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
I've read multiple questions but I couldn't find any solution that works fine for me.
As you can see in the picture above the grid doesn't touch neither the top or the bottom!
Set gird-auto-rows to use a percentage of the viewport height. Equal amounts per expected row. So in your case 25vh. Then remove any padding or margin around the grid.
html, body {
margin: 0
}
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 25vh;
width: 100%;
}
.prova{
border: 1px solid;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
<div class="wrapper">
<div class="prova">One</div>
<div class="prova"> </div>
<div class="prova">Three</div>
<div class="prova">Four</div>
<div class="prova"> five </div>
<div class="prova">Six</div>
<div class="prova">Seven</div>
<div class="prova">Eight</div>
<div class="prova">Nine</div>
<div class="prova">Ten</div>
<div class="prova">Eleven</div>
<div class="prova">Twelve</div>
</div>
If you want it to touches the top just remove the padding
And for other sides just set the width and height of the wrapper to 100vh and 100vw

How to set in CSS in grid this disposition in picture?

.grid-container {
display: grid;
grid-gap: 10px;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr 1fr;
}
.grid-item {
background: blue;
height: 100px;
}
.grid-item .item1 {
grid-row-start: 1;
grid-row-end: 3;
}
<div class="grid-container">
<div class="grid-item"> </div>
<div class="grid-item item1"> </div>
<div class="grid-item"> </div>
</div>
I have this, but it's not what I want
What I don't want
I want this, see this following picture :
What I want
Remove the height from the grid-items and set the rows to be 100px.
Then tell the "tall" item to be in column 2
.grid-container {
display: grid;
gap: 10px;
grid-template-columns: 2fr 1fr;
grid-auto-rows: 100px;
}
.grid-item {
background: blue;
}
.grid-item.item1 {
grid-column:2;
grid-row: 1 / span 2;
}
<div class="grid-container">
<div class="grid-item"> </div>
<div class="grid-item item1"> </div>
<div class="grid-item"> </div>
</div>
At first, You have a typo .grid-item .item1 , .item1 is not a child of .grid-item . You need to remove that space in between classnames : .grid-item.item1.
beside you have also to reset height for .item1 so it can grow the entire rows it spans, and if you also set in which columns it should stand, it avoids to see it elsewhere.
To help you debug your css, give different background-color to your items to see exactly where they stand.
possible CSS fix
.grid-container {
display: grid;
grid-gap: 10px;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr 1fr;
}
.grid-item {
background: blue;
height: 100px;
}
.grid-item.item1 {
grid-row-start:1;
grid-row-end:3;
grid-column:2;
height:auto;
background:red;
}
<div class="grid-container">
<div class="grid-item"> </div>
<div class="grid-item item1"> </div>
<div class="grid-item"> </div>
</div>
CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.
So you setting height of grid-item is wrong, because it defeats the whole purpose of grid, which is to assign area to grid childrens based upon the layout divided by grid-lines.
.grid-container {
display: grid;
grid-gap: 10px;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr 1fr;
height:200px;
}
.grid-item {
background: blue;
}
.item1 {
grid-row: 1/3;
grid-column: 2/3;
}
<div class="grid-container">
<div class="grid-item"> </div>
<div class="grid-item item1"> </div>
<div class="grid-item"> </div>
</div>

Inserting a new div between two grid items

I have the following grid layout:
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="index-view"></div>
</div>
and I am trying to insert a new div between sidebar and index such that the resulting layout will be like:
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="profile-pane"></div>
<div class="index-view"></div>
</div>
My attempt so far has been:
.main-page {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: 72px 1fr;
height: 100%;
}
.main-page > .side-bar {
display: grid;
grid-row: 1/4;
width: 80px;
}
.main-page > .profile-pane {
width: 260px;
position: relative;
grid-row: 2/4;
}
.main-page > .index-view {
grid-row: 2/4;
}
This renders a huge space between profile and index and compresses index to the right. I've been trying different values for the grid-row property but to no avail. However, if I remove either one of profile and index, the remaining div will render nicely and right beside the sidebar. How do I achieve the second layout?
You can consider different values based on the existance of the profile element:
.main-page {
display: grid;
grid-template-columns: 80px 1fr 4fr;
grid-template-rows: 72px 1fr;
height: 200px;
margin:20px;
}
.side-bar {
grid-row: span 2;
}
.nav-bar,
.index-view {
grid-column:span 2;
}
/* Take only one clumn if profile exist*/
.profile-pane + .index-view {
grid-column:span 1;
}
/* Irrelevant code */
.main-page > * {
border:1px solid;
}
.main-page > *:before {
content:attr(class);
}
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<!--<div class="profile-pane"></div>-->
<div class="index-view"></div>
</div>
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="profile-pane"></div>
<div class="index-view"></div>
</div>
You can achieve the desired result by setting the "grid-row: span 2" property in the sidebar to increase its height by two lines. And for the navigation bar, the "grid-column: span 2" property is to expand it into two columns
Oh yes, and do not forget to set the columns of the required width for the grid container grid-template-columns: 10% 15% 70%;
Result:
.main-page {
display: grid;
grid-template-columns: 10% 15% 70%;
}
.main-page>* {
padding: 20px;
border: 1px solid #000;
}
.side-bar {
grid-row: span 2;
}
.nav-bar {
grid-column: span 2;
}
.index-view {
min-height: 500px;
}
<div class="main-page">
<div class="side-bar">side-bar</div>
<div class="nav-bar">nav-bar</div>
<div class="profile-pane">profile-pane</div>
<div class="index-view">index-view</div>
</div>

How to make CSS Grid items take up remaining space?

I have a card built with CSS Grid layout. There might be an image to the left, some text to the right top and maybe a button or a link at the right bottom.
In the code below, how can I make the green area take up as much space as possible and at the same time make the blue area take up as little space as possible?
The green should push the blue area down as far as possible.
https://jsfiddle.net/9nxpvs5m/
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Adding grid-template-rows: 1fr min-content; to your .grid will get you exactly what you're after :).
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 1fr min-content;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Jens edits: For better browser support this can be used instead: grid-template-rows: 1fr auto;, at least in this exact case.
A grid is a series of intersecting rows and columns.
You want the two items in the second column to automatically adjust their row height based on their content height.
That's not how a grid works. Such changes to the row height in the second column would also affect the first column.
If you must use CSS Grid, then what I would do is give the container, let's say, 12 rows, then have items span rows as necessary.
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: repeat(12, 15px);
}
.one {
grid-row: 1 / -1;
background: red;
}
.two {
grid-row: span 10;
background: lightgreen;
}
.three {
grid-row: span 2;
background: aqua;
}
.grid > div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
Otherwise, you can try a flexbox solution.
.grid {
display: flex;
flex-flow: column wrap;
height: 200px;
}
.one {
flex: 0 0 100%;
width: 30%;
background: red;
}
.two {
flex: 1 0 1px;
width: 70%;
background: lightgreen;
}
.three {
background: aqua;
}
.grid>div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
When using grid, and you have grid template area used, and by chance you gave a particular area a width, you are left with a space grid does automatically.
In this situation, let grid-template-columns be either min-content or max-content, so that it adjusts its position automatically.
A possible approach might be grouping two and three together, and using flexbox:
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas: "one two"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.wrap {
grid-area: two;
display: flex;
flex-direction: column;
}
.two {
background: green;
flex: 1;
}
.three {
background: blue;
}
<div class="grid">
<div class="one">
One
</div>
<div class="wrap">
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
</div>
Definitely not the most elegant solution and probably not best practice, but you could always add more lines of
"one two"
before the part where you have
"one three"
so it ends up looking like
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one two"
"one two"
"one three"
}
Again, pretty sure this is just a work around and there's better solutions out there... But this does work, to be fair.
Just use width: 100% and height: 100% in the CSS class of the item you want to fill the grid. Join a max-width property and a max-height property if you don't want a grid item inside a grid container to grow more than some size.