3ocene 3ocene - 2 months ago 16
CSS Question

Change div order with CSS depending on device-width

I am working on a responsive site and came across an interesting problem. I have some divs side by side. There could be anywhere from 2 to 6 or so of them. When the screen isn't wide enough to show all the content properly, the divs stack vertically. Simple enough to do with CSS.

The problem is, I need them to be in a different order depending on the layout. This is easy to do with 2 or 3 divs (Changing divs order based on width), but significantly more challenging when you add a fourth.

I could use

position: absolute;
and manually set the position, however this causes the parent to shrink and not contain them properly.

To make this even more complicated, I can't use JavaScript.

Working with two columns:



(untested)

HTML:

<div id="container">
<div class="column-half column-half-2">
First div on mobile, right div on desktop
</div>
<div class="column-half column-half-1">
Second div on mobile, left div on desktop
</div>
</div>


CSS:

.container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 20px;
position: relative;
}
.column-half {
display: table-cell;
padding: 25px;
vertical-align: top;
width: 40%;
}
.column-half-1 {
float: left;
}
.column-half-2 {
float: right;
}


HTML, with 4 columns:



<div id="container">
<div class="column-quarter column-quarter-3">
First div on mobile, third div on desktop
</div>
<div class="column-quarter column-quarter-2">
Second div on mobile, second div on desktop
</div>
<div class="column-quarter column-quarter-1">
Third div on mobile, first div on desktop
</div>
<div class="column-quarter column-quarter-4">
Fourth div on mobile, fourth div on desktop
</div>
</div>

Answer Source

This is doable in CSS thanks to the wonderful flexbox spec. Using the order and flex-flow properties, we can achieve what you want. Unprefixed, IE11 and all evergreen browsers will support this. IE10 prefixes -ms-order and doesn't support flex-flow.

The solution takes into consideration all the constraints you listed:

  • Have a list of elements in a given order displayed as a row.
  • When the window is too small, change them to display in a column.
  • Change the order of the elements when they are displayed in a column.

Because of the limitations of Stack Snippets, you'll need to view the demo in Full page mode, and resize your browser to see the effect.

.container div {
    width: 100px;
    height: 50px;
    display: inline-block;
}

.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }

@media screen and (max-width: 531px) {
    .container { display: flex; flex-flow: column; }
    .five { order: 1; }
    .four { order: 2;  }
    .three { order: 3; }
    .two { order: 4; }
    .one { order: 5 }
}
<div class="container">
    <div class="one">I'm first</div>
    <div class="two">I'm second</div>
    <div class="three">I'm third</div>
    <div class="four">I'm fourth</div>
    <div class="five">I'm fifth</div>
</div>

Alternatively, here is a JSFiddle demo.