How can I reorder my divs using only CSS?

Given a template where the HTML cannot be modified because of other requirements, how is it possible to display (rearrange) a div above another div when they are not in that order in the HTML? Both divs contain data that varies in height and width.

<div id="wrapper">
    <div id="firstDiv">
        Content to be below in this situation
    </div>
    <div id="secondDiv">
        Content to be above in this situation
    </div>
</div>
Other elements

Hopefully it is obvious that the desired result is:

Content to be above in this situation
Content to be below in this situation
Other elements

When the dimensions are fixed it easy to position them where needed, but I need some ideas for when the content is variable. For the sake of this scenario, please just consider the width to be 100% on both.

I am specifically looking for a CSS-only solution (and it will probably have to be met with other solutions if that doesn't pan out).

There are other elements following this. A good suggestion was mentioned given the limited scenario I demonstrated—given that it might be the best answer, but I am looking to also make sure elements following this aren't impacted.


Solution 1:

This solution uses only CSS and works with variable content

#wrapper   { display: table; }
#firstDiv  { display: table-footer-group; }
#secondDiv { display: table-header-group; }

Solution 2:

A CSS-only solution (works for IE10+) – use Flexbox's order property:

Demo: http://jsfiddle.net/hqya7q6o/596/

#flex { display: flex; flex-direction: column; }
#a { order: 2; }
#b { order: 1; }
#c { order: 3; }
<div id="flex">
   <div id="a">A</div>
   <div id="b">B</div>
   <div id="c">C</div>
</div>

More info: https://developer.mozilla.org/en-US/docs/Web/CSS/order

Solution 3:

As others have said, this isn't something you'd want to be doing in CSS. You can fudge it with absolute positioning and strange margins, but it's just not a robust solution. The best option in your case would be to turn to javascript. In jQuery, this is a very simple task:

$('#secondDiv').insertBefore('#firstDiv');

or more generically:

$('.swapMe').each(function(i, el) {
    $(el).insertBefore($(el).prev());
});

Solution 4:

This can be done using Flexbox.

Create a container that applies both display:flex and flex-flow:column-reverse.

/* -- Where the Magic Happens -- */

.container {
  
  /* Setup Flexbox */
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;

  /* Reverse Column Order */
  -webkit-flex-flow: column-reverse;
  flex-flow: column-reverse;

}


/* -- Styling Only -- */

.container > div {
  background: red;
  color: white;
  padding: 10px;
}

.container > div:last-of-type {
  background: blue;
}
<div class="container">
  
  <div class="first">

     first

  </div>
  
  <div class="second">

    second

  </div>
  
</div>

Sources:

  • https://css-tricks.com/using-flexbox/
  • https://developer.mozilla.org/en-US/docs/Web/CSS/flex-flow#Browser_compatibility