1

Is there a common CSS layout technique for controlling the vertical source order of a page?

For example, can I change this...

<container>
    <header></header>
    <content></content>
    <footer></footer>
</container>

...to this...

<container>
    <content></content>
    <header></header>
    <footer></footer>
</container>

...while still having the <header> appear at the top of the page, above the <content>?

In other words, I'd like to apply the techniques used for controlling horizontal source order, such as "One True Layout" and "Holy Grail", to the vertical source order of the page.

This question asks essentially the same thing, but the responders didn't seem to get what was being asked and the asker's solution seems cumbersome.

I might get criticism for micro-optimizing, but Mega Menus and responsive design keep pushing my page content down further and further.

Community
  • 1
  • 1
cantera
  • 24,479
  • 25
  • 95
  • 138
  • I send to my answer there: http://stackoverflow.com/questions/7425665/switching-the-order-of-block-elements-with-css/14428249#14428249 – kspacja Jan 20 '13 at 19:22

4 Answers4

3

Littlefool's answer works well if you know the height of the block you are moving (if you are swapping two blocks, it's sufficient for either of them to have a fixed height).

However it doesn't help if the blocks all have flexible height. In that case you can try the technique from http://tanalin.com/en/articles/css-block-order/:

<div class="container">
    <div class="block-1">1st block</div>
    <div class="block-2">2nd block</div>
    <div class="block-3">3rd block</div>
</div>
<style>
    .container { display: table; width: 100%; }
    .block-1 { display: table-footer-group; } /* Will display at the bottom. */
    .block-2 { display: table-row-group;    } /* Will display in the middle. */
    .block-3 { display: table-header-group; } /* Will display at the top. */
</style>

(see demo: http://jsbin.com/etujad/11/edit)

Caveats:

  1. It only works for up to 3 blocks (you may be able to achieve more by nesting).

  2. It doesn't work in IE6/7, and there are some wrinkles in IE8.

  3. Many browsers (except Firefox?) don't allow replaced elements like images to be given these display values (testcase), so you'd have to wrap them in a div and reorder the div instead.

You could either supplement this with JavaScript for old IE, or depending on the design it might be acceptable to just leave the blocks in the wrong order in old IE (note that very few smartphones run old versions of IE, as even Windows Phone 7.5 runs IE9, so this is a good option if you're only swapping the source order on mobile devices).

John Mellor
  • 12,572
  • 4
  • 46
  • 35
2

You cannot alter the source of a page with CSS. You can, to some mild degree, alter the HTML output, but not in this way.

The order of elements in an HTML document has meaning. So typically it won't make sense for your source to have a heading which comes after its related content. It is the order which defines that relationship in many cases.

What you can do is use CSS techniques to lay out these elements visually so that they appear to be in different order.

But their vertical order in HTML should be semantically logical.

  • Thanks - I've come to this conclusion as well, especially after studying the HTML5 Document Outline Algorithm – cantera Oct 22 '12 at 17:17
2

You should know that searching for "the holy grail" is quite useless. Although I can understand why you want to have the content section in front. Usually search engines index the pages on the content as they appear in html. Having first a bunch of headers and other things won't do any good.

I haven't had time to look into HTML5 and CSS3 yet, but it is quite possible to alter your layout with only css. I'm a developer so my css and html skills are less then real web producer but you can play around with the position properties in CSS.

<div id="content">this is your content</div>
<div id="header">this is the header</div>
<div id="footer">this is your footer</div>

This html can still show the header tag on top of your page with the following css.

    #header
    {
        height:100px;
        width:100%;
        background-color:Red;
        position:absolute;
        top:0;
    }
    #content
    {
        margin-top:100px;
        height:500px;
        background-color:Green;
    }
    #footer
    {
        height:100px;
        background-color:Blue;
    }

I hope it gives you an idea of what is possible. (since you mention HTML5 I suppose you don't need to worry about older browsers but only the latest releases).

Ronald
  • 1,990
  • 6
  • 24
  • 39
  • Beat me to posting an almost identical solution. The one thing to note about this, it requires a fixed height on the header to work. Also, with a container element, it's position needs to be set to `relative` and I've found it is better to set the `padding-top` on it rather than the `margin-top` on the `#content`. – ScottS May 04 '12 at 19:00
  • Yes this is indeed a disadvantage. If it really needs to be flexible (like RIA-flexible) you need to write a javascript that will calculate every container div on resize (have done such thing before). But I think it gives an idea that it's possible ;) – Ronald May 04 '12 at 19:13
  • BTW: "holy grail" refers to the CSS technique with that name, not my objective (see article: http://alistapart.com/article/holygrail). – cantera Feb 17 '14 at 17:45
2

You can use the old friend display:table to re order your element.

Lets say this is your source.

<div id="container">
    <div id="header"></div>
    <div id="content"></div>
    <div id="footer"></div>
</div>

In order to reorder try this.

   #container{
      display: table;
   }

   #content{
     display: table-header-group;
   }

    #header{
     display: table-row-group;
   }

    #footer{
     display: table-footer-group;
   }

bam. you got it. Here is the proof of concept. http://jsfiddle.net/k0La8egp/1/

Hasanavi
  • 8,455
  • 2
  • 29
  • 35