1

I need to create a grid that has 3 rows, each row has 2 columns.

  • First row columns should be 40% - 60%
  • Second row both columns should be 50%
  • Third row first column should be 60%, second column 40%.

The columns should have a 10px gutter in between the columns, and for screen sizes smaller then 992px all columns should be 100% while still having a 10px "gutter".

(Underneath every 100% column except the last one should be 10px gutter). I am struggling on how to do this the best way.

HTML:

<div class="flexrow">
   <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>

CSS:

.flexrow{
   display: flex;
   align-items:stretch;
   flex-wrap: wrap;
}

I have tried margins but can't get it to work properly.

41 72 6c
  • 1,600
  • 5
  • 19
  • 30
fredrik
  • 85
  • 2
  • 11
  • What went wrong with using margins? It might help to show what you tried and where you got stuck. – showdev Jun 11 '19 at 18:01
  • It created a margin at the very bottom. I also don't understadn what the best way is to set the widths for the columns. – fredrik Jun 11 '19 at 19:00

3 Answers3

4

Flexbox makes this pretty easy with a justify-content value of space-between:

.flexrow {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

This makes sure that the items will stick to the outer edge of the container when the dimensions are correct.

The gutter is created by setting the width of the flex items to less than 100% of the total width. Here we want 2 columns so you can set the width of the items to 50% minus enough to make up the gutter width:

.flexcol {
  width: calc(50% - 5px); // 50% minus 5px for each column, with 2 columns that's a 10px gutter space between the two columns.
  margin-bottom: 10px; //space between the rows, remove if you dont want that.
}

Now to set the first and third rows, just change the width accordingly:

.col-1,
.col-6 {
  width: calc(40% - 5px); // here's the 40% ones
}

.col-2,
.col-5 {
  width: calc(60% - 5px); // and the 60% ones
}

For the 100% change at 992px, just add a media query and update the necessary values:

@media (max-width: 992px) {
  .flexcol {
    width: 100%; // 100% width, no margin or anything to deal with because of the space-between layout approach
  }
  .col-5 {
    margin-bottom: 10px; // add this so the 5th and 6th items have space between them when 100% wide
  }
}

.flexrow {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  background: #efefef;
}

.flexcol {
  width: calc(50% - 5px);
  margin-bottom: 10px;
  
  /* just for visibility */
  border: 1px solid red;
  padding: 20px;
  background: #fff;
  box-sizing: border-box;
}

.col-1,
.col-6 {
  width: calc(40% - 5px);
}

.col-2,
.col-5 {
  width: calc(60% - 5px);
}

.col-5,
.col-6 {
  margin-bottom: 0;
}

@media (max-width: 992px) {
  .flexcol {
    width: 100%;
  }
  .col-5 {
    margin-bottom: 10px;
  }
}
<div class="flexrow">
  <div class="flexcol col-1">THING 1</div>
  <div class="flexcol col-2">THING 2</div>
  <div class="flexcol col-3">THING 3</div>
  <div class="flexcol col-4">THING 4</div>
  <div class="flexcol col-5">THING 5</div>
  <div class="flexcol col-6">THING 6</div>
</div>
BugsArePeopleToo
  • 2,976
  • 1
  • 15
  • 16
  • Yes, this does work. Both, your solution and the grid one from above achieve the same. Now I am not sure what is better for browser compatibility. – fredrik Jun 12 '19 at 06:00
  • Flexbox support: https://caniuse.com/#search=flex. Grid support: https://caniuse.com/#search=grid. It's close, flexbox has little bit better support. – BugsArePeopleToo Jun 12 '19 at 15:32
2

For various reasons, this job is better suited for CSS Grid than Flexbox.

First, getting the gutters to work in Grid is simple. You can use the grid-gap property, which isn't available yet in flexbox.

Second, the "columns" you're requesting aren't really columns. A column has the same width from top to bottom. You're asking for a masonry layout, which allows content items to span across multiple columns and rows.

Again, this task is much easier to achieve with CSS Grid.

Here's one solution that may work for you (including the media query):

jsFiddle demo

.grid-container {
  display: grid;
  grid-auto-columns: 1fr;
  width: 500px;
  grid-auto-rows: 50px;
  grid-gap: 10px;
}

.col-1 {
  grid-column: 1 / span 4;
  grid-row: 1;
}

.col-2 {
  grid-column: 5 / span 6;
  grid-row: 1;
}

.col-3 {
  grid-column: 1 / span 5;
  grid-row: 2;
}

.col-4 {
  grid-column: 6 / span 5;
  grid-row: 2;
}

.col-5 {
  grid-column: 1 / span 6;
  grid-row: 3;
}

.col-6 {
  grid-column: 7 / span 4;
  grid-row: 3;
}

@media ( max-width: 992px ) {
  .grid-container>div {
    grid-column: 1;
    grid-row: auto;
  }
}

/* non-essential demo styles */

.grid-container {
  border: 1px solid black;
  background-color: lightgray;
}
.grid-container > div {
  font-size: 1.3em;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
.grid-container > div:nth-child(odd) {
  background-color: green;
}
.grid-container > div:nth-child(even) {
  background-color: orangered;
}
<div class="grid-container">
  <div class="col-1">40%</div>
  <div class="col-2">60%</div>
  <div class="col-3">50%</div>
  <div class="col-4">50%</div>
  <div class="col-5">60%</div>
  <div class="col-6">40%</div>
</div>

In the layout above, each column you create has a width of 1fr. This means each column takes an equal distribution of the free space in the container.

You can now span across columns to create grid areas with your desired widths.

For instance, if you want a "column" to be 60% wide, tell the grid item to span across six columns (span 6).

Another benefit of 1fr is that it gets applied after all fixed widths (such as gutters) are factored into the length of the row. This means you don't need to do any calculations for ten columns to fit.

Adrift
  • 58,167
  • 12
  • 92
  • 90
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Flexbox handles it pretty elegantly actually, just posted my flexbox answer. – BugsArePeopleToo Jun 11 '19 at 22:31
  • Yep, you made it work with flexbox. But I wouldn't call it elegant, as reducing the size of the items in order to create the gutters is a hack. The benefit of using the `gap` properties is that gutters can be created naturally. Hopefully, this feature will be available for flexbox soon. @BugsArePeopleToo – Michael Benjamin Jun 12 '19 at 02:52
  • @Michael_B thank you, I had read about Grid, but it seems like browser support is not 100%? It won't work on IE for example. – fredrik Jun 12 '19 at 05:58
  • But how does this work when I need other sized columns with 33.333% width for example,or any other decimal? – fredrik Jun 12 '19 at 06:09
  • Changing column lengths is actually quite simple with CSS Grid. It's what the module is designed for. https://jsfiddle.net/0oyap8fm/ – Michael Benjamin Jun 12 '19 at 11:41
  • Would this be correct for 38-62% ? https://jsfiddle.net/xeqd4bjp/ And how to make it work for IE and Opera Mini as well? – fredrik Jun 12 '19 at 16:47
-1

I would just do this with flexbox (https://yoksel.github.io/flex-cheatsheet/) and some margins, as there is no "perfect" or preferred way to do this I think.

Make sure you check the snippet also in fullscreen to see the %-wise separation of your columns.

/*




I need to create a grid that has 3 rows, each row has 2 columns.

    First row columns should be 40% - 60%
    Second row both columns should be 50%
    Third row first column should be 60%, second column 40%.

The columns should have a 10px gutter in between the columns, and for screen sizes smaller then 992px all columns should be 100% while still having a 10px "gutter".

(Underneath every 100% column except the last one should be 10px gutter). I am struggling on how to do this the best way.

*/
.row {
  display: flex;
  flex-flow: row nowrap;
  background-color: white;
  height: 100px;
}

.item1 {
  flex-basis: 40%;
  margin-right: 5px;
  background-color: red;
}

.item2 {
  flex-basis: 60%;
  margin-left: 5px;
  background-color: yellow;
}

.item3 {
  margin-right: 5px;
  flex-basis: 50%;
  background-color: blue;
}

.item4 {
  margin-left: 5px;
  flex-basis: 50%;
  background-color: pink;
}

.item5 {
  margin-right: 5px;
  flex-basis: 60%;
  background-color: grey;
}

.item6 {
  margin-left: 5px;
  flex-basis: 40%;
  background-color: brown;
}

@media(max-width: 992px) {
  .row {
    display: flex;
    flex-flow: row wrap;
    background-color: white;
    height: 100px;
  }
  .item1 {
    flex-basis: 100%;
    margin-right: 0px;
    background-color: red;
        margin-bottom: 10px;
  }
  .item2 {
    flex-basis: 100%;
    margin-left: 0px;
    background-color: yellow;
        margin-bottom: 10px;
  }
  .item3 {
    margin-right: 0px;
    flex-basis: 100%;
    background-color: blue;
        margin-bottom: 10px;
  }
  .item4 {
    margin-left: 0px;
    flex-basis: 100%;
    background-color: pink;
        margin-bottom: 10px;
  }
  .item5 {
    margin-right: 0px;
    flex-basis: 100%;
    background-color: grey;
        margin-bottom: 10px;
  }
  .item6 {
    margin-left: 0px;
    flex-basis: 100%;
    background-color: brown;
  }
}
<div class="row">
  <div class="item1"></div>
  <div class="item2"></div>
</div>
<div class="row">
  <div class="item3"></div>
  <div class="item4"></div>
</div>
<div class="row">
  <div class="item5"></div>
  <div class="item6"></div>
</div>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
DigitalJedi
  • 1,577
  • 1
  • 10
  • 29