Equal height different aspect ratio boxes with CSS grid - html

I'm trying to create layout like this:
Orange blocks on the right side all have the same aspect ratio and thus height.
Blue block has different aspect ratio.
Height of blue block and summ of orange blocks should be equal, as shown on the image.
Is there a way to create such layout via CSS grid? I know that I can wrap orange items in a separate column element, but I'd like to avoid this. I also managed to create this layout when aspect ratio of each item is square, but no luck with this one...
Example on jsfiddle http://jsfiddle.net/fq974gov/
.grid {
display: grid;
grid-gap: 10px;
width: 200px;
}
.item-left {
background: lightblue;
padding-bottom: 120%;
}
.item-right {
background: tomato;
padding-bottom: 60%;
}
<div class="grid">
<div class="item-left"></div>
<div class="item-right"></div>
<div class="item-right"></div>
<div class="item-right"></div>
</div>

You can define template areas and control the ratio using grid-template-columns
.grid {
display: grid;
grid-template-areas:
"l1 r1"
"l1 r2"
"l1 r3";
grid-template-columns:3fr 2fr; /*adjust this as you like*/
grid-gap: 10px;
width: 200px;
animation:change 2s infinite alternate linear;
}
.item-left {
grid-area:l1;
background: lightblue;
/*padding-bottom: 120%; no more needed*/
}
.item-right {
background: tomato;
padding-bottom: 60%;
}
.item-right:nth-child(2) {
grid-area:r1;
}
.item-right:nth-child(3) {
grid-area:r2;
}
.item-right:nth-child(4) {
grid-area:r3;
}
#keyframes change{
to{width:300px;}
}
<div class="grid">
<div class="item-left"></div>
<div class="item-right"></div>
<div class="item-right"></div>
<div class="item-right"></div>
</div>
The code can be simplified like this:
.grid {
display: grid;
grid-template-areas:
"l r"
"l r"
"l r";
grid-template-columns:3fr 2fr; /*adjust this as you like*/
grid-gap: 10px;
width: 200px;
animation:change 2s infinite alternate linear;
}
.item-left {
grid-area:l;
background: lightblue;
}
.item-right {
background: tomato;
padding-bottom: 60%;
}
#keyframes change{
to{width:300px;}
}
<div class="grid">
<div class="item-left"></div>
<div class="item-right"></div>
<div class="item-right"></div>
<div class="item-right"></div>
</div>

This is working code for it.
Check it out on JSFiddle
<html>
<head>
<title>Grid View</title>
</head>
<style>
.grid {
display: grid;
grid-gap: 10px;
width: 500px;
grid-template-areas:
"a a b b"
"a a c c"
"a a d d"
;
}
.item-left {
background: lightblue;
padding-bottom: 120%;
grid-area: a;
}
.item-right {
background: tomato;
padding-bottom: 40%;
}
#grid_b {
grid-area: b;
}
#grid_c {
grid-area: c;
}
#grid_d {
grid-area: d;
}
</style>
<body>
<div class="grid">
<div id="grid_a" class="item-left"></div>
<div id="grid_b" class="item-right"></div>
<div id="grid_c" class="item-right"></div>
<div id="grid_d" class="item-right"></div>
</div>
</body>
</html>

At first, I suggest you to read more about grid layout. This link may help you.
And let's solve your problem. Every div item in your case is a grid item. So you should give them different styles. At first You should set grid-template-columns and grid-template-rows for container. After that for items, you should set grid-column-start, grid-column-end, grid-row-start, grid-row-end. Look at the above link about grid layout and try to solve it, This is my solution that may help you.
https://jsfiddle.net/sghgh1996/0cf39bm1/
HTML:
<div class="grid">
<div class="item-left">
</div>
<div class="item-right row1">
</div>
<div class="item-right row2">
</div>
<div class="item-right row3">
</div>
</div>
CSS:
.grid {
display: grid;
grid-gap: 10px;
width: 200px;
grid-template-columns: 50% 50%;
grid-template-rows: 33.333% 33.333% 33.333%;
}
.item-left {
background: lightblue;
padding-bottom: 120%;
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 6;
}
.item-right {
background: tomato;
padding-bottom: 60%;
}
.row1{
grid-row-start: 1;
grid-row-end: 2;
}
.row2{
grid-row-start: 3;
grid-row-end: 4;
}
.row3{
grid-row-start: 5;
grid-row-end: 6;
}

Related

How can I prevent overflow of nested grid's content of div?

MCVE
I would like to nest a grid within another grid, and have a tall content box within the nested grid's content div. However no matter I set the overflow property of this content div to scroll, the content box grows causing the outer grid to exceed the viewport. So the viewport gets a scrollbar. The scrollbar of the content div is present but disabled.
// html
<div class="outergrid">
<div class="row1">
Outer Grid Header
</div>
<div class="row2">
<div class="header">
Inner Grid Header
</div>
<div class="box">
Tall Box
</div>
</div>
</div>
// style scss
*{
padding: 0px;
margin: 0px;
}
.outergrid {
display: grid;
grid-template-rows: 50px 100%;
grid-gap: 10px;
background-color: #0ff;
div {
background-color: #afa;
}
}
.row1{
grid-row: 1;
}
.row2{
grid-row: 2;
display: grid;
grid-template-rows: 50px 100%;
grid-gap: 5px;
.header {
grid-row: 1;
background-color: #ffa;
}
.contentbox {
grid-row: 2;
overflow: scroll;
.tallcontent {
background-color: #89f;
height: 1000px;
}
}
}
screenshot highlighting the problem
If I understood you correctly, then perhaps this solution (pure CSS, without SCSS) below can help you. The solution is to enforce a constraint on the height of the parent elements.
* {
padding: 0px;
margin: 0px;
}
.outergrid {
--grid-gap: 10px;
display: grid;
grid-template-rows: 50px calc(100% - 50px - var(--grid-gap));
grid-gap: var(--grid-gap);
background-color: #0ff;
max-height: 100vh;
}
.outergrid div {
background-color: #afa;
}
.row1 {
grid-row: 1;
}
.row2 {
--grid-gap: 5px;
grid-row: 2;
display: grid;
max-height: 100%;
grid-template-rows: 50px calc(100% - 50px - var(--grid-gap));
grid-gap: var(--grid-gap);
}
.row2 .header {
grid-row: 1;
background-color: #ffa;
}
.row2 .contentbox {
grid-row: 2;
overflow: scroll;
}
.row2 .contentbox .tallcontent {
background-color: #89f;
height: 1000px;
}
<div class="outergrid">
<div class="row1">
Outer Grid Header
</div>
<div class="row2">
<div class="header">
Inner Grid Header
</div>
<div class="contentbox">
<div class="tallcontent">
Tall Content
</div>
</div>
</div>
</div>

how to divide css grid like first column 50%, second column 50% and third column 100%?

.main-dev {
display: grid;
grid-template-columns: 50% 50%;
}
I want to arrange my grid into 50% 50% and 100% structures. I have attached the required output image.
Current output :
Expected Output :
.item {
border: 1px solid red;
text-align: center;
padding: 10px;
}
.main-dev {
display: grid;
grid-template-columns: 1fr 1fr;
width: 200px;
border: solid red 1px;
}
.item3 {
grid-column: 1 / 3;
/* or grid-column: 1 / span 2 */
}
<div class="main-dev">
<div class="item">1</div>
<div class="item">2</div>
<div class="item item3">3</div>
You can try this,
.item3 {
grid-column-start: 1;
grid-column-end: 3;
}
.grid-container {
display: grid;
grid-template-columns: auto 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;
}
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
</div>
So. Let's imagine you have 3 items with class names item1, item2, item3.
Here is the style for them:
.item1 { grid-area: item1; }
.item2 { grid-area: item2; }
.item3 { grid-area: item3; }
div{
display: grid;
grid-template-areas:
'item1 item2'
'item3 item3'
grid-gap: 10px;}
First of all, you can use col-. Here is my example:
.red{
border: 1px solid red;
height:200px;
}
.col-6{
float:left;
width:50%;
}
.col-12{
float:left;
width:100%;
}
<body>
<div class="col-6">
<div class="red"></div>
</div>
<div class="col-6">
<div class="red"></div>
</div>
<div class="col-12">
<div class="red"></div>
</div>
</body>
And you can modify the code as you like.

CSS layout - grid or flex [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I'm trying to create this layout.
https://pasteboard.co/K1C5o3k.jpg
I tried to use display: grid but the spacing was strange. What would be the best solution? Use grid or flexbox? How do I achieve this spacing using grid or flexbox?
<div class="wrap">
<div class="test-grid">
<div class="card box1">some text</div>
<div class="card box2">some text</div>
<div class="card">some text</div>
<div class="card box4">some text</div>
</div>
</div>
.wrap {
max-width: 600px;
}
.test-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 1em;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
margin-top: 40px;
}
.box4 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 3;
}
On your grid layout, I use grid-template-row/columns to define the fraction amount and then grid-template-areas to layout the elements, for each child element you want to define the unique class as its grid-area. You can use gap to control the spacing between the elements. Once you define a height and width for the parent element, the children will fill in their respective fraction, along with any defined gap.
Then use a media query with flex for your mobile layout. You may need to tweek the CSS a bit to get it to look just as you want, but the following example should do the trick.
.test-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 20px 20px;
grid-template-areas:
". two ."
"one two four"
"one three four"
". three .";
width: 100vw;
height: 100vh;
}
.one {
grid-area: one;
background-color: tomato;
}
.two {
grid-area: two;
background-color: tomato;
}
.three {
grid-area: three;
background-color: tomato;
}
.four {
grid-area: four;
background-color: tomato;
}
.box {
display: flex;
justify-content: center;
align-items: center;
}
#media only screen and (max-width: 600px) {
.test-grid {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.box {
width: 100%;
height: 100%;
}
}
<div class="test-grid">
<div class="one box">some text</div>
<div class="two box">some text</div>
<div class="three box">some text</div>
<div class="four box">some text</div>
</div>
Both Grid and flex will do the work, it just based on your preferences.
Snippet below will do the trick and when the screen became small (less than 500px). The grid will show as a list.
.wrap {
max-width: 600px;
}
.test-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 1em;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
grid-column: 1/span 1;
grid-row: 2/span 2;
}
.box2 {
grid-column: 2/span 2;
grid-row: 1/span 1;
}
.box3 {
grid-column: 3/span 2;
grid-row: 2/span 2;
}
.box4 {
grid-column: 2/span 2;
grid-row: 3/span 3;
}
#media (max-width: 500px) {
.test-grid {
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
<div class="wrap">
<div class="container">
<div class="test-grid">
<div class="card box1">box1</div>
<div class="card box2">box2</div>
<div class="card box3">box3</div>
<div class="card box4">box4</div>
</div>
</div>
Here's an option using only grid. In this example we create many small grid rows (10px each) which then allows you to start each element at a specific row and adjust the boxes by 10 pixel increments.
.test-grid {
display: grid;
grid-template-columns: repeat(3, 160px);
grid-template-rows: repeat(45, 10px);
column-gap: 10px;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
grid-row-start: 10;
}
.box2 {
grid-row-start: 0;
grid-column-start: 2;
}
.box3 {
grid-row-start: 24;
grid-column-start: 2;
}
.box4 {
grid-row-start: 8;
grid-column-start: 3;
}
<div class="wrap">
<div class="test-grid">
<div class="card box1">some text</div>
<div class="card box2">some text</div>
<div class="card box3">some text</div>
<div class="card box4">some text</div>
</div>
</div>

Getting grid-row to override grid-template-rows

I am asking this for my own education, if it is something that is bad practice feel free to say so.
I want elements #one #two #three and #four to have their parent property grid-template-rows: 100px 100px 100px 100px overwritten by setting individual grid-row settings to each element.
Elements #one and #two are responding as I expect when I set them like this:
#one{
grid-row: 1/ span 4 ;
}
#two{
grid-row: 1/ span 4 ;
}
However, when I attempt to apply similar settings to #three and #four I do not get the result I expect. I expect the height of #three and #four to be exactly the same as #one and #two. Instead they fly off to the side of the page.
I expected this to display the elements similar to #one and #two. It doesn't work:
#three{
grid-row: 2/ span 4 ;
}
#four{
grid-row: 2/ span 4 ;
}
I want to know how to fix this and the correct individual values to set #three and #four to overwrite grid-template-rows as described.
Code: https://jsfiddle.net/ek2r6a19/
* {
font-family: Helvetica;
font-size: 1em;
color: white;
text-align: center;
}
img {
display: block;
margin: 20px 20px;
margin-left: auto;
margin-right: auto;
border-radius: 50%;
border-width: 5px;
border-style: solid;
border-color: rgb(141, 110, 99);
max-width: 50%;
height: auto;
}
/*_____________________________GRID */
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 100px 100px 100px 100px 100px 100px;
grid-gap: 10px;
}
.container div:nth-child(even) {
background-color: orange;
}
.container div:nth-child(odd) {
background-color: purple;
}
#one {
grid-row: 1/ span 4;
}
#two {
grid-row: 1/ span 4;
}
/*
I expected this to display the elements similar to #one and #two. It doesn't work
#three{
grid-row: 2/ span 4 ;
}
#four{
grid-row: 2/ span 4 ;
}
*/
<div class="container">
<div id="one">1
<div class="content-container">
</div>
</div>
<div id="two">
2
<div class="content-container">
text
</div>
</div>
<div id="three">3
<div class="content-container">
text
</div>
</div>
<div id="four">4
<div class="content-container">
text
</div>
</div>
<div id="five">5
<div class="content-container">
text
</div>
</div>
<div id="six">6
<div class="content-container">
text
</div>
</div>
</div>
You need to override the grid auto-placement algorithm, which calculates the "right" places to render grid areas, when they're not explicitly defined.
You're defining the rows. Just define the columns, as well.
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 100px 100px 100px 100px 100px 100px;
grid-gap: 10px;
}
#one {
grid-row: 1 / span 4;
grid-column: 1; /* new */
}
#two {
grid-row: 1 / span 4;
grid-column: 2; /* new */
}
#three {
grid-row: 2 / span 4;
grid-column: 1; /* new */
}
#four {
grid-row: 2 / span 4;
grid-column: 2; /* new */
}
* {
font-family: Helvetica;
font-size: 1em;
color: white;
text-align: center;
}
img {
display: block;
margin: 20px 20px;
margin-left: auto;
margin-right: auto;
border-radius: 50%;
border-width: 5px;
border-style: solid;
border-color: rgb(141, 110, 99);
max-width: 50%;
height: auto;
}
.container div:nth-child(even) {
background-color: orange;
}
.container div:nth-child(odd) {
background-color: purple;
}
<div class="container">
<div id="one">1
<div class="content-container"></div>
</div>
<div id="two">2
<div class="content-container">text</div>
</div>
<div id="three">3
<div class="content-container">text</div>
</div>
<div id="four">4
<div class="content-container">text</div>
</div>
<div id="five">5
<div class="content-container">text</div>
</div>
<div id="six">6
<div class="content-container">text</div>
</div>
</div>
You'll notice that #one and #three, and #two and #four, don't appear to be the same height. Actually, they are.
The issue is that you've set #three and #four to start spanning at grid row line 2.
Well, #one and #two are set to start at grid row line 1, and span 4 rows, so they are overlapping #three and #four (or vice versa). You would need to start #three and #four at grid row line 5.
.container {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 100px 100px 100px 100px 100px 100px;
grid-gap: 10px;
grid-auto-rows: 100px; /* added to accommodate more rows */
}
#one {
grid-row: 1 / span 4;
grid-column: 1;
}
#two {
grid-row: 1 / span 4;
grid-column: 2;
}
#three {
grid-row: 5 / span 4;
grid-column: 1;
}
#four {
grid-row: 5 / span 4;
grid-column: 2;
}
* {
font-family: Helvetica;
font-size: 1em;
color: white;
text-align: center;
}
img {
display: block;
margin: 20px 20px;
margin-left: auto;
margin-right: auto;
border-radius: 50%;
border-width: 5px;
border-style: solid;
border-color: rgb(141, 110, 99);
max-width: 50%;
height: auto;
}
.container div:nth-child(even) {
background-color: orange;
}
.container div:nth-child(odd) {
background-color: purple;
}
<div class="container">
<div id="one">1
<div class="content-container"></div>
</div>
<div id="two">2
<div class="content-container">text</div>
</div>
<div id="three">3
<div class="content-container">text</div>
</div>
<div id="four">4
<div class="content-container">text</div>
</div>
<div id="five">5
<div class="content-container">text</div>
</div>
<div id="six">6
<div class="content-container">text</div>
</div>
</div>

Looking a more terse syntax for repeating columns of a pattern using css grid?

Is there any syntax for repeating this exact grid layout?
.grid-system {
grid-template-columns: 42px 48px 42px 48px 42px 48px 42px 48px 42px 48px 42px;
}
I tried but it seemingly didn't work:
.grid-system {
grid-template-columns: repeat(11, 42px, 48px);
}
Here's a code pen with more details:
https://codepen.io/matthewharwood/pen/vPXWmm
As you can see the design breaks the default grid system so I made a flattened grid (samba-flat-grid) w/o gaps to compensate:
It is grid-template-columns: repeat(11, 42px 48px) - without the space between them. Check here for all the possibilities.
See demo below:
.samba-grid {
display: grid;
grid-template-columns: repeat(12, 42px);
background: pink;
width: 100%;
column-gap: 48px;
}
.samba-flat-grid {
display: grid;
grid-template-columns: repeat(11, 42px 48px); /* CHANGED */
background: yellow;
width: 100%;
}
.container {
width: 100%;
max-width: 1032px;
margin: 0 auto;
background: green;
}
.section {
width: 100%;
display: block;
background: papayawhip;
}
.element-1 {
grid-column-start: 1;
grid-column-end: span 6;
}
.element-2 {
grid-column-start: 7;
grid-column-end: span 6;
}
.element-inner-img {
background: blue;
grid-column-start: 1;
grid-column-end: span 6;
}
.element-inner-img img {
width: 100%;
}
.element-inner-content {
background: #b000b5;
grid-column-start: 7;
grid-column-end: 12;
}
<div class="section">
<div class="container">
<div class="samba-grid">
<div class="element-1">
<div class="samba-flat-grid">
<div class="element-inner-img">
<img src="https://placebear.com/1600/900" alt="">
</div>
<div class="element-inner-content">
<p>Hello World</p>
</div>
</div>
</div>
<div class="element-2">
<div class="samba-flat-grid">
<div class="element-inner-img">
<img src="https://placebear.com/1600/900" alt="">
</div>
<div class="element-inner-content">
<p>Hello World</p>
</div>
</div>
</div>
</div>
</div>
</div>