CSS grid and inline-block design issue - html

I have made a blog design using CSS grid, having used inline-block to pack DIVs together.
In my blog I have 2 picture-DIVS of height 60 that I want to show next to a text-DIV of height 120. Only the first picture is shown next to the text.
Why is the second picture shown below the text, and please get some pointers on how I can fix this.
.GridCont {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto auto auto;
grid-template-areas: "content content content content" "content content content content" "content content content content";
}
.PostContent {
grid-area: content;
background: #B8E986;
}
.Content {
background: #000000;
width: 35%;
color: white;
display: inline-block;
}
.box1 {
height: 120vh;
}
.PicContent {
background: blue;
color: white;
display: inline-block;
}
.pic1 {
height: 60vh;
width: 50%;
}
.pic2 {
height: 60vh;
width: 45%;
}
.cTextP {
padding: 20px;
}
<div class="GridCont">
<div class="PostContent">
<div class="PicContent pic1">
<div class="cTextP">Picture #1</div>
</div>
<div class="Content box1">
<div class="cTextP">Content #1</div>
</div>
<div class="PicContent pic2">
<div class="cTextP">Picture #2</div>
</div>
</div>
</div>
Code is at this JS-fiddle

Why would the second image show right beneath the first? There is no reason for that.
The second image is on the second row.
The second row goes right beneath the first row.
More specifically, the first row is occupied by two elements: image #1 and the content box. The height of the first row is defined by the tallest element. In this case, that would the content box.
So, because image #1 doesn't extend the full height of row #1, there will be a gap between images.
Here's an even more detailed explanation of the problem:
Is it possible for flex items to align tightly to the items above them?
(It's a flexbox-related post, but the logic applies here, as well.)
Instead of inline-block, use Grid properties to get the content box to span both rows:
.PostContent {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 60vh 60vh;
grid-gap: 1em;
grid-template-areas: " pic1 box1 "
" pic2 box1 ";
}
.box1 {
grid-area: box1;
}
.pic1 {
grid-area: pic1;
}
.pic2 {
grid-area: pic2;
}
.PostContent { background: #B8E986; }
.PicContent { background: blue; color: white; }
.Content { background: #000000; color: white; }
.cTextP { padding: 20px;}
<div class="GridCont">
<div class="PostContent">
<div class="PicContent pic1">
<div class="cTextP">Picture #1</div>
</div>
<div class="Content box1">
<div class="cTextP">Content #1</div>
</div>
<div class="PicContent pic2">
<div class="cTextP">Picture #2</div>
</div>
</div>
</div>
revised jsfiddle
Also note that grid properties work only between parent and child elements.

This will fix your problem:
<div class="grid-container">
<div class="image1"></div>
<div class="image2"></div>
<div class="text"></div>
</div>
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas: "image1 image1 text text" "image2 image2 text text";
}
.image1 { grid-area: image1; }
.image2 { grid-area: image2; }
.text { grid-area: text; }
You can see the working example over here:
https://codepen.io/dennisperremans/pen/NeqNJp

Related

Unequal rows in CSS grid

I am trying to create a CSS grid with unequal rows and I cannot make .feature-block-header take ONLY as much space as it actually needs. I don't want it to be equal height with .feature-block-text. Is there a way of having a flex-grow sort of way on .feature-block-text so that it takes whatever space header did not use?
I think I have tried almost every grid row property...
.feature-block {
display: grid;
grid-template-columns: 320px auto;
grid-column-gap: 10px;
grid-template-areas:
"feature-block-image feature-block-header"
"feature-block-image feature-block-text";
}
.feature-block-header {
grid-area: feature-block-header;
background: yellow;
margin-top: 0;
}
.feature-block-image {
grid-area: feature-block-image;
width: 320px;
height: 320px;
background: lightblue;
}
.feature-block-text {
grid-area: feature-block-text;
background: lightgreen;
}
<div class="feature-block">
<h2 class="feature-block-header">Header</h2>
<div class="feature-block-image"></div>
<div class="feature-block-text">
<p>Some text within text block</p>
</div>
</div>
By adjusting the grid-template-rowsproperty, you can adjust the row heights. I just added this property to your code to demonstrate the result.
EDIT: I changed 50px to auto to make it flexible to adjust row content height.
grid-template-rows: auto 1fr;
.feature-block {
display: grid;
grid-template-columns: 320px auto;
grid-column-gap: 10px;
grid-template-areas:
"feature-block-image feature-block-header"
"feature-block-image feature-block-text";
grid-template-rows: auto 1fr;
}
.feature-block-header {
grid-area: feature-block-header;
background: yellow;
margin-top: 0;
}
.feature-block-image {
grid-area: feature-block-image;
width: 320px;
height: 320px;
background: lightblue;
}
.feature-block-text {
grid-area: feature-block-text;
background: lightgreen;
}
<div class="feature-block">
<h2 class="feature-block-header">Header</h2>
<div class="feature-block-image"></div>
<div class="feature-block-text">
<p>Some text within text block</p>
</div>
</div>
You can set align-self: start; to .feature-block-header.
https://developer.mozilla.org/en-US/docs/Web/CSS/align-self

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>

Make a child element take a third of the parent container (Parent is styled using grid-layout)

I'd want one child element to be 1/3 the size of its parent container and the other 2/3. The parent container is in a main container that uses grid-layout.
The parent container in question spans 2 columns of the main container it is contained in.
I've tried using margin, but it doesn't work: when I switch from a small screen to a large screen it moves to leave a gap.
<div class="main-container" style="display:grid; grid-template-columns: 1fr 2fr 1fr"> 1
<div></div>
<div class="parent-container" style="grid-column:span 2">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
</div>
css code I've tried:
.child-1{
margin-left:-20%;
}
Child-1 must be 1/3 of parent-container and child-2 2/3 of parent-container
You can make use of the nested grid container. The dotted borders signify the width that the child elements take from the parent container. The solid borders are for the main container's child elements. Rest is explained in comments.
.main-container {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 1/4th for Extra, 2/4th for Parent, 1/4th for Extra */
grid-auto-flow: column; /* Normal flow is row */
}
.parent-container {
display: grid; /* Nested Grid */
grid-template-columns: 1fr 2fr; /* 1/3rd for Child 1, 2/3rd for Child 2 of parent container*/
grid-auto-flow: column;
}
/* Extra styling for snippet, you just need the above logic */
.main-container {
font-size: 1.15em;
font-family: Sans-Serif;
}
.parent-container {
border: 2px solid black;
}
.parent-container>div {
background: #6660CE;
padding: 10px;
color: #fff;
text-align: center;
border: 2px dotted black;
}
.main-container>div {
background: #6660CE;
padding: 10px;
color: #fff;
text-align: center;
}
<div class="main-container">
<div class="extra">Extra</div>
<div class="parent-container">
<div class="child-1">Child 1 </div>
<div class="child-2">Child 2</div>
</div>
<div class="extra">Extra</div>
</div>
Simply give the parent element two columns with grid-template-columns, where the second column is twice the size of the first column (i.e. 1fr and 2fr).
This can be seen in the following:
.container {
display: grid;
grid-template-columns: 1fr 2fr;
}
.child-1 {
background: red;
}
.child-2 {
background: blue;
}
.child {
height: 50px;
}
<div class="container">
<div class="child child-1"></div>
<div class="child child-2"></div>
</div>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child:nth-child(1) {
grid-area: 1 / 1;
background-color: #9341aa;
}
.child:nth-child(2) {
grid-area: 2 / 1 / span 1 / span 2;
background-color: #ab41aa;
}
.child:nth-child(3) {
grid-area: 3 / 1 / span 1 / span 3;
background-color: #cab332;
}
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>
Using calc, something like this should do the trick:
HTML:
<div class="main-container">
<div></div>
<div class="parent-container">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
</div>
CSS:
.parent-container{
position: relative;
width: 100%;
height: 100%;
}
.parent-container .child-1,
.parent-container .child-2{
width: calc(100% / 3);
height: 100%;
float: left;
}

What am i doing wrong using grid

I am trying to use grid and make one big box and two different on the right side of it but it is all scrambled up and as i inspect it it doesn't even show the pattern i'm aiming for. What could be wrong because i think i declared everything right.
I am trying to make 3 columns and 2 rows fill them with 2 columns 2 rows main box and the right side to take up the third column 1 small different box each row. But instead as i am inspecting it i get 5 columns and 2 rows -.-
.top-container {
display: grid;
grid-template-areas:
"main-box main-box small-box-a"
"main-box main-box small-box-b";
grid-template-columns: 200px 50px;
grid-template-rows: 300px 50px;
}
.main-box {
grid-area: main-box;
min-height: 300px;
background-color: green;
}
.small-box-a {
grid-area: small-box-a;
}
.small-box-b {
grid-area: big-box-b;
}
<div class="top-container">
<div class="main-box"> This is a big box </div>
<div class="small-box-a"> This is a small box A</div>
<div class="small-box-b"> This is a small box B</div>
</div>
You had a typo..
.small-box-b {
grid-area: big-box-b;
}
should be
.small-box-b {
grid-area: small-box-b;
}
.top-container {
display: grid;
grid-template-areas:
"main-box main-box small-box-a"
"main-box main-box small-box-b";
grid-template-columns: 200px 50px;
grid-template-rows: 300px 50px;
}
.main-box {
grid-area: main-box;
min-height: 300px;
background-color: green;
}
.small-box-a {
grid-area: small-box-a;
}
.small-box-b {
grid-area: small-box-b;
}
<div class="top-container">
<div class="main-box"> This is a big box </div>
<div class="small-box-a"> This is a small box A</div>
<div class="small-box-b"> This is a small box B</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.