1fr grid cell expands past 100% - html

I have the following grid which I want to span for exactly the height of the screen - not less, not more. In the grid, I have a fixed header (one), a fixed footer (three) and a scrollable content (two)
.grid-container {
display: grid;
grid-template-areas:
"one"
"two"
"three"
;
grid-template-rows: 33px 1fr 34px;
height: 100vh;
}
What happens is that if the content inside two gets too large, the height of the entire grid is now larger than the viewport. As a result, my footer gets pushed down, while I would like instead to scroll the content and keep the footer where it is.
I know I can achieve what I want with position: fixed, but this is a trimmed-down example of a more complex grid. Any help is appreciated, I prefer to keep the grid approach if at all possible. I put together a fiddle for your convenience. Thank you!
https://jsfiddle.net/x6stfc01/1/
HTML For your convenience
<div class="grid-container">
<div class="one"></div>
<div class="two">
Start of Content
<div style="height: 5000px"></div>
End of Content
</div>
<div class="three"></div>
</div>

You could just add overflow-y: scroll to the two item or overflow-y: auto (even better)
body {
margin: 0;
}
.grid-container {
display: grid;
grid-template-areas: "one" "two" "three";
grid-template-rows: 33px 1fr 34px;
height: 100vh;
}
.one {
grid-area: one;
background-color: blue;
}
.two {
grid-area: two;
background-color: yellow;
overflow-y: scroll;
}
.three {
grid-area: three;
background-color: red;
}
<html>
<head>
</head>
<body>
<div class="grid-container">
<div class="one"></div>
<div class="two">
Start of Content
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> End of Content
</div>
<div class="three"></div>
</div>
</body>
</html>

Related

How can I shrink the height of a flex child to 50% only?

I am trying to have a UI like this :
This is how I have tried doing it :
A div at the top as cover Image
The next div containing two child divs as profile photo & UI details as -
<div>Image Cover photos<div>
<div style="display : flex;">
<div>profile photo</div>
<div>UI Details Card</div>
</div>
Then I'm using the transform : translateY(-50%) to the profile photo div to move 50 percent of the portion on top of the background cover photo.
This, however creates a problem, the UI details remains at the same place(which is ideal), but the baseline has been changed.I want it to have only 50% of the height, so the baseline matches with the profile photo as well, and also UI details wcard will have some text, I do not want it to overlap on the Cover Image background as well(as that of profile photo). How can I achieve this?
One way to solve this problem is to use CSS grid to place everything.
body {
padding: 100px;
}
.card {
height: 300px;
width: 300px;
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: repeat(3, 1fr);
outline: 1px solid;
}
.details {
background-color: blanchedalmond;
grid-area: 3/2/4/3;
}
.photo {
background-color: aquamarine;
grid-area: 2/1/4/2;
}
.cover {
grid-area: 1/1/3/3;
background-color: grey;
}
.cover img,
.photo img {
height: 100%;
width: 100%;
}
<div class="card">
<div class="cover">
<img src="https://source.unsplash.com/random/?1" alt="">
</div>
<div class="photo">
<img src="https://source.unsplash.com/random/" alt="">
</div>
<div class="details">Details here</div>
</div>
Here's a diagram showing the different grid areas :
Notice the overlap region between the blue box (photo) and the red box (cover). Since the photo div appears after the cover div in the DOM, the photo div will have higher priority and will occupy this overlap region.
You can make a 2 column, 3 row grid and place items where you want them.
Here's a simple example:
.container {
display: grid;
grid-template-columns: 1fr 4fr;
grid-template-rows: 1fr 1fr 1fr;
width: 30vw;
height: 20vw;
}
.container :nth-child(1) {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
background: red;
}
.container :nth-child(2) {
grid-column: 1;
grid-row: 2 / span 2;
background: green;
}
.container :nth-child(3) {
background: blue;
}
<div class="container">
<div></div>
<div></div>
<div></div>
</div>
Obviously you will want to alter the relative sizes of the grid to suit your particular case.
Note: it depends on whether you want to put some text in the first item so that it comes directly above the second item or not as to whether you start the first div in the first column or the second column.

Grid element height affected by content image width percentage [duplicate]

This question already has answers here:
Prevent content from expanding grid items
(3 answers)
Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
(1 answer)
Closed 2 years ago.
Edit: Let me clarify! I'm not asking about how to keep the content from flowing out by restricting the size of the container, what I'm looking for is how to properly adjust the size of the content based on the container and why a div with a background image set to cover works, while and img element does not.
I am trying to achieve a standard grid layout with a header, sidebar, content and footer, where the content element would have only a single image as a child, that should fill the entire remaining space. I thought that applying
img {
width: 100%;
height: 100%;
object-fit: cover;
}
would be enough to get the desired result, but it unexpectedly increased the height of the content element. What's even more absurd is that no matter how much I reduce the height of the image, as long as it is measured in percentages, the height of the container keeps depending on the width of the image. See the following pen (or look at the snippets below, but the issue is more apparent in the pen, since there the boxes are visible side-by-side) for example.
https://codepen.io/Isti115/pen/vYGRNpg
Try adjusting the .a img { widht: 100%; } and see how it affects the overall height.
.container {
display: inline-grid;
width: 400px;
height: 300px;
margin: 50px;
grid-template-rows: 75px 1fr 50px;
/* grid-template-rows: 75px minmax(0, 1fr) 50px; */
grid-template-columns: 100px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header {
grid-area: header;
background-color: red;
}
.sidebar {
grid-area: sidebar;
background-color: yellow;
}
.content {
grid-area: content;
background-color: green;
}
.footer {
grid-area: footer;
background-color: blue;
}
.a .content {
/* min-height: 0; */
}
.a img {
width: 100%;
height: 20%;
/* object-fit: cover; */
/* height: 100%; */
}
.b img {
width: 100%;
height: 50px;
/* object-fit: cover; */
}
.c .placeholder {
width: 100%;
height: 100%;
/* background-color: purple; */
background: url("http://lorempixel.com/200/150/cats");
background-size: cover;
}
<div class="container a">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container b">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<img src="http://lorempixel.com/200/150/cats">
</div>
<div class="footer"></div>
</div>
<div class="container c">
<div class="header"></div>
<div class="sidebar"></div>
<div class="content">
<div class="placeholder"></div>
</div>
<div class="footer"></div>
</div>
I have since found a solution by either adding min-height: 0 or using minmax(0, 1fr), but I don't consider those ideal solutions, since I don't see why I couldn't simply take the remaining space that gets assigned to the content div element and place an image inside it that fills it completely without expanding the containers size. For example using a simple div instead of the image and giving it a background works perfectly as intended.
ps.: I know that this might sound similar to some other questions that got answered with max-height: 100%, but I think that there is a more complicated underlying issue that I would like to explore.

CSS - Ensuring the first two rows of my CSS grid is equal to the remaining height of the screen (excluding header)

I am wondering if the first two rows of my CSS grid can be equal to the height of the screen excluding the header. The content container below the header has been set to overflow: auto, but I would want only my first two rows of the grid to be equal to the height of the content container (without overflowing). My grid has a total of 3 rows, and basically, I want the first two rows to take up the entire height of the container without overflowing, followed by the third row being completely invisible to the screen unless the container is scrolled down. Do let me know if my explanation is confusing, as I am new to CSS grid, and not too sure if my explanation has been sufficient. Thanks all, and I look forward to your replies!
Here's a sample of my HTML layout
<div class='entire'>
<div class='header'>Header</div>
<div class='content'>
<div class='grid'>
item 1
item 2
item 3
</div>
</div>
</div>
CSS
.entire {
height: 100vh;
}
.content {
overflow: auto;
}
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: ___ ____ ____;
}
The height of .header should be defined in CSS. If not - it should be get by JS. Let's agree with definition in CSS.
Taking into account your last comment about 1st and 2nd row which should be both fit into one screen, 1st should take auto height and 2nd - all the rest height, I don't see any evidence to include the block 3rd into the grid at all. Moved it away.
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
.entire {
height: 100vh;
}
.header {
background: cyan;
height: 20px;
}
.content {
overflow: auto;
}
.grid {
/* subtracting known height of .header */
height: calc(100vh - 20px);
display: grid;
grid-template-columns: 1fr;
/* this will make 1st row auto height and 2nd - all the rest */
grid-template-rows: auto 1fr;
}
.item1 {
background: #eee;
}
.item2 {
background: #ddd;
}
.item3 {
background: #ccc;
height: 100vh;
}
<div class="entire">
<div class="header">Header</div>
<div class="content">
<div class="grid">
<div class="item1">item 1</div>
<div class="item2">item 2</div>
</div>
<div class="item3">item 3</div>
</div>
</div>

CSS grid and inline-block design issue

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

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>