Struggling to place 2 Divs on the same line with Grid Template - css

Basically I am trying to recreate this image:
https://imgur.com/a/OcgGfmn
But struggling on the LightBlue and Red section on putting them on the same line:
.sidebar {
background-color: lightblue;
width:20%;
min-height:100px;
}
.content {
background-color: red;
width:80%;
min-height:100px;
}
So far I have tried Flex, inline-block and changing the widths, but cannot seem to get them from not appearing under each other
Inmy container I have:
.container {
display:grid;
grid-template-areas:
"navbar navbar navbar navbar"
"sidebar content"
"footer footer footer footer"
}

See below. Using grid-area for all relevant classes and width removed for sidebar and content.
.navbar {
grid-area: navbar;
background-color: lightgreen;
}
.sidebar {
background-color: lightblue;
min-height: 100px;
grid-area: sidebar;
}
.content {
background-color: red;
min-height: 100px;
grid-area: content;
}
.footer {
grid-area: footer;
background-color: lightgreen;
}
.container {
display: grid;
grid-template-areas: "navbar navbar navbar navbar" "sidebar content content content" "footer footer footer footer"
}
<div class="container">
<div class="navbar">navbar</div>
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>

Related

CSS Grid use specific item height as max row height

I'm trying to prevent the sidebar height from exceeding the content height.
The "area" will contain an image of any height so its height is not fixed or known in advance.
function toggleTabsContent() {
const display = document.querySelector('.content').style.display;
if (display == "none") {
document.querySelector('.content').style.display = "block";
} else {
document.querySelector('.content').style.display = "none";
}
}
.grid {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr auto;
grid-template-areas:
"tabs area"
"footer footer";
}
.tabs {
grid-area: tabs;
background: #FF9800;
}
.area {
grid-area: area;
height: 200px;
background: #673AB7;
}
.footer {
grid-area: footer;
background: #607D8B;
height: 40px;
}
.content {
height: 250px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>
<div class="grid">
<div class="tabs">
<div class="content" style="display: none"></div>
</div>
<div class="area"></div>
<div class="footer"></div>
</div>
JSFiddle
Display: flex; allows for a lot of flexibility - in fact it's purpose is exactly to flex the height or width to the required dimensions per the content inside of it.
Based on your question, this is exactly what you need.
I've separated your footer from the grid, in order to separate statically sized elements, from those you wish to flex.
Next I've added a min-width to your area, to avoid it collapsing completely. However if you want this functionality, you can remove this. i.e. if you want that when there is no image it doesn't appear, you can remove this.
Lastly, the display: flex; and flex-flow: row nowrap; allows the sizing to flex, and for elements within the grid (now named "flex") to be placed next to each other with the same dimensions and they won't wrap to the next line to accommodate the sizing changes.
function toggleTabsContent() {
const display = document.querySelector('.content').style.display;
if (display == "none") {
document.querySelector('.content').style.display = "block";
} else {
document.querySelector('.content').style.display = "none";
}
}
.flex {
display: flex;
flex-flow: row nowrap;
}
.tabs {
background: #FF9800;
height: auto;
width: 100%;
}
.area {
height: auto;
min-height: 200px;
width: 100%;
background: #673AB7;
}
.footer {
background: #607D8B;
height: 40px;
}
.content {
height: 400px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>
<div class="flex">
<div class="tabs">
<div class="content" style="display: none"></div>
</div>
<div class="area"></div>
</div>
<div class="footer"></div>
Use height:0;min-height:100%; on the tabs element. This will make sure the height of the element will not contribute on the size of its track then by adding min-height:100% you force it to use the height of the track defined by other elements:
function toggleTabsContent() {
const display = document.querySelector('.content').style.display;
if (display == "none") {
document.querySelector('.content').style.display = "block";
} else {
document.querySelector('.content').style.display = "none";
}
}
.grid {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr auto;
grid-template-areas:
"tabs area"
"footer footer";
}
.tabs {
grid-area: tabs;
background: #FF9800;
height:0;
min-height:100%;
overflow:auto;
}
.area {
grid-area: area;
height: 200px;
background: #673AB7;
}
.footer {
grid-area: footer;
background: #607D8B;
height: 40px;
}
.content {
height: 250px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>
<div class="grid">
<div class="tabs">
<div class="content" style="display: none"></div>
</div>
<div class="area"></div>
<div class="footer"></div>
</div>
Related question: How can you set the height of an outer div to always be equal to a particular inner div?
You can set the max-height of tabs to be the height of area
.tabs {
grid-area: tabs;
background: #FF9800;
max-height: 400px;
overflow: scroll;
}
I added lot of H1 elements and it worked the way you wanted it.
JS Fiddle
You should go the flex route, but if the only content in .tabs is an image, you can set it as a background-image and let it automatically fill the area with background-size: cover.
document.getElementById("slider").addEventListener('change', changeAreaHeight);
function changeAreaHeight(event) {
let sliderValue = event.target.value;
document.querySelector('.area').style.height = sliderValue + 'px';
}
.grid {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 1fr auto;
grid-template-areas:
"tabs area"
"footer footer";
}
.tabs {
grid-area: tabs;
background: #FF9800;
background-image: url('https://i.picsum.photos/id/167/100/300.jpg'); /* NEW */
background-size: cover; /* NEW */
}
.area {
grid-area: area;
height: 200px;
background: #673AB7;
}
.footer {
grid-area: footer;
background: #607D8B;
height: 40px;
}
<input type="range" id="slider" min="50" value="200" max="800" />
<label>Change height on .area</label>
<div class="grid">
<div class="tabs">
<div class="content" style="display: none"></div>
</div>
<div class="area"></div>
<div class="footer"></div>
</div>

Why won't my CSS grid fill the entire screen?

I can't seem to figure out why my grid will not fill out the entire (or at least more of the) screen. I can't seem to make the grid fill out the screen more, so that the white space on the left and right side does not take up so much of the screen space on bigger monitors.
#media only screen and (max-width:970px){
.billedebar{display: none;}
}
/*Tablets, Ipads osv*/
#media only screen and (min-width:600px){
#content{
margin-left: auto;
margin-right: auto;
max-width: 970px;
display: grid;
grid-template-columns:repeat(auto-fill,1fr);
grid-auto-rows:minmax(100px,auto);
grid-gap: 10px;
grid-template-areas:
"header header header header"
"main main main main"
"main main main main"
"main main main main"
"billedebar billedebar billedebar billedebar"
"boks01 boks01 boks02 boks02"
"boks03 boks03 boks04 boks04"
"footer footer footer footer";
} }
/*DESKTOP/LAPTOP*/
#media only screen and (min-width:970px){
#content{
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-auto-rows: minmax(100px,auto);
grid-gap: 10px;
grid-template-areas:
"header header header header"
"header header header header"
"billedebar main main main"
"billedebar main main main"
"billedebar main main main"
"boks01 boks02 boks03 boks04"
"boks01 boks02 boks03 boks04"
"footer footer footer footer"
"footer footer footer footer";
}
.billedebar{
display: block;
}
}
#content div{
background: #3498db;
padding: 10px; /*tekst i grid paddes ind fra kant*/
color: white; }
.header{
grid-area: header;
}
.billedebar{
grid-area: billedebar;
}
.main{
grid-area: main;
}
.section{
grid-area: bigad;
}
.boks01{
grid-area: boks01;
}
.boks02{
grid-area: boks02;
}
.boks03{
grid-area: boks03;
}
.boks04{
grid-area: boks04;
}
.footer{
grid-area: footer;
}
<body>
<div id="content">
<div class="header"><p>header</p></div>
<div class="billedebar">billedebar</div>
<div class="main">main</div>
<div class="boks01">ad</div>
<div class="boks02">ad</div>
<div class="boks03">ad</div>
<div class="boks04">ad</div>
<div class="footer">footer</div>
</div>
</body>
You're setting max-width: 970px; on #content.

Alignment not straight and rows don't span?

I am stuck on two issues with my layout.
1) The two divs in header and footer don't align up (just off slightly)
2) I am using grid-areas for my main content, but can't get it to span all the way down to the footer.
https://codepen.io/anon/pen/rEZwJY?editors=1100
.grid {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"header header header header header header header header header header header header"
"main main main main main main main main main main main main"
"footer footer footer footer footer footer footer footer footer footer footer footer"
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-areas:
"logo nav"
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-areas:
"legal links"
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
If you define grid-template-columns or grid-template-rows you have to specify the same amount of units in your grid-template-areas!
html, body { margin: 0; }
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"footer";
height: 100vh;
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"logo nav";
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-areas:
"sidebar content content content content newsletter";
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"legal links";
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
The two divs in header and footer don't align up
it is caused by the width of the content varies, in this case because it depends on text length and the font and font sizes etc.
Also You didn't specify columns so here's what happens:
The font here is Times New Roman default in chrome and font size is 16px
Say the container is 300px wide the word logo takes 33.77px and navigation takes 71.09px
First sum up the lengths of the content
33.77 + 71.09 = 104.86000000000001
Second subtract it from the width of the container
300 - 104.86000000000001 = 195.14
Third Split it amongst the grid items in this case we 2
195.14 / 2 = 97.57
Fourth we add that to the length of each grid item thus the container will fill up
*logo* takes 97.57 + 33.7 = 131.34
*navigation* takes 97.57 + 71.09 = 168.66
*sum equals container's width* 168.66 + 131.34 = 300
Nice, How do we fix this ?
So How can we fix this by defining explicit even widths (just because you want the footer to align with the header for some reason), or we can define columns using fr units exactly like the other answer suggested, but keep in mind that the padding also affects the content's length.
*, *:before, *:after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 300px;
}
.header {
background-color: pink;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
grid-template-areas: 'logo nav';
}
.footer {
background-color: pink;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
grid-template-areas: 'legal links'
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.container div {
animation:anim 10s linear infinite alternate;
}
#keyframes anim{
0%{
padding: 0em;
}
100%{
padding: 3em;
}
}
<div class="container">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
I am using grid-areas for my main content, but can't get it to span all the way down to the footer.
It's because you defined 12 rows yet you using just 5
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
.grid {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"header header header header header header header header header header header header"
"main main main main main main main main main main main main"
"footer footer footer footer footer footer footer footer footer footer footer footer"
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-areas:
"logo nav"
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-areas:
"legal links"
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
i would define a height rather than define 12 rows because you're just duplicating the height of content (which is the text in this case) 12 times

Puzzled by column span in CSS grid not working as expected

I am trying to build a layout with a full-width header, then two 150px wide ad blocks stacked vertically on the left, the main part in the center, then two more ad blocks stacked vertically on the right, with a full-width footer at the bottom.
The code I expected to work is
.container {
display: grid;
grid-gap: 2px;
background-color: black;
padding: 2px;
min-height: 300px;
width: 100%;
margin: 0 auto;
--nav-width: 250px;
}
.container {
grid-template-columns: 150px 1fr 150px; /*Three columns - 150px for the ads; rest of screen for main */
grid-template-rows: 200px 1fr 1fr 40px;
grid-template-areas:
"header header header"
"left_ad1 main right_ad1"
"left_ad2 main right_ad2"
"footer footer footer";
}
.header {
background:PaleTurquoise;
}
.nav {
background:LightPink;
}
.content {
background:red;
}
.footer {
background:blue;
}
div {
font-size: 28px;
}
body {
text-align: center;
}
.ad {
height: 250px;
}
header {
background: LightSalmon;
}
#left_ad1 {
background:PaleTurquoise;
grid-area: left_ad1;
}
#left_ad2 {
background:PaleTurquoise;
grid-area: left_ad2;
}
#right_ad1 {
background:LightPink;
grid-area: right_ad1;
}
#right_ad2 {
background:LightPink;
grid-area: right_ad2;
}
main {
background-color: red;
grid-area: main;
}
footer {
background: LightSkyBlue;
grid-area: footer;
}
<div class="container">
<header>Header</header>
<div id="left_ad1">Left ad 1</div>
<main>Main</main>
<div id="right_ad1" class="ad">Right ad 1</div>
<div id="left_ad2" class="ad">Left ad 2</div>
<div id="right_ad2" class="ad">Right ad 2</div>
<footer>Footer</footer>
</div>
but this makes the header fill just the left-most cell of the top row.
I can get it to work by adding
header {
grid-column: 1 / 4;
}
to force the header to span the whole width of the grid, but surely that shouldn't be needed? The use of grid-template-areas: "header header header" should achieve that without the use of grid-column shouldn't it?
Confused! Any help appreciated!
You need to specify grid-area: header; on your header element.
.container {
display: grid;
grid-gap: 2px;
background-color: black;
padding: 2px;
min-height: 300px;
width: 100%;
margin: 0 auto;
--nav-width: 250px;
}
.container {
grid-template-columns: 150px 1fr 150px; /*Three columns - 150px for the ads; rest of screen for main */
grid-template-rows: 200px 1fr 1fr 40px;
grid-template-areas:
"header header header"
"left_ad1 main right_ad1"
"left_ad2 main right_ad2"
"footer footer footer";
}
div {
font-size: 28px;
}
body {
text-align: center;
}
.ad {
height: 250px;
}
header {
background: LightSalmon;
grid-area: header;
}
#left_ad1 {
background:PaleTurquoise;
grid-area: left_ad1;
}
#left_ad2 {
background:PaleTurquoise;
grid-area: left_ad2;
}
#right_ad1 {
background:LightPink;
grid-area: right_ad1;
}
#right_ad2 {
background:LightPink;
grid-area: right_ad2;
}
main {
background-color: red;
grid-area: main;
}
footer {
background: LightSkyBlue;
grid-area: footer;
}
<div class="container">
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
<div id="left_ad1">Left ad 1</div>
<div id="left_ad2" class="ad">Left ad 2</div>
<div id="right_ad1" class="ad">Right ad 1</div>
<div id="right_ad2" class="ad">Right ad 2</div>
</div>

CSS Grid with an additional wrapper in the middle

I want to use CSS Grid's grid-template-areas.
But the problem is that the CMS I'm using is adding lots of additional wrappers.
Is there a way to ignore extra wrappers? since it is messing up the nice grid areas...
I'm trying to override css grid's auto-placement mechanism.
So any div that is in the middle, and wasn't assigned a specific grid-area, will appear at the end of the grid, and wouldn't mess with the grid itself.
I created an example of the problem here -
https://codepen.io/shaal/pen/qPvQWW
You can see that because of the extra wrapper, the 'sidebar' element is not assigned to the areas I wanted it to be.
HTML
.container {
display: grid;
grid-gap: 5px;
grid-template-areas: "header header header" "sidebar content content" "sidebar content content" "footer footer footer";
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
height: 180px;
}
.footer {
grid-area: footer;
}
<h1>CSS GRID</h1>
<div class="container">
<div class="item header">Header</div>
<div class="cms-annoying-wrapper">
<div class="item sidebar">Sidebar</div>
<div class="item content">Content</div>
</div>
<div class="item footer">Footer</div>
</div>
Grid Layout Module Level 2 - Subgrids are supposed to solve this problem.
In the meantime, there is a workaround:
display: contents (caniuse)
From Caniuse:
display: contents causes an element's children to appear as if they
were direct children of the element's parent, ignoring the element
itself. This can be useful when a wrapper element should be ignored
when using CSS grid or similar layout techniques.
So in your scenario you could simply add the rule:
.cms-annoying-wrapper {
display: contents;
}
body {
margin: 10px;
text-align: center;
width: 580px;
}
.cms-annoying-wrapper {
display: contents;
}
.container {
display: grid;
grid-gap: 5px;
grid-template-areas:
"header header header"
"sidebar content content"
"sidebar content content"
"footer footer footer";
}
.item {
color: white;
padding: 1.5em 0;
font-size: 2em;
}
.header {
background: #0d6;
}
.sidebar {
background: #f00;
}
.content {
background: #d60;
}
.footer {
background: #60d;
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
height: 180px;
}
.footer {
grid-area: footer;
}
<h1>CSS GRID</h1>
<div class="container">
<div class="item header">Header</div>
<div class="cms-annoying-wrapper">
<div class="item sidebar">Sidebar</div>
<div class="item content">Content</div>
</div>
<div class="item footer">Footer</div>
</div>
Codepen Demo (firefox)
If using the unwrap jQuery function to remove this div is not a problem for you I would use it.
$(".sidebar").unwrap(".cms-annoying-wrapper");
Otherwise in plain JS :
https://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/

Resources