3

I am trying to build this layout:

Desired 2-column layout

I used float: left for the boxes in the left side and float: right for the ones in the right.

The problem is that every right-floated box is aligning it's top with the the previous left-floated element.

Thus all I get is this:

Actual 2-column layout

HTML:
I need to keep the elements in this order (box1, box2, ... box7)

<div class="container">
  <div class="box box1 left green">
    BOX 1 (big) Lorem ipsum (...)
  </div>
  <div class="box box2 right orange">
    BOX 2 (small) 
  </div>
  <div class="box box3 right blue">
    BOX 3 (small) 
  </div>
  <div class="box box4 left pink">
    BOX 4 (big) Lorem ipsum (...)
  </div>
  <div class="box box5 right yellow">
    BOX 5 (small)
  </div>
  <div class="box box6 left teal">
    BOX 6 (big) Lorem ipsum (...)
  </div>
  <div class="box box7 right purple">
    BOX 7 (small)
  </div>
</div>

DEMO: https://codepen.io/constagorgan/pen/vjLJzG

Other considerations:

  • On smaller devices the boxes should be merged in a single column, same as using col-*-12 in Bootstrap, but keeping same ordering (box1, box2, ... box7)
  • I can use Bootstrap, Masonry, Bulma or other library that helps building grids / layouts as long as it's supported by IE11, Chrome and Firefox
  • A CSS-only solution would be absolutely fantastic.
  • I don't want to use display: table. Reasons for this are given here.

What I've tried so far:

  • Using Bootstrap → I cannot make it responsive for small screens without moving things around inside the DOM.
  • Using Masonry → I couldn't find a way to order the boxes. They are just positioning themselves in the closest available place.
  • Using flex → I got stuck in a similar situation.
  • Using CSS grid layout → It's not fully supported on IE11.
  • Using CSS columns → I need a 70%|30% ratio. This is designed for 50%|50%.

How can I remove those white gaps from the layout? Can I achieve this with floated elements? If not, what's the proper way to do it?

EDIT: I need to make it responsive. On smaller screen I need to stick with this one-column layout (as I mentioned in the "Other considerations" section.

Mobile 1-column layout

Asons
  • 84,923
  • 12
  • 110
  • 165
Consta Gorgan
  • 549
  • 6
  • 22
  • 1
    Not possible with floats. You'd have to change the HTML. But `display: table` is not the same as "use tables for layout". Short answer: use table layout if it's a solution. The idea behind not using HTML table layouts is that your HTML is supposed to describe your information and if your information is not a table then why use a table to describe it? CSS `display: table` on the other had has nothing to do with your markup, it's presentation only, do whatever you want with it. – Sergiu Paraschiv Apr 23 '18 at 16:35
  • Can the html be modifyed? – Gerardo BLANCO Apr 23 '18 at 16:36
  • I agree with @SergiuParaschiv. `display:table` is not the same thing as ``. And people get so worked up about this that they forget that even `
    ` is perfectly fine if you have a tabular layout, which you do.
    – Scott Marcus Apr 23 '18 at 16:39
  • what if you create two column, one for large text and one for small text. – Ravi Sevta Apr 23 '18 at 16:42
  • @SergiuParaschiv the thing is that I need to switch to another layout on smaller screens. I need to keep the same order (box1, box2, ... box7) but show them in a single column (as Bootstrap does when using `col-*-12`). I don't see how I can achieve this by using ``. Maybe you do?
    – Consta Gorgan Apr 23 '18 at 16:43
  • @GerardoBLANCO the HTML can be modified only by adding / removing classes or adding other elements to it but I need to maintain the current boxes and their ordering – Consta Gorgan Apr 23 '18 at 16:45
  • 1
    @ConstaGorgan If you use CSS `display:table` in your media query for large viewports, you can then have a different (single column) layout in another media query for small viewports. Very simple. – Scott Marcus Apr 23 '18 at 16:45
  • You use media queries and only apply the table layout on large screens. (as @ScottMarcus just said :) ) – Sergiu Paraschiv Apr 23 '18 at 16:45
  • But can i add 2 divs to contain each column. This will help for a flexbox design – Gerardo BLANCO Apr 23 '18 at 16:47
  • @ScottMarcus I don't see how I can keep the layout in the first image for big screens and change to a single-column layout on smaller ones maintaining their HTML order in the same time (box1, box2, ... box7) – Consta Gorgan Apr 23 '18 at 16:49

2 Answers2

3

If you combine Flexbox and float, you can do like this, where on narrower screens make use of the Flexbox property order.

By initially add the smaller elements first, you can simply float and clear them and they will align right, in a column of their own.

When the media query kicks in, remove float, add display: flex and order them 1-7.

Updated codepen

Stack snippet

.left {
  width: 75%;
}
.right {
  float: right;
  width: 25%;
  clear: right
}

.green { background-color: #90EE90; }
.blue { background-color: #20B2AA; }
.orange { background-color: #FFA07A; }
.pink { background-color: #FFB6C1; }
.yellow { background-color: #FFD700; }
.teal { background-color: #00CED1; }
.purple { background-color: #9370DB; }

@media (max-width: 500px) {
  .left, .right {
    float: none;
    width: 100%;
  }
  .container {
    display: flex;
    flex-direction: column;
  }

  .container .box1 { order: 1 }
  .container .box2 { order: 2 }
  .container .box3 { order: 3 }
  .container .box4 { order: 4 }
  .container .box5 { order: 5 }
  .container .box6 { order: 6 }
  .container .box7 { order: 7 }
}
<div class="container">
  
  <div class="box box2 right orange">
  BOX 2 (small) 
  </div>
  
  <div class="box box3 right blue">
  BOX 3 (small) 
  </div>

  <div class="box box5 right yellow">
  BOX 5 (small)
  </div>

  <div class="box box7 right purple">
  BOX 7 (small)
  </div>

  <div class="box box1 left green">
  BOX 1 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum. Integer luctus dolor quis condimentum mollis.
  </div>

  <div class="box box4 left pink">
  BOX 4 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum. 
  </div>

  <div class="box box6 left teal">
  BOX 6 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum.
  </div>

</div>

If you can't change markup, you need script, where you either hook up on the resize event, or as here, the window.matchMedia event.

Stack snippet

document.addEventListener("DOMContentLoaded", function(event) {

  var container = document.querySelector('.container');
  var items = document.querySelectorAll('.container .box');

  var reorderitems = function(matched) {
    if (matched) {
      container.appendChild(items[0]);
      container.appendChild(items[3]);
      container.appendChild(items[5]);
    } else {
      container.insertBefore(items[2], items[3]);
      container.insertBefore(items[1], items[2]);
      container.insertBefore(items[4], items[5]);
      container.appendChild(items[6]);
    }
  }
  reorderitems(window.outerWidth > 500);

  window.matchMedia("(min-width: 501px)").addListener(function(e) {
    if (e.matches) {
      reorderitems(true);
    } else {
      reorderitems(false);
    }
  });
});
.left {
  width: 75%;
}

.right {
  float: right;
  width: 25%;
  clear: right
}

.green {
  background-color: #90EE90;
}

.blue {
  background-color: #20B2AA;
}

.orange {
  background-color: #FFA07A;
}

.pink {
  background-color: #FFB6C1;
}

.yellow {
  background-color: #FFD700;
}

.teal {
  background-color: #00CED1;
}

.purple {
  background-color: #9370DB;
}

@media (max-width: 500px) {
  .left,
  .right {
    float: none;
    width: 100%;
  }
}
<div class="container">

  <div class="box box1 left green">
    BOX 1 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci
    in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum. Integer luctus dolor quis condimentum mollis.
  </div>

  <div class="box box2 right orange">
    BOX 2 (small)
  </div>

  <div class="box box3 right blue">
    BOX 3 (small)
  </div>

  <div class="box box4 left pink">
    BOX 4 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci
    in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum.
  </div>

  <div class="box box5 right yellow">
    BOX 5 (small)
  </div>

  <div class="box box6 left teal">
    BOX 6 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci
    in, efficitur pulvinar ipsum.
  </div>

  <div class="box box7 right purple">
    BOX 7 (small)
  </div>

</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • 1
    Brilliant answer! I selected yours. Clear, concise, older browser support with 2 code examples. Who could ask for anything more? – Consta Gorgan Apr 23 '18 at 20:07
0

You need to create two new Divs to group the boxes at each side:

<div class="container">

  <div class="group box left">

  <div class="box box1 green">
  BOX 1 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum. Integer luctus dolor quis condimentum mollis.
  </div>

  <div class="box box4 pink">
  BOX 4 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum. Praesent pretium nisl quis ante accumsan sagittis. Nullam ac tortor quis turpis dictum fringilla ut non arcu. Praesent eget tellus vitae leo malesuada condimentum. 
  </div>    

  <div class="box box6 teal">
  BOX 6 (big) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vel eros non odio varius efficitur. Aliquam vel dui iaculis, imperdiet odio ut, posuere nulla. Maecenas rutrum nibh sit amet sem congue ornare. Donec tellus ipsum, pulvinar sed orci in, efficitur pulvinar ipsum.
  </div>    

  </div>

  <div class="group box right">

    <div class="box box2 orange">
  BOX 2 (small) 
  </div>

  <div class="box box3 blue">
  BOX 3 (small) 
  </div>

  <div class="box box5 yellow">
  BOX 5 (small)
  </div>

  <div class="box box7 purple">
  BOX 7 (small)
  </div>    

  </div>

</div>
Amc
  • 88
  • 7
  • 1
    I don't think he wants to make this radical change to the HTML. – Sergiu Paraschiv Apr 23 '18 at 16:44
  • I've edited my answer to explain it better. It's important to keep the HTML structure in a valid state for a single-column layout on smaller screens. And I must keep the boxes in chronological order (box1, box2, ... box7). – Consta Gorgan Apr 23 '18 at 16:59
  • @Amc Your answer is helpful for the 2-column layout but fails for the single-column. It's not maintaining the chronological order. **Desired:** _box1, box2, ... box7_. **Actual:** _box1, box4, box6, box2, box3, box5, box7_. But thanks! I appreciate you taking the time to write the answer. – Consta Gorgan Apr 23 '18 at 17:03