How to auto resize grid items to fit parent height - css

I have 5 elements which were devided into two columns by grid layout like this:
Codepen
<!DOCTYPE html>
<html>
<head>
<style>
.grid-container {
display: grid;
grid-template-columns: auto auto;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
</style>
</head>
<body>
<h1>The grid-row Property</h1>
<p>Use the <em>grid-row</em> property to specify where to place an item.</p>
<p>Item1 will start on row-line 1 and end on row-line 4:</p>
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
</div>
</body>
</html>
How can I resize for 2, 4 elements to fit the height of screen, such as the height of 2 and 4 will be equal to 1.5 the height of 1,3 and 5?

I would just break it down into another pair of grids using grid-template-areas to align the new containers so you have a left and right grid. If you want to keep the order the elements then separate item2 and item4 into their own container.
.grid-container {
display: grid;
grid-template-columns: auto auto;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
grid-template-areas:
'left-container right-container'
}
.grid-container > div > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
.left-container {
display: grid;
grid-row-gap: 10px;
}
.right-container {
display: grid;
grid-row-gap: 10px;
}
<div class="grid-container">
<div class="left-container">
<div class="item1">1</div>
<div class="item3">3</div>
<div class="item5">5</div>
</div>
<div class="right-container">
<div class="item2">2</div>
<div class="item4">4</div>
</div>
</div>

Related

CSS Border grid layout

I'm trying to set border for a grid layout with a vertical spanned cell. As suggested in some other forum posts, I set "margin-left: -1px" to avoid double borders (in the case a cell with right border is next to a cell with left border)
The problem is that only one part of the vertical border of the spanned cell is displayed, see example. How to solve it?
.grid-container {
display: grid;
grid-template-columns: 90px 90px 90px;
grid-template-rows: 24px 24px 27px;
}
.grid-item {
background-color: #EEEEEE;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item" style="grid-row: span 3; border: solid 1px;margin-left: -1px;">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
In this particular case the problem is arising because the 5 and 8 items come after the 3.
One way round it is to give the 3 item a higher z-index.
.grid-container {
display: grid;
grid-template-columns: 90px 90px 90px;
grid-template-rows: 24px 24px 27px;
}
.grid-item {
background-color: #EEEEEE;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item" style="grid-row: span 3; border: solid 1px;margin-left: -1px;z-index: 1;">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>
I would give .grid-container the same background color as the border color and use a gap of equal width as the border for the cell mentioned, or any other cell requiring the same.
In your specific case, with 3 * 90px grid columns, you will need to limit the width of the grid with width: max-content.
Snippet, moved the inline style to .special for clarity...
.grid-container {
background-color: black; /* added */
width: max-content; /* added */
display: grid;
grid-template-columns: 90px 90px 90px;
grid-template-rows: 24px 24px 27px;
}
.grid-item {
background-color: #EEEEEE;
}
.grid-item.special { /* special cell */
grid-row: span 3;
border: solid 1px;
gap: 1px;
}
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item special">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
</div>

Account for gap when calculating flex-basis

I'm trying to use gap to specify gaps between flexed items within my grid system, but running in to a major drawback. It seems that when you're using flex-grow: 0;/flex-shrink: 0; in conjunction with gap and flex-basis values that fill the entire available width (i.e. three columns with flex: 0 0 33.3333%;), the columns overflow their parent container as the gap doesn't account for the fixed width as specified with flex: 0 0 33.3333%.
Similar to box-sizing: border-box;, is there some way to instruct the rendering engine that the gap should be subtracted when determining the width of these columns?
Demonstration:
.row {
display: flex;
gap: 30px;
border: 2px solid red;
}
.col {
flex: 0 0 33.3333%;
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
}
:root {
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
<h2>With gap:</h2>
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
</div>
<h2>Without gap:</h2>
<div class="row" style="gap:0;">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
</div>
Note: I could account for this with a formula like flex-basis: calc($width - ($gap / ($number-of-columns / 2));, but as this is for a reusable grid system, I can't practically account for every possible scenario.
Here is another not very elegant quick way to hack your way forward. Similar to the answer by UPinar it alters the outer flex container. Here with negative margin on the right (this might cause other layout problems!). This "solution" is using shrink 0. Also it works with a wrapping flex.
I agree that this should not be so complicated and hacky. Maybe we are missing something? I am also under the impression that this is not the really the desired box-sizing border-box behavior which I hoped to find in combination with the gap property.
flex and gap should be hack free like: Draw three containers each consuming a third of the width and have some space between em. AFAIK gap works that way with CSS grid and CSS columns.
.flex {
display: flex;
flex-grow: 0;
flex-shrink: 0;
flex-wrap: wrap;
}
.flex.gap {
gap: var(--space-s);
margin-right: calc(-1 * var(--space-s));
}
.col {
flex-basis: 33.3333%;
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
}
.flex.gap .col {
flex-basis: calc(33.3333% - var(--space-s));
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
}
:root {
font-family: sans-serif;
--space-s: 1rem;
}
* {
box-sizing: border-box;
}
<h2>With gap</h2>
<div class="flex gap">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
</div>
<h2>Without gap</h2>
<div class="flex">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
<div class="col">
4
</div>
<div class="col">
5
</div>
<div class="col">
6
</div>
</div>
The formula you mentioned works... you can use CSS variables to make a reuseable grid system. A buddy and I came up with this:
.flex{
--columns:3;
--gap:30px;
--gap-count:calc( var(--columns) - 1 );
display:flex;
gap:var(--gap);
}
.flex-child {
flex-basis: calc( calc( 100% / var(--columns) ) - calc( var(--gap) / var(--columns) * var(--gap-count) ) );
}
#media (max-width: 992px) {
.flex{
--columns:2;
}
}
#media (max-width: 767px) {
.flex{
--columns:1;
}
}
So then all you need to change are the variables --columns and --gap
https://codepen.io/pyledigital/pen/mdWmjQb
When you add a padding-right: calc(var(--gap-space) * 2); to parent container. Parent container width will calculte before child containers use 100% which is parent container width. You need to change parent containers width before using its width inside child container.
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
min-height: 100vh;
text-rendering: optimizeSpeed;
line-height: 1.5;
margin: 0;
background-color: bisque;
display: grid;
place-content: center;
}
:root{
--gap-space:30px;
font-family: sans-serif;
}
.row-1 {
display: flex;
gap: var(--gap-space);
border: 2px solid red;
padding-right: calc(var(--gap-space) * 2);
}
.row-1 .col{
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
flex: 0 0 calc(100% / 3);
}
.row-2{
display: flex;
flex-direction: row;
border: 2px solid red;
}
.row-2 .col{
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
flex: 0 0 calc(100% / 3);
}
<h2>With gap:</h2>
<div class="row-1">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
<h2>Without gap:</h2>
<div class="row-2" style="gap: 0">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
What's wrong with using only width?
.col {
width: 33.3333%;
...
}
.row {
display: flex;
gap: 30px;
border: 2px solid red;
}
.col {
width: 33.3333%;
background: teal;
border: 2px solid #004D4D;
color: white;
font-weight: 700;
padding: 50px;
text-align: center;
}
:root {
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
<h2>With gap:</h2>
<div class="row">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
</div>
<h2>Without gap:</h2>
<div class="row" style="gap:0;">
<div class="col">
1
</div>
<div class="col">
2
</div>
<div class="col">
3
</div>
</div>

How to make a css grid grow to contain a flexbox when using grid-auto-rows?

In the following codepen you will see that there is a flexbox inside of a css grid. As you can see, the contents of the flexbox div are overflowing under other parts of the grid.
If I remove the CSS grid-auto-rows:100px; then the flexbox contents no longer overflow. However, I really want the other css grid items to be 100px tall, unless their contents are too tall to be contained within 100px.
How can I have all the css grid items default to 100px tall while having any items whose contents are taller than 100px grow to hold all of the contents?
* {box-sizing: border-box;}
.wrapper {
display: grid;
grid-auto-rows: 100px;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
.box2 {
display:flex;
flex-direction: column;
}
.box2 > div{
border: 2px solid #ffa999;
border-radius: 5px;
background-color: #ffd899;
padding: 1em;
color: #d94899;
}
<div class="wrapper">
<div class="box1">Box 1</div>
<div class="box2">
Box 2
<div class="flex1">Flex One</div>
<div class="flex2">Flex One</div>
<div class="flex3">Flex One</div>
<div class="flex4">Flex One</div>
</div>
<div class="box3">Box 3</div>
</div>
Use the minmax(min, max) function.
* {box-sizing: border-box;}
.wrapper {
display: grid;
grid-auto-rows: minmax(100px, auto);
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
.box2 {
display:flex;
flex-direction: column;
}
.box2 > div{
border: 2px solid #ffa999;
border-radius: 5px;
background-color: #ffd899;
padding: 1em;
color: #d94899;
}
<div class="wrapper">
<div class="box1">Box 1</div>
<div class="box2">
Box 2
<div class="flex1">Flex One</div>
<div class="flex2">Flex One</div>
<div class="flex3">Flex One</div>
<div class="flex4">Flex One</div>
</div>
<div class="box3">Box 3</div>
</div>

css grid: grid gap 1px has different size with columns and rows

I am using css grid in my layout and want 1px gap bewteen grid items and around items as well so I decided to give container background color and 1px padding,
in result you can see that between some items gap is clearly bigger than 1px. what is the problem ?
OS windows 10
chrome:
firefox
* {
box-sizing: border-box;
}
body {
font-family: sans-serif;
padding: 1rem;
}
.container {
max-width: 700px;
margin: 0 auto;
background: #555;
padding: 1px;
display: grid;
grid-template-columns: 1fr;
grid-gap: 1px;
}
.item {
background: #fff;
padding: 1rem;
}
.item:nth-child(2n) {
background: #f9f9f9;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>

Float second div to right only when its fits next to the first

I have the following (simplified) html & css:
<div class="container">
<div class="one">Some text for div 1</div>
<div class="two">Some text for div 2</div>
</div>
<style>
.two {float: right}
</style>
When both elements fit together in their container, I want it to look like;
Some text for div 1 Some text for div 2
However when they do not fit next to each other I want the second div's float to be removed, like;
Some text for div 1
Some text for div 2
How can I achieve this?
Flexbox can do that;
.parent {
border: 1px solid red;
margin: 1em auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.skinny {
width: 60%;
}
.left {
height: 50px;
background: green;
flex: 0 0 250px
}
.right {
height: 50px;
background: pink;
flex: 0 0 250px;
}
<div class="parent">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="parent skinny">
<div class="left"></div>
<div class="right"></div>
</div>
my variant without flexbox and more cross-browser
.container{
font-size: 0;
text-align: justify;
}
.container::after{
content: "";
display: inline-block;
width: 100%;
height: 0;
visibility: hidden;
}
.class-1, .class-2{
display: inline-block;
font-size: 14px;
text-align: left;
}
<div class="container">
<div class="class-1">Some text for div 1</div>
<div class="class-2">Some text for div 2</div>
</div>

Resources