I've got a grid layout with 2 columns and 3 rows.
I want to be able to resize the column widths. I know I can use resize: horizontal but that only changes width for one row.
I'm thinking I can't do what I want and I'll need to use nested grids but I'm not sure so I wanted to check.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"logo search"
"nav main"
"log main";
}
.logo {
grid-area: logo;
}
.search {
grid-area: search;
}
.nav {
grid-area: nav;
overflow: auto;
resize: horizontal;
}
.log {
grid-area: log;
overflow: auto;
resize: horizontal;
}
.main {
grid-area: main;
}
html,
body,
.container {
height: 100%;
margin: 0;
}
/* For presentation only, no need to copy the code below */
.container * {
border: 1px solid red;
position: relative;
}
.container *:after {
content: attr(class);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div class="container">
<div class="logo"></div>
<div class="search"></div>
<div class="nav">
</div>
<div class="log"></div>
<div class="main"></div>
</div>
</body>
</html>
You can do it with your structure. The trick is to use auto 1fr on the template columns and set the initial width of the resizable element to be equal to 50vw to simulate the 1fr 1fr initially:
PS: I simplified the code by removing the areas but that's not part of the trick, you can keep it
.container {
display: grid;
height: 100vh;
grid-template-columns: auto 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.log {
overflow: auto;
resize: horizontal;
width:50vw;
}
.main {
grid-row:2/span 2;
grid-column:2;
}
body{
margin: 0;
}
/* For presentation only, no need to copy the code below */
.container * {
border: 1px solid red;
position: relative;
}
.container *:after {
content: attr(class);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="logo"></div>
<div class="search"></div>
<div class="nav">
</div>
<div class="log"></div>
<div class="main"></div>
</div>
If you will have content, you can do it like below:
.container {
display: grid;
height: 100vh;
grid-template-columns: auto 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.log {
overflow: auto;
resize: horizontal;
width:50vw;
}
/* disable the width contribution so only the log will define the width */
.logo,
.nav {
width:0;
min-width:100%;
}
/**/
.main {
grid-row:2/span 2;
grid-column:2;
}
body{
margin: 0;
}
/* For presentation only, no need to copy the code below */
.container * {
border: 1px solid red;
position: relative;
}
<div class="container">
<div class="logo"> Lorem ipsum dolor sit amet, consectetur .</div>
<div class="search"> </div>
<div class="nav">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div class="log"> </div>
<div class="main"></div>
</div>
Related
I am setting up a video player in CSS Grid and for the life of me can't figure out why the width of the right most grid column (one with three multi-colored rows) increases when I add text content.
I have tried setting the overflow property to hidden but the width still changes.
If I remove the following code from the html markup, the column goes back to the desired width:
<div id="title">This Text</div>
<div id="location">is making this 3 row div</div>
<div id="date">wider for some reason</div>
I want to add text to the column without the width changing. Probably an easy fix. Thanks for any help!
https://codepen.io/Wcomp/pen/LKMrRK?editors=1100
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
*:focus {
outline: 0;
outline: none;
user-select: none;
}
* {
margin: 0;
padding: 0;
user-select: none;
}
body {
display: block;
overflow: hidden;
height: 100vh;
background-color: darkblue;
}
.middle {
display: grid;
grid-template-areas: 'item1 item1 item1 item1 item2';
grid-column-gap: 3vh;
position: absolute;
width: 100%;
top: 23.3333666667%;
height: 53.3332667%;
border-left: 3vh solid transparent;
border-right: 3vh solid transparent;
}
.vid_player {
display: grid;
background-color: green;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr;
grid-column-gap: 3vh;
left: 0%;
height: 100%;
width: 100%;
grid-area: item1;
}
.item {
background-color: white;
height: 100%;
width: 100%;
border-radius: 10px;
}
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 1fr;
height: 100%;
width: 100%;
background-color: grey;
grid-area: item2;
}
#one {
background-color: aqua;
}
#two {
background-color: red;
}
#three {
background-color: yellow;
}
#title {
color: white;
font-family: arial;
font-size: 50px;
text-align: center;
}
#location {
color: white;
font-family: arial;
font-size: 30px;
text-align: center;
}
#date {
color: white;
font-family: arial;
font-size: 30px;
text-align: center;
}
<div class="middle">
<div class="vid_player">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container">
<div id="one">
<div id="title">This Text</div>
<div id="location">is making this 3 row div</div>
<div id="date">wider for some reason</div>
</div>
<div id="two"></div>
<div id="three"></div>
</div>
</div>
Does it give the expected result if you add grid-template-columns: 1fr 1fr 1fr 1fr 1fr; to your .middle class?
By making all of the columns 1fr wide, you are telling the browser to make all of them take up the same amount of remaining space left on the page. That is, the space left after your content-filled columns have taken up what they need.
If you want the columns to take up the same amount of space no matter what try giving them widths in vw units to make their width a fraction of the screen, or percents to make their width a fraction of their parent's width.
Here's how you define your primary grid container:
.middle {
display: grid;
grid-template-areas: 'item1 item1 item1 item1 item2';
}
You've created a grid with five columns.
However, you haven't specified a width for these columns. In other words, you haven't defined any values for grid-template-columns.
As a result, each column defaults to the width of its content.
Because the column in question has text content, unlike the other columns, it is wider.
Set a rule for equal widths. Add this to your code:
.middle {
display: grid;
grid-template-areas: 'item1 item1 item1 item1 item2';
grid-template-columns: repeat(5, 1fr); /* new */
}
revised codepen
.middle {
display: grid;
grid-template-areas: "item1 item1 item1 item1 item2";
grid-template-columns: repeat(5, 1fr); /* new */
grid-column-gap: 3vh;
position: absolute;
width: 100%;
top: 23.3333666667%;
height: 53.3332667%;
border-left: 3vh solid transparent;
border-right: 3vh solid transparent;
}
.vid_player {
display: grid;
background-color: green;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr;
grid-column-gap: 3vh;
left: 0%;
height: 100%;
width: 100%;
grid-area: item1;
}
.item {
background-color: white;
height: 100%;
width: 100%;
border-radius: 10px;
}
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 1fr;
height: 100%;
width: 100%;
background-color: grey;
grid-area: item2;
}
#one {
background-color: aqua;
}
#two {
background-color: red;
}
#three {
background-color: yellow;
}
#title {
color: white;
font-family: arial;
font-size: 50px;
text-align: center;
}
#location {
color: white;
font-family: arial;
font-size: 30px;
text-align: center;
}
#date {
color: white;
font-family: arial;
font-size: 30px;
text-align: center;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
*:focus {
outline: 0;
outline: none;
user-select: none;
}
* {
margin: 0;
padding: 0;
user-select: none;
}
body {
display: block;
overflow: hidden;
height: 100vh;
background-color: darkblue;
}
<div class="middle">
<div class="vid_player">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="container">
<div id="one">
<div id="title">This Text</div>
<div id="location">is making this 3 row div</div>
<div id="date">wider for some reason</div>
</div>
<div id="two"></div>
<div id="three"></div>
</div>
</div>
I have a container div that has a header, a content area and a footer. And I want the footer to always be stuck to the bottom, while the content area always fills the remaining space. And I don't know how to do that.
This is what I have currently:
.container {
display: grid;
/*position: relative;*/
grid-template-columns: 1fr;
border: 1px solid black;
}
.header {
background-color: yellow;
display: grid;
grid-template-columns: 3fr 3fr 3fr 1fr;
padding: 10px 0;
}
.content {
background-color: teal;
position: relative;
display: grid;
grid-template-columns: 1fr 7fr 1fr;
padding: 15px 20px 20px 0;
min-height: 100%;
}
.footer {
background-color: maroon;
position: absolute;
width: 100%;
bottom: 0;
}
<div class="container">
<div class="header">This is a header.</div>
<div class="content">This is a content area.</div>
<div class="footer">This is a footer.</div>
</div>
As you can see, the content section doesn't stretch all the way to the footer section. What am I missing here?
Thanks!
Use grid-template-rows: auto 1fr auto; - this way footer and header will take only space that they need, and content will take everything else. Also, remove position: absolute; from footer to make it a grid-item.
body {
margin: 0;
}
* {
box-sizing: border-box;
}
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
border: 1px solid black;
min-height: 100vh;
}
.header {
background-color: yellow;
padding: 10px 0;
}
.content {
background-color: teal;
padding: 15px 20px 20px 0;
min-height: 100%;
}
.footer {
background-color: maroon;
width: 100%;
}
<div class="container">
<div class="header">This is a header.</div>
<div class="content">This is a content area.</div>
<div class="footer">This is a footer.</div>
</div>
<script>
$(document).ready(function(e) {
var h = $( window ).height();
$('.container').css('max-height', h-220+'px');
});
</script>
This is for container height if your footer height is 220px. You can change the height as per your need.
<style>
.footer{ bottom:0; position:fixed; }
</style>
This is for footer to fixed at bottom.
This is a simplified HTML & CSS code to what I currently have in project. Essentially since I'm using ReactJS & routes, I can't wrap everything inside another container with a css grid so I'm looking for solutions to get full page height on both the 'sidebar' & 'content' classes.
I do understand that I could use 100vh and substract from that the height of the header but in this case the header doesn't have a fixed height so I'm looking for alternatives.
.header {
display: grid;
grid-template-columns: auto auto;
background-color: lightblue;
}
.main {
display: grid;
grid-template-columns: 0.2fr 1fr;
}
.sidebar {
background-color: lightpink;
height: 100%;
}
.content {
background-color: orange;
height: 100%;
}
<div class="header">
<div>
One
</div>
<div>
Two
</div>
</div>
<div class="main">
<div class="sidebar">
Menu
</div>
<div class="content">
Content
</div>
</div>
http://jsfiddle.net/de5ut6np/39/
You can consider the body as the main container:
html {
height:100%;
}
body {
margin:0;
height:100%;
display: grid;
grid-template-rows: max-content 1fr;
}
.header {
display: grid;
grid-template-columns: auto auto;
background-color: lightblue;
}
.main {
display: grid;
grid-template-columns: 0.2fr 1fr;
}
.sidebar {
background-color: lightpink;
height: 100%;
}
.content {
background-color: orange;
height: 100%;
}
<div class="header">
<div>
One<br>
more
</div>
<div>
Two
</div>
</div>
<div class="main">
<div class="sidebar">
Menu
</div>
<div class="content">
Content
</div>
</div>
I tested like this and it worked:
html {
height:100%;
}
body {
margin: 0;
height:100%;
display: grid;
grid-template-rows: max-content 1fr;
}
.header {
display: grid;
grid-template-columns: auto auto;
background-color: lightblue;
}
.main {
display: grid;
grid-template-columns: 0.2fr 1fr;
}
.sidebar {
display: grid;
background-color: lightpink;
}
.content {
display: grid;
background-color: orange;
}
<div class="header">
<div>
One
</div>
<div>
Two
</div>
</div>
<div class="main">
<div class="sidebar">
Menu
</div>
<div class="content">
Content
</div>
</div>
I have a grid layout with two columns and two rows. A sticky left nav, a sticky header, and content that will live in the bottom right corner of the grid.
What I have now is nearly there, but I would like the .content div to use scroll when content extends beyond the screen. I thought I would be able to just use overflow: auto, but that isn't working. Is what I have close?
body {
margin: 0;
overflow: hidden;
}
.page {
display: grid;
grid-template-rows: 55px auto;
grid-template-columns: 20vh auto;
grid-template-areas: "nav header" "nav content";
}
.nav {
grid-area: nav;
background-color: blue;
}
.header {
grid-area: header;
background-color: grey;
}
.content {
grid-area: content;
height: 1000px; // This is dynamic
background-color: red;
}
<div class="page">
<div class="nav">Side nav</div>
<div class="header">Header</div>
<div class="content">
<h1>title</h1>
</div>
<div>
JS fiddle
For overflow: auto to work (i.e., for scrollbars to render) browsers need a trigger. This trigger is usually a height / width limitation that forces an overflow condition, which launches the scrollbars.
Trigger conditions vary among browsers. They also vary among CSS technologies, such as flex, grid and block layouts.
In this particular case, there are several logical places to establish an overflow condition, but none of them work.
You could target the grid item, as you have tried:
.content {
height: 1000px
overflow: auto;
}
But it doesn't work. No scrollbar appears on the fluid item.
body {
margin: 0;
/* overflow: hidden; */
}
.page {
display: grid;
grid-template-rows: 55px auto;
grid-template-columns: 20vh auto;
grid-template-areas: "nav header"
"nav content";
}
.nav {
grid-area: nav;
background-color: aqua;
}
.header {
grid-area: header;
background-color: lightgrey;
}
.content {
grid-area: content;
height: 1000px;
overflow: auto;
background-color: red;
}
<div class="page">
<div class="nav">Side nav</div>
<div class="header">Header</div>
<div class="content">
<h1>title</h1>
</div>
<div>
You could target the row itself, as I tested:
.page {
display: grid;
grid-template-rows: 55px 1000px;
}
.content {
overflow: auto;
}
But that doesn't work either. Still no scrollbar on the fluid item.
body {
margin: 0;
/* overflow: hidden; */
}
.page {
display: grid;
grid-template-rows: 55px 1000px;
grid-template-columns: 20vh auto;
grid-template-areas:
"nav header"
"nav content";
}
.nav {
grid-area: nav;
background-color: aqua;
}
.header {
grid-area: header;
background-color: lightgrey;
}
.content {
overflow: auto;
grid-area: content;
background-color: red;
}
<div class="page">
<div class="nav">Side nav</div>
<div class="header">Header</div>
<div class="content">
<h1>title</h1>
</div>
<div>
So I targeted a child of the grid item. DING DING DING! That worked.
No need for fixed positioning. No need for sticky positioning. This works across all browsers that support Grid Layout.
body {
margin: 0;
}
.page {
display: grid;
grid-template-rows: 55px calc(100vh - 55px); /* height limitation on second row */
grid-template-columns: 20vh auto;
grid-template-areas: "nav header"
"nav content";
}
.nav {
grid-area: nav;
background-color: aqua;
}
.header {
grid-area: header;
background-color: lightgrey;
}
.content {
grid-area: content;
background-color: red;
overflow: auto; /* overflow condition on parent */
}
article {
height: 1000px; /* height set on child; triggers scroll */
}
<div class="page">
<div class="nav">Side nav</div>
<div class="header">Header</div>
<div class="content">
<article><!-- new section for content -->
<h1>title</h1>
</article>
</div>
<div>
jsFiddle demo
Browser support is not 100%, but what about actually using sticky instead of fixed positioning? (now tested in Chrome) You won't have to deal with hard-coded margins.
One of the issues you'll still have to deal with, what to do when the content in your sidebar (.nav > div) Is higher than your viewport.
body {
margin: 0;
}
.page {
display: grid;
grid-template-rows: 55px auto;
grid-template-columns: 3.5rem auto;
grid-template-areas: "nav header" "nav content";
}
.nav {
grid-area: nav;
background-color: blue;
}
.nav > div {
position: sticky;
top: 0;
}
.header {
grid-area: header;
background-color: grey;
position: sticky;
top: 0;
min-height: 3.5rem;
}
.content {
grid-area: content;
min-height: 1000px;
background-color: red;
}
<div class="page">
<div class="nav">
<div>Side nav</div>
</div>
<div class="header">Header</div>
<div class="content">
<h1>title</h1>
</div>
<div>
I have included the change log to see where the code needs to be change in order to get an understanding. Also the full code snippet is available below. Hope this is what you expect.
Change log
*Remove body { overflow: hidden; }
*Change .page { grid-template-columns: 3.5rem auto; }
*Added
.nav { position: fixed;
top: 0;
bottom:0;}
*Added
.header { position: fixed;
margin-left: 3.5rem;
width: 100%;
height: 3.5rem; }
Full Code
body {
margin: 0;
}
.page {
display: grid;
grid-template-rows: 55px auto;
grid-template-columns: 3.5rem auto;
grid-template-areas:
"nav header"
"nav content";
}
.nav {
position: fixed;
top: 0;
bottom:0;
grid-area: nav;
background-color: blue;
}
.header {
grid-area: header;
background-color: grey;
position: fixed;
margin-left: 3.5rem;
width: 100%;
height: 3.5rem;
}
.content {
grid-area: content;
height: 1000px;
background-color: red;
}
<div class="page">
<div class="nav">Side nav</div>
<div class="header">Header</div>
<div class="content">
<h1>title</h1>
</div>
<div>
So I'm trying to display cards within a grid. I would like the card size to be based on the grid size and then to overlay text on top of it that correctly matches the width.
Here's my implementation so far but it seems like the div/img no longer respects the grid's sizes
for (let i = 0; i < 15; i++)
{
$("#grid").append(`
<div class="item">
<div>
<img src="http://via.placeholder.com/250x350" />
<div class="text">
sadfsd
</div>
</div>
</div>
`);
}
.flex {
border: 1px solid black;
display: flex;
flex-direction: column;
height: 100vh;
}
.footer {
height: 20%;
}
.upper {
flex: 1;
overflow: auto;
}
#grid {
border: 1px solid black;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
height: 100%;
position: relative;
max-width: 100%;
box-sizing: border-box;
}
.item {
display: inline-block;
text-align: center;
position: relative;
}
.inner {
border: 1px solid red;
max-height: 100%;
max-width: 100%;
}
.text {
position: absolute;
bottom: 10%;
left: 50%;
transform: translateX(-50%);
height: 30%;
border: 1px solid black;
width: 90%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="flex">
<div class='upper'>
<div id="grid">
</div>
</div>
<div class="footer">
footer
</div>
</div>
What I want is it to look something like this (of course with the text matching the width of the image)
for (let i = 0; i < 15; i++)
{
$("#grid").append(`
<div class="item">
<img src="http://via.placeholder.com/150x350" />
<div class="text">
text
</div>
</div>
`);
}
.flex {
border: 1px solid black;
display: flex;
flex-direction: column;
height: 100vh;
}
.footer {
height: 20%;
}
.upper {
flex: 1;
overflow: auto;
}
#grid {
border: 1px solid black;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
height: 100%;
position: relative;
max-width: 100%;
box-sizing: border-box; /* added */
}
.item {
position: relative;
}
.text {
border: 1px solid black;
position: absolute;
bottom: 10%;
left: 50%;
transform: translateX(-50%);
width: 90%;
height: 30%;
}
img {
display: block;
margin: 0 auto;
max-height: 100%;
max-width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="flex">
<div class='upper'>
<div id="grid">
</div>
</div>
<div class="footer">
footer
</div>
</div>