Switching the order of block elements with CSS [duplicate]

Short Story

Let's say my HTML is already set in stone:

<div id="blockA">Block A</div>
<div id="blockB">Block B</div>
<div id="blockC">Block C</div>

It will look like this:

------------
| Block A  |
------------
| Block B  |
------------
| Block C  |
------------

Now I want to switch the order of the blocks. How can I do that with only CSS?

------------
| Block C  |
------------
| Block A  |
------------
| Block B  |
------------

I'm aware there's hacky solutions such as using position:absolute, but this doesn't preserve the effective use of the display:block property. That is, blocks push other blocks downward when they grow in size.

Long Story

When user uses a computer to view my webpage, the blocks are displayed in this order:

  1. General info.
  2. Event schedule.
  3. iPhone app advertisement

The iPhone app advertisement is placed last because it's not terribly important to computer users. A small percentage of computer users will whip out their phone and install the app.

If a mobile user comes to this site, the iPhone app advertisement should be the most important thing on the page. Therefore, it should be moved to the top:

  1. iPhone app advertisement
  2. General info.
  3. Event schedule.

I would like iPhone and computer users to share the same HTML, but have a CSS media query switch the order of the blocks.

@media only screen and (max-device-width: 480px) {
   #blockC {
      /* magic order switching */
   }
}

Solution 1:

Here is a "simple as possible" example, for changing the order of div-elements (when resizing the browser window):

<!DOCTYPE html>
<html>
  <head>
    <title>foobar</title>
    <style>
      @media screen and (max-width:300px){
        #parent{
          display:flex;
          flex-flow: column;
        }
        #a{order:2;}
        #c{order:1;}
        #b{order:3;}
      }
    </style>
  </head>
  <body>
    <div id="parent">
      <div id="a">one</div>
      <div id="b">two</div>
      <div id="c">three</div>
    </div>
  </body>
</html>

Example: http://jsfiddle.net/devnull/qyroxexv/ (change window-width to see the effect of changing the order of the divs)

Solution 2:

As has already been suggested, Flexbox is the answer - particularly because you only need to support a single modern browser: Mobile Safari.

See: http://jsfiddle.net/thirtydot/hLUHL/

You can remove the -moz- prefixed properties if you like, I just left them in for future readers.

    #blockContainer {
        display: -webkit-box;
        display: -moz-box;
        display: box;
        
        -webkit-box-orient: vertical;
        -moz-box-orient: vertical;
        box-orient: vertical;
    }
    #blockA {
        -webkit-box-ordinal-group: 2;
        -moz-box-ordinal-group: 2;
        box-ordinal-group: 2;
    }
    #blockB {
        -webkit-box-ordinal-group: 3;
        -moz-box-ordinal-group: 3;
        box-ordinal-group: 3;
    }
    <div id="blockContainer">
        <div id="blockA">Block A</div>
        <div id="blockB">Block B</div>
        <div id="blockC">Block C</div>
    </div>

Solution 3:

Update: Two lightweight CSS solutions:

Using flex, flex-flow and order:

Example1: Demo Fiddle

    body{
        display:flex;
        flex-flow: column;
    }
    #blockA{
        order:4;
    }
    #blockB{
        order:3;
    }
    #blockC{
        order:2;
    }

Alternatively, reverse the Y scale:

Example2: Demo Fiddle

body{
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
}
div{
    -webkit-transform: scaleY(-1);
    transform: scaleY(-1);
}