CSS Grid Layout Gap Box Sizing - css

I have a CSS grid that occupies 100% width and 100% height of a window (the body element has display: grid;). The grid has row and column templates and elements which occupy 100% of their allocated space. However, when I add a grid-gap to the grid, it makes the grid too large for the window, forcing scrollbars to appear. How can I stop the grid-gap from adding to the dimensions of the grid - similar to how box-sizing: border-box; stops padding from adding to the dimensions of an element? Instead, I want the gaps to shrink the cells of the grid.
Thanks.

When you use "fr" it works.
Example:
HTML:
<section>
<article class="a">A</article>
<article class="b">B</article>
<article class="c">C</article>
<article class="d">D</article>
</section>
SCSS:
section {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: column;
grid-gap: 20px;
border: 10px solid blue;
article {
background-color: tomato;
&.d {
grid-column: 2;
grid-row-start: 1;
grid-row-end: 4;
background-color: olive;
}
}
}

It works same as if you used box-sizing: border-box and padding as you can see in this demo. Height is set to 100vh and you can see that if you remove or add grid-gap there is no scrollbar, you just need to remove margin from body.
body {
margin: 0;
}
.grid {
display: grid;
height: 100vh;
grid-gap: 20px;
background: #FF7D7D;
grid-template-columns: 1fr 2fr; /* Use Fractions, don't use % or vw */
}
.grid > div {
background: black;
color: white;
}
div.a, div.d {
color: black;
background: white;
}
<div class="grid">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="d">D</div>
</div>

You could use view-port units:
vw (1% of window's width)
vh (1% of window's height)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
height: 100%;
}
.first { height: 40vh; }
.hori { height: 10vh; }
.second { height: 50vh; }
div > div {
float: left;
}
.left { width: 40vw; }
.vert { width: 10vw }
.right { width: 50vw; }
.first .left,
.second .right {
background: #ccc;
}
.first .right,
.second .left {
background: #000;
}
<div class="first">
<div class="left"></div>
<div class="grid-break vert"></div>
<div class="right"></div>
</div>
<div class="grid-break hori"></div>
<div class="second">
<div class="left"></div>
<div class="grid-break vert"></div>
<div class="right"></div>
</div>

Related

Grid layout but avoid space distribute equally

I'm trying to use the grid layout for two columns in one row which can be easily achieved by flex. I have to create one more div for flex but the grid doesn't need one more div.
The problem with the grid is that it will divide the width space by 2 (cannot align to start/left) and that's not what I want, please refer to the first example below and you will understand.
Is there any way to use the grid in this situation but we can align the items to the left like in the second example?
#main-1 {
display: grid;
gap: 30px;
grid-teplate-column: repeat(2, minmax(0, 1fr));
}
.test-1 {
background-color: orange;
grid-area: span 1 / span 2;
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>
Edited
Inline-block might work but we cannot control how many items should be on each row. Imagine the width of the first div .first is dynamic and we do not know how wide it would be(but I will make it 30px for illustration). Now the desired layout should be only one .first and one .second on each row.
By inline-block it would appear that now each row is one .first, one .second, and one .first. Check out the example below. Because we cannot control the amount like grid on each row.
#main {
width: 120px;
}
.first,
.second {
display: inline-block;
height: 60px;
}
.first {
background-color: orange;
width: 30px;
}
<div id="main">
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
<div class="first"></div>
<p class="second">hhhhhh</p>
</div>
Define the columns as auto and keep only one at 1fr then you can align to the left.
#main-1 {
display: grid;
gap: 30px;
/* update "5" based on your needs */
grid-template-columns: repeat(5,auto) 1fr;
justify-content: left; /* align to left */
}
.test-1 {
background-color: orange;
grid-column: 1/-1; /* take all the columns */
}
.test-2 {
background-color: gray;
width: 150px;
}
#main-2 {
display: flex;
gap: 30px;
margin-top: 30px;
}
.test-3 {
background-color: orange;
width: 100%;
}
.test-4 {
background-color: gray;
width: 150px;
}
.test-1,
.test-2,
.test-3,
.test-4 {
height: 60px;
}
<h1>Grid</h1>
<div id="main-1">
<div class="test-1"></div>
<div class="test-2"></div>
<div class="test-2"></div>
</div>
<h1 style="margin:30px 0 0 0;padding-top:15px;border-top: 3px solid #000;">Flex</h1>
<p style="margin:0 0 30px 0;">This is the desired layout but with one more extra div</p>
<div>
<div class="test-3"></div>
<div id="main-2">
<div class="test-4"></div>
<div class="test-4"></div>
</div>
</div>

Repeating CSS grid without defining more grid areas

I'm trying to use CSS grid to layout some content in the following constraints.
I have three divs - all should be 50% wide but div two and three should stack on top of each other next to div 1.
I've managed to achieve this using grid-template-areas, but I'm using PHP to dynamically populate this, so there's no guarantee that there will always be three divs, so if it goes over this amount, I simply want the grid to repeat.
I'm using the following code right now:
.container {
display: grid;
grid-template-columns: 50% 50% 50%;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"Grid-1 Grid-2 ."
"Grid-1 Grid-3 ."
". . .";
}
.Grid-2 { grid-area: Grid-2; }
.Grid-3 { grid-area: Grid-3; }
.Grid-1 { grid-area: Grid-1; }
html, body , .container {
height: 100%;
margin: 0;
}
.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="Grid-1"></div>
<div class="Grid-2"></div>
<div class="Grid-3"></div>
</div>
It would also ne nice to not have to give each div that I'm generating a PHP the specific area class. Is this achievable using grid?
Simply like below:
.container {
display: grid;
grid-template-columns: 50% 50%; /* 2 columns */
grid-auto-rows:50vh; /* size of one row*/
}
/* for each 3 divs make the first one span 2 rows */
.container > :nth-child(3n + 1) { grid-row:span 2 }
.container * {
border: 1px solid red;
display: grid;
place-items: center;
}
.container *:after {
content:"some content";
}
body {
margin: 0;
}
<div class="container">
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>

How to set the with of grid-item to minimum of random generated width and 50% in CSS grid layout?

I was trying to make a design in which there are 2 grid items i.e. left and right. I was trying to make the design fluid so that left can take a minimum of its width or 50%
something like min of(width, 50%)
I've tried minmax but it is just the opposite as I want. Now I'm out of options
Remember: first column would be of dynamic width. Just for testing, I've taken it 200px. It should be responsive as well.
In the below snippet I would like the second column to fill the white space between first and
second
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.left {
width: 200px;
background-color: cornflowerblue;
}
.right {
background-color: cadetblue;
}
.container {
display: grid;
height: 100%;
grid-template-columns: minmax(auto, 1fr) 1fr;
}
<div class="container">
<div class="left">LEFT</div>
<div class="right"> Right </div>
</div>
im not sure, if i got your point but you could do this:
grid-template-columns: minmax(auto, auto) 1fr;
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.left {
width: 200px;
background-color: cornflowerblue;
}
.right {
background-color: cadetblue;
}
.container {
display: grid;
height: 100%;
grid-template-columns: minmax(auto, auto) 1fr;
}
<div class="container">
<div class="left">LEFT</div>
<div class="right"> Right </div>
</div>
Flex might be what you are looking for :
Use flex which is the latest trend in CSS
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.left {
width: 200px;
background-color: cornflowerblue;
}
.right {
width: 100%;
background-color: cadetblue;
}
.container {
display: flex;
height: 100%;
width: 100%;
}
<div class="container">
<div class="left">LEFT</div>
<div class="right"> Right </div>
</div>

Css Grid layout 1fr exceeds parent height [duplicate]

This question already has answers here:
Prevent content from expanding grid items
(3 answers)
Closed 2 years ago.
I have made a demo to demonstrate my problem
<style>
.main {
display: grid;
grid-template-rows: 1fr auto;
background-color: red;
width: 300px;
height: 120px;
}
.top {
height: 50px;
background-color: blue;
}
.bottom {
display: grid;
grid-template-columns: minmax(100px, 30%) auto;
column-gap: 10px;
margin: 10px;
}
.left {
background-color: green;
max-height: 100%;
overflow-y: scroll;
}
.right {
background-color: yellow;
}
</style>
<div class="main">
<div class="top">My content</div>
<div class="bottom">
<div class="left">Left hkjs ajsgf dh a sk si sk dils k lkao one sp shek siej</div>
<div class="right">Right</div>
</div>
</div>
The green div exceeds the height of its parent div. I want the green div to be within the red div and have a scroll bar whenever the content exceeds the height of the parent.
I don't know how clear I have explained my problem but please help me.
Add min-height:0 to the parent element.
<style>
.main {
display: grid;
grid-template-rows: 1fr auto;
background-color: red;
width: 300px;
height: 120px;
}
.top {
height: 50px;
background-color: blue;
}
.bottom {
display: grid;
grid-template-columns: minmax(100px, 30%) auto;
column-gap: 10px;
margin: 10px;
min-height:0;
}
.left {
background-color: green;
max-height: 100%;
overflow-y: scroll;
}
.right {
background-color: yellow;
}
</style>
<div class="main">
<div class="top">My content</div>
<div class="bottom">
<div class="left">Left hkjs ajsgf dh a sk si sk dils k lkao one sp shek siej</div>
<div class="right">Right</div>
</div>
</div>

Extend column background into grid gutters

Consider this…
You are creating three column layout using grid system. Your container is fixed sized and centered using margin:0 auto.
Your design specs calls for first column to have background color that extends to the left edge of browser.
Any idea how you can achieve this? I could make it work this way, which is kind of a hack and it may not work for certain kind of image backgrounds.
HTML:
<main>
<section>
<div class="container">
<header>
<h1>Hey There!</h1>
</header>
<div>
<h2>Column 2</h2>
</div>
<div>
<h2>Column 3<h2>
</div>
</div>
</section>
</main>
CSS
main {
min-width: 800px;
}
section {
background-image: linear-gradient(to right, #dfdfdf 50%, #fff 50%);
border-bottom: 1px solid #dfdfdf;
}
.container {
width: 500px;
margin:0 auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
section > * {
min-height: 200px;
}
.container > div {
background-color: #fff;
padding-left: 30px;
}
You could also generate the background using a pseudoelement.
The left value is large enough to keep the background extending out of the screen. It may be problematic if you need precise position of a background image.
Also, you could consider grid-gap instead of adding padding-left to the grid items.
body {
margin: 0;
}
main {
min-width: 800px;
}
section {
border-bottom: 1px solid #dfdfdf;
}
.container {
width: 500px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
section>* {
min-height: 200px;
}
.container>div {
background-color: #fff;
padding-left: 30px;
}
header {
position: relative;
}
header:before {
content: '';
background: lightgrey;
display: block;
position: absolute;
left: -50vw;
right: 0;
bottom: 0;
height: 100%;
z-index: -1;
}
<main>
<section>
<div class="container">
<header>
<h1>Hey There!</h1>
</header>
<div>
<h2>Column 2</h2>
</div>
<div>
<h2>Column 3</h2>
</div>
</div>
</section>
</main>
You could try making the columns stretch the full width of the container, and then aligning the content inside to appear as three centered columns.
.container {
display: grid;
grid-template-columns: 1fr auto 1fr;
grid-column-gap: 20px;
min-height: 50px;
}
header {
background-color: lightgray;
display: flex;
justify-content: flex-end;
}
section {
border-bottom: 1px solid #dfdfdf;
}
body {
margin: 0;
}
p { text-align: center;}
p > span { padding: 5px; background-color: aqua; }
<main>
<section>
<div class="container">
<header>
<h1>Hey There!</h1>
</header>
<div>
<h2>Column 2</h2>
</div>
<div>
<h2>Column 3</h2>
</div>
</div>
</section>
</main>
<p><span>True Center</span></p>
codepen demo

Resources