I just started learning the CSS grid today, and I can start seeing the point to use this awesome css classes. But one thing that really is confusing me, is how to reorganize the grid on mobile devices.
I made an example below here. That is working how it should on a desktop view. When the screen size is going below 991px. I would like the grid was looking like this:
But how should I control that using the CSS grid?
.wrapper {
display:grid;
grid-template-columns:1fr 2fr 1fr;
grid-auto-rows:minmax(100px,auto);
grid-gap:1em;
}
.wrapper > div {
background-color: #eee;
padding: 1em;
}
.wrapper > div:nth-child(odd) {
background-color: #ddd;
}
.box1 {
grid-column:1/3;
grid-row:1/3;
}
.box2 {
grid-column:3;
}
.box3 {
grid-column:3;
}
<div class="wrapper">
<div class="box box1">Box 1</div>
<div class="box box2">Box 2</div>
<div class="box box3">Box 3</div>
</div>
You should use #media and you need to make again adjustments for 991px.
.wrapper {
display:grid;
grid-template-columns:1fr 2fr 1fr;
grid-auto-rows:minmax(100px,auto);
grid-gap:1em;
}
.wrapper > div {
background-color: #eee;
padding: 1em;
}
.wrapper > div:nth-child(odd) {
background-color: #ddd;
}
.box1 {
grid-column:1/3;
grid-row:1/3;
}
.box2 {
grid-column:3;
}
.box3 {
grid-column:3;
}
#media screen and (max-width:991px){
.wrapper {
grid-template-columns:1fr 1fr;
}
.box1 {
grid-column:1/4;
grid-row:1/3;
}
.box2 {
grid-column:1/2;
}
.box3 {
grid-column:2/4;
}
}
<div class="wrapper">
<div class="box box1">Box 1</div>
<div class="box box2">Box 2</div>
<div class="box box3">Box 3</div>
</div>
You can use media queries with #media only screen and (max-width: 990px) -
you can use a two-column grid using grid-template-columns: 1fr 1fr for this view - see demo below:
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-auto-rows: minmax(100px, auto);
grid-gap: 1em;
}
.wrapper>div {
background-color: #eee;
padding: 1em;
}
.wrapper>div:nth-child(odd) {
background-color: #ddd;
}
.box1 {
grid-column: 1/3;
grid-row: 1/3;
}
.box2 {
grid-column: 3;
}
.box3 {
grid-column: 3;
}
#media only screen and (max-width: 990px) {
.wrapper {
grid-template-columns: 1fr 1fr;
}
.box1 {
grid-column: span 2; /* span the first row */
grid-row: 1; /* first row */
}
.box2 {
grid-column: 1; /* first column */
}
.box3 {
grid-column: 2; /* second column */
}
}
<div class="wrapper">
<div class="box box1">Box 1</div>
<div class="box box2">Box 2</div>
<div class="box box3">Box 3</div>
</div>
Related
I have created flexbox to rearrange the boxes. Here is the demo code
The problem is that when I resize for smaller screen, I want to insert B between A and C.
How can I achieve that ? Thanks in advance.
grid is the grid-system you may need for this kind of layout.
here is a short example
/* let make a grid of 2 columns */
.main {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 20px;
}
/* b should span through 2 rows */
.b {
grid-row: span 2;
}
/* clear the grid system on small screen */
#media (max-width: 639px) {
.main {
display: block;
}
}
/* original styling for bg */
.a {
background-color: red;
}
.b {
background-color: green;
}
.c {
background-color: blue;
}
<div class="main">
<div class="a">A - I have some content</div>
<div class="b">B - I have some content</div>
<div class="c">C - I have some content</div>
</div>
As you can see, you may need little HTML and CSS to get this organized. Mind to set your media query in last position so it is not overridden ;)
see https://css-tricks.com/snippets/css/complete-guide-grid/ to dig further into grid
Here a solution that gather all classes a b and c in one container:
html code :
<div class="main">
<div class="container-1">
<div class="a">A - I have some content</div>
<div class="b">B - I have some content</div>
<div class="c">C - I have some content</div>
</div>
</div>
CSS code :
.a {
background-color: red;
height: 20px;
}
.b {
background-color: green;
height: 30px;
}
.c {
background-color: blue;
height: 20px;
}
.container-1 div{
width: 45%;
display: inline-block;
}
#media (max-width: 639px) {
.container-1 div {
width: 100%;
display: block;
}
}
I think it would be easier using grid instead flex:
HTML
<div class="main">
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
</div>
CSS
.main {
display: grid; /* If you don't wanna add a gap between blocks, put this attribute into the media query */
gap: 1rem; /* To add a gap between blocks */
}
.a {
background: red;
}
.b {
background: green;
}
.c {
background: blue;
}
#media (min-width: 768px) {
.main {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.a {
grid-area: 1 / 1 / 2 / 2;
}
.b {
grid-area: 1 / 2 / 3 / 3;
}
.c {
grid-area: 2 / 1 / 3 / 2;
}
}
I have this grid over here:
and i want the first big card to take the whole height of the wrapper and remain the same width, while the bottom two cards go to the right, somehow like this:
here's my css/html code where item-1 is the bigger card on the top-left:
.cards-wrapper {
background-color: #43cbff;
width: 1240px;
height: 380px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: 20px;
#media (min-width: 30em) {
grid-template-columns: 1fr 1fr;
}
#media (min-width: 60em) {
grid-template-columns: repeat(4, 1fr);
}
}
.cards {
display: flex;
flex-direction: column;
min-height: 100%;
position: relative;
top: 0;
background-color: aquamarine;
border: 1px solid lightgrey;
border-radius: 8px;
}
.item-1 {
#media (min-width: 60em) {
grid-column: 1 / span 2;
h1 {
font-size: 24px;
}
}
}
You can keep the grid layout and use grid-template-areas to make that first item take up the full height whilst retaining its existing width.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
gap: 8px 8px;
grid-auto-flow: row;
grid-template-areas:
"one one two three"
"one one four five";
}
.container * {
background: orange;
}
.one { grid-area: one; }
.two { grid-area: two; }
.three { grid-area: three; }
.four { grid-area: four; }
.five { grid-area: five; }
<div class="container">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
Flex version
I dont know you entire structure and your requirement. But by using only flexbox you can archive this also quite easy.:
.cards-wrapper {
background: gray;
}
.flex {
display: flex;
gap:5px;
}
.left, .right {
width: 50%;
}
.right {
flex-wrap: wrap;
justify-content: center;
}
.right > div {
width: 49,2%;
background-color: lightgreen;
height:100px;
}
.big {
background-color: green;
width: 100%;
}
<div class="cards-wrapper flex">
<div class="left flex">
<div class="big">BIG</div>
</div>
<div class="right flex">
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</div>
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>
Any idea of how to make this grid responsive?
This is my CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 100px 100px 100px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.a {
grid-column: 1 / 3;
grid-row: 1;
}
.b {
grid-column: 3 ;
grid-row: 1 / 3;
}
.c {
grid-column: 1 ;
grid-row: 2 ;
}
.d {
grid-column: 2;
grid-row: 2;
}
HTML
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
</div>
I tried this code:
#media only screen and (max-width:500px) {
.box {
width: 100%;
margin-right: 0;
float: none;
margin-bottom: 20px !important;
}
What's the best way to accomplish this?
I agree with #Petra that you need to use fr, but use a media query if you want to display them stacked on a mobile device. You could also just change the display to block. Make sure you add these after the initial CSS so that it isn't overridden.
#media screen and (max-width: 512px) {
.wrapper {
grid-template-columns: 1fr;
}
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
background-color: #fff;
color: #444;
}
ith CSS Grid Layout, we get a new flexible unit: the Fr unit. Fr is a fractional unit and 1fr is for 1 part of the available space.
The following code works as expected: the cells are filled with colors between defined lines
#grid {
display: grid;
height: 100px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 2/4;
}
#item3 {
background-color: blue;
grid-column: 4/7;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>
I then tried to swap the last two elements (yellow and blue), by swapping the grid-column entries:
#grid {
display: grid;
height: 100px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 4/7;
}
#item3 {
background-color: blue;
grid-column: 2/4;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>
item3 is not correctly displayed. I suppose that this is because item2 has been rendered further in the grid and the earlier element cannot be rendered anymore (wild guessing).
I am lost at how the order of the elements in the HTML is influenced by the placement of elements in the CSS, as explained in the documentation? Shouldn't the order in the HTML be insignificant?
The items are inserted one by one into the grid in the order of appearance in the html and according to their specified placement. The placement algorithm does not try to fill any previous gaps.
Note: By default, the auto-placement algorithm looks linearly through the grid without backtracking; if it has to skip some empty spaces to place a larger item, it will not return to fill those spaces. To change this behavior, specify the dense keyword in grid-auto-flow.
#grid {
display: grid;
height: 300px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 4/7;
}
#item3 {
background-color: blue;
grid-column: 2/4;
}
#item4 {
background-color: grey;
grid-column: 5/6;
}
#item5 {
background-color: orange;
grid-column: 1/7;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
<div id="item4"></div>
<div id="item5"></div>
</div>
In your example you could either make use of the grid-auto-flow property and set it to dense as suggested by the documentation:
#grid {
display: grid;
height: 100px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
grid-auto-flow: dense;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 4/7;
}
#item3 {
background-color: blue;
grid-column: 2/4;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>
or you could make use of the order property to get the wished result:
#grid {
display: grid;
height: 100px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 4/7;
order: 3;
}
#item3 {
background-color: blue;
grid-column: 2/4;
order: 2;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>
or, as suggested by GCyrillus, force the third item to be placed in the first row by using the grid-row property:
#grid {
display: grid;
height: 100px;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: 100px;
}
#item1 {
background-color: lime;
}
#item2 {
background-color: yellow;
grid-column: 4/7;
}
#item3 {
background-color: blue;
grid-column: 2/4;
grid-row: 1;
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
</div>