Switching the order of block elements with CSS

HtmlCss

Html Problem Overview


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 */
   }
}

Html Solutions


Solution 1 - Html

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 - Html

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 - Html

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);
}

Solution 4 - Html

I known this is old, but I found a easier solution and it works on ie10, firefox and chrome:

<div id="wrapper">
  <div id="one">One</div>
  <div id="two">Two</div>
  <div id="three">Three</div>
</div> 

This is the css:

#wrapper {display:table;}
#one {display:table-footer-group;}
#three {display:table-header-group;}

And the result:

"Three"
"Two"
"One"

I found it here.

Solution 5 - Html

This method worked for me without flexbox:

#blockA,
#blockB,
#blockC {
    border: 1px solid black;
    padding: 20px;
}


.reverseOrder,
#blockA,
#blockB,
#blockC {
    -webkit-transform: rotate(180deg);
       -moz-transform: rotate(180deg);
        -ms-transform: rotate(180deg);
         -o-transform: rotate(180deg);
            transform: rotate(180deg);
}

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

Solution 6 - Html

HTML:

<div id="blockC second-order">Block C</div>
<div id="blockA">Block A</div>
<div id="blockB">Block B</div>
<div id="blockC first-order">Block C</div>

CSS

.second-order {
     display: none;
}

@media only screen and (max-device-width: 480px) {
     .first-order: {
         display: none;
     }

     .second-order: {
         display: block;
     }
}

I think this is non-stupid solution becouse repeating content is no problem in the most of cases and in your case if it is advertisment you would repeat not a lot of content.

I've answers on this question althought one year passed, becouse I was searching for solution, I read this and got this idea.

Solution 7 - Html

<div id="container">
    <div id="a">Block A</div>
    <div id="b">Block B</div>
    <div id="c">Block C</div>
</div>

lets say the height of a block is 100px

#container     {position:relative; height: 300px;}
#a, #b, #c     {position:absolute; height: 100px}
#c             {top: 0px;}
#b             {top: 100px;}
#a             {top: 200px;}

Solution 8 - Html

I managed to do it with CSS display: table-*. I haven't tested with more than 3 blocks though.

fiddle

Solution 9 - Html

You could mess with the margins: http://jsfiddle.net/zV2p4/

But you would probably be better off using position: absolute. This does not change display: block, but it will make the width auto. To fix this, make the divs width: 100%

Solution 10 - Html

Possible in CSS3: http://www.w3.org/TR/css3-writing-modes/#writing-mode

Why not change the orders of the tags? Your HTML page isn't made out of stone, are they?

Solution 11 - Html

Hows this for low tech...

put the ad at the top and bottom and use media queries to display:none as appropriate.

If the ad wasn't too big, it wouldn't add too much size to the download, you could even customise where the ad sent you for iPhone/pc.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoJoView Question on Stackoverflow
Solution 1 - HtmldevnullView Answer on Stackoverflow
Solution 2 - HtmlthirtydotView Answer on Stackoverflow
Solution 3 - HtmlSW4View Answer on Stackoverflow
Solution 4 - HtmlSertageView Answer on Stackoverflow
Solution 5 - HtmlValentinVoileanView Answer on Stackoverflow
Solution 6 - HtmlkspacjaView Answer on Stackoverflow
Solution 7 - HtmlfcerutiView Answer on Stackoverflow
Solution 8 - HtmlyodaView Answer on Stackoverflow
Solution 9 - HtmlWillView Answer on Stackoverflow
Solution 10 - HtmldppView Answer on Stackoverflow
Solution 11 - HtmlControl FinkView Answer on Stackoverflow