tags:

views:

2571

answers:

4

Problem: how to combine fixed heights with flexible page layout?

  • "bodyDiv" height needs to be : 100% of ( window.innerWidth less ?px ).
  • "a" & "b" height need to be : 50% of ( body.div.height less ?px ).


<HTML>
    <body>
        <div id="headerDiv" style="height:?px">fixed height</div>
        <div id="bodyDiv" style="height:100%">flexible height
            <div id="a" style="height:50%">flexible height</div>
            <div id="x" style="height:?px">fixed height</div>
            <div id="b" style="height:50%">flexible height</div>
            ...
        </div>
    </body>
<HTML>


It's been fully worked out in JavaScript, but it looks terrible on page load and resize events because it's too slow, even though I've given my best to optimize this for speed.

CSS expressions are not an option either, since to my knowledge that would be restricted to IE 5-7 anyway.

So, after spending 3 days trying to fix this by using any combination of negative and positive margins, I finally have to admit defeat by finally asking for public help.

Thanks for reading this! Jörg Schaper

A: 

I'm afraid it can't be done with pure CSS/HTML. I would be the happiest if I were wrong. There have been several related questions on SO (haven't read them all, some of them might touch slightly different problems):

  1. http://stackoverflow.com/questions/90178/make-a-div-fill-the-remaining-screen-space
  2. http://stackoverflow.com/questions/147528/how-to-force-a-div-block-to-extend-to-the-bottom-of-a-page-even-if-it-has-no-con
  3. http://stackoverflow.com/questions/206652/how-to-create-div-to-fill-all-space-between-header-and-footer-div
  4. http://stackoverflow.com/questions/572783/how-can-i-scale-a-div-to-100-height-and-width-inside-of-another-element

There are various "solutions", but neither of them are perfect. Let me know if you figured out a better way to solve this.

David Hanak
+4  A: 

At the risk of loosing my reputation.

I would suggest doing something like this:

<table style="height:100%;width:100%">
  <tr style="vertical-align:top;height:50px;background-color:#faa;">
    <td>Fixed</td></tr>
  <tr style="vertical-align:top;background-color:#afa;">
    <td>Flexible</td></tr>
  <tr style="vertical-align:top;height:100px;background-color:#faa;">
    <td>Fixed</td></tr>
  <tr style="vertical-align:top;background-color:#afa;">
    <td>Flexible</td></tr>
</table>

This will offend the layout v semantics purists, but it gets the job done and will save you days of messing around with divs and CSS.

P.S This is just an illustration, the styles should really be in an external style sheet and linked by element id's.

Noel Walters
+1 Even though it may offend some purits, it's short, simple, readable, and will work in most browsers.
Tracy Probst
Hello Noel,this was just what the doctor ordered.I'm glad you risked your reputation, because it does exactly what I want.I'll post the full solution to my problem, consisting of both your and my own approach as soon as I got my user id. Thanks! Jörg Schaper
Thanks for the feedback Jörg. Looking forward to your full solution. ---- I generally try to avoid using tables for layout, but sometimes it can't be avoided. ---- Oh, and reputation schmeputation.
Noel Walters
A: 

The following does exactly what I want, which is:

  • page is exactly 100% in width and height
  • header and footer are fixed in height
  • all other elements are flexible in width and height
  • flexible sizes ares stated in amounts totalling 100%
  • static sizes are stated in pixels
  • no javascript needed for page load/resize
  • no css expressions needed for page load/resize
  • no ugly page repaint delay on page load event
  • no ugly page repaint delay on resize event
  • script for splitters will be simple because of 4) and 5)


<html>
  <style type="text/css" media="all">
    html,body,table,div{height:100%;width:100%;}
    html * {outline:0;border:0;margin:0;padding:0;border-collapse:collapse;border-spacing:0;}
    div{float:left}
  </style>
  <body>
    <table>
      <tr style="height:100px;background-color:red;"><td>Fixed</td></tr>
      <tr style="height:100%;"><td>
        <div style="width:25%;margin-right:-4px;background-color:green;">Flexible</div>
        <div style="width:8px;background-color:silver;cursor: e-resize;"></div>    
        <div style="width:50%;margin-right:-4px;margin-left:-4px;background-color:blue;">Flexible</div>
        <div style="width:8px;background-color:silver;cursor: e-resize;"></div>  
        <div style="width:25%;margin-left:-4px;">
          <div style="height:33.33%;margin-bottom:-4px;margin-top:-0px;background-color:green;">Flexible</div>
          <div style="height:8px;background-color:silver;cursor: n-resize;"></div>          
          <div style="height:33.33%;margin-bottom:-4px;margin-top:-4px;background-color:blue;">Flexible</div>
          <div style="height:8px;background-color:silver;cursor: n-resize;"></div>          
          <div style="height:33.33%;margin-bottom:-0px;margin-top:-4px;background-color:yellow;">Flexible</div>
        </div>
      </td></tr>
      <tr style="height:20px;background-color:red;"><td>Fixed</td></tr>
    </table>
  </body>
</html>


This solution was made possible by the help of Noel Walters (table approach), and myself (divs with negative margins). Thanks Noel. Wasn't able to vote your answer up, though, as I still haven't received conformation for my user id!


I'd liked to have done this via divs and css only just like David suggested, but as stated in my original post I just wasn't "able". Will read the links that you suggested, and let you know about the "perfect" solution in case I manage to work it out. Thanks for those links, Dave.


New minor problem: splitters need to be 4px wide/high, and they are. Curiously enough, I had to use 8px for the splitters, and -4px * 2 for negative margins of surrounding elements, though. Any suggestions?


A: 

Well this is the same never-ending-story about tables vs. css for layout. CSS purist would even say CSS layouts are faster to download? faster to be rendered by the browser? less code??? In real life, and having the "visual" styles in a proper CSS sheet, table layouts have much less characters than doing the same with CSS. Dont believe it? Just try to do a full browser height, fixed width, horizontally centered, header/2 columns content/footer simple layout with CSS and with tables... get the code, paste in Word and do a word count. CSS code is no shorter than x2 times bigger than the table code! Tell me, how many CSS stuff do you need to do to replicate a 100% width 100% height text in the middle of the screen layout, simple as:

Some text

or

  • { margin:0px; padding:0px;
    }

html, body { height:100%; min-height: 99%; }

.test { border: 1px solid #cccccc; height:100%; position:relative; }

.test2{ display:inline; height:24px; width:24px; left:50%; top:50%; }

test

So CSS is better for layout because what? Easier to maintain? Tell me how many times would anyone tweak the layout of a page when is completely finished and working? Unless no wife/husband at reach :D Less code? yeah right, "more" is "less" right, like 1 is 0? Better design/code separation? Sure, your design do not need those DIVs or SPANs or P or whatever tags you want.

I always think: use hybrid code for do whatever you want in less time to render the way you want, no matter if css or tables or css + tables! For me, tables as for layout are the best, css for optimizing and rendering visuals. At the end, clients wont care a cucumber if their sites are made with css or with tables or with wood and nails. :) Tell me a good reason why should I use a pure CSS approach to get say a 3 columns totally centered by the width, fixed middle column, full browser height WITHOUT having CSS tweaks, fixes, hacks... everybody working really into website creation knows tables rendering is more visual consistent and less code needed than CSS among all the browsers around.

Quick test :) test would this work alone??