On two separate occasions this month, I’ve been required to produce a layout in which a fixed-width scrolling side “pane” and flexible scrolling main “pane” must resize to fill all available space in a browser window.
As a CSS purist, I’ve always tried to avoid such dynamic layouts, but sometimes they’re required. When they are, I like to have a good old grumble about the fact that I’ve resorted to using JavaScript for my layouts.
The most advanced way of achieving such a layout is to use a JavaScript toolkit such as DOJO—but for what I was trying to achieve, even DOJO felt too bloated and seemed liable to create further complications.
We can, of course, achieve these layout goals by using JavaScript to resize the div
s every time the page is loaded or resized. Unfortunately—among other headaches—that’s made more complicated by the choices between window.innerHeight
and document.documentElement.clientHeight
and document.body.clientHeight
, and the need for cross-browser event listeners.
It seems that using JavaScript is an attainable but inelegant solution for this layout. What I really want is a lightweight, easy-to-understand, pure CSS template…
The problem with percentages#section2
We often use elements that have dynamic widths and heights by defining those attributes as percentages. But there’s a problem with percentages: they don’t play well with others. Despite everyone’s best attempts, you just can’t mix up pixels and percentages (although I’ve read rumors that it’s in the cards).
While we can create relatively effective layouts using just percentages, we can’t then have a fixed-width side panel or a fixed-height header. So percentages just aren’t going to do the job in our layout.
The nature of divs#section3
Adopting a tried and tested philosophical technique, I went back to the basic assumptions to try and find something else I’d missed. I realized that I thought the following statements about div
s were all true:
In all browsers#section4
- A
div
is rectangular. - Only one corner of a
div
can be absolutely positioned on a page. - The location of the diagonally opposing corner must be determined by the width and height of the
div
. - If the width and height are dynamic, they must be determined using JavaScript.
It struck me that assumption no. 2—that only one corner of a div
can be absolutely positioned on a page—should be very easy to either confirm or deny. What happens if we absolutely position a div
by defining its top
, left
, bottom
, and right
properties, all at the same time? After all, although I think of it as being a “conflict,” it’s actually perfectly valid CSS.
Assigning “conflicting” absolute positions#section5
I had assumed that if you assigned top
, left
, bottom
, and right
properties that most browsers would simply ignore two of those properties.
It seemed like a fair assumption at the time. I expected some variation between the browsers, but I also expected all of them to ignore two of the four positions.
I was utterly wrong about that. What actually happens is something rather magical. In every browser I tested, with the exception of IE5 and IE6, all four rules are obeyed. The result is that the div
is effectively “stretched” to fill the viewport.

A bit of research revealed that I’m certainly not the first person to discover this.
“In browsers that support CSS you can specify all four edges and let the browser compute the width and the height. Unfortunately this doesn’t work in Internet Explorer…”
“Technically you can use both a
right
and aleft
property and leave thewidth
asauto
. But unfortunately IE does not support this…”
In general, this little bit of CSS trickery seems to have been discarded due to its incompatibility with IE5 and IE6, and as a result has remained largely unnoticed, although it’s nice to see that IE7 now supports these “conflicting” absolute positions.
Incompatibility doesn’t make the discovery useless. Our original statements may still apply to IE5 and IE6, but we now have a different set of statements for all other browsers.
In all browsers except for IE5 and IE6#section6
- A
div
is rectangular. - All four corners of a
div
can be absolutely positioned on a page. - If the location of diagonally opposing corners has been determined the width and height is implied.
An alternative solution for IE#section7
What does this mean? It means our assumption that only one corner of a div can be absolutely positioned on a page creates a problem specifically for IE5 and IE6. As it turns out Internet Explorer actually offers us its own alternative. Earlier on, I said that you can’t mix pixels and percentages, but that wasn’t strictly true: you can in Internet Explorer.
Using the power of dynamic properties, it is now possible to declare property values not only as constants, but also as formulas.
Dynamic properties are undeniably powerful, but as they’re only supported in IE, they tend to be of little real use.
But, once again, incompatibility isn’t a reason for discarding this little trick. Being able to determine the width and height of our div
s as a formula means we can specify “the width of the page minus 40px.” As long as we can do that in IE5 and IE6, we can modify our original assumption #4 just a little bit and settle on our final set of statements.
In IE5 and IE6#section8
- A
div
is rectangular. - Only one corner of a
div
can be absolutely positioned on a page. - The location of the diagonally opposing corner must be determined by the width and height of the
div
. - The width and height can be determined using dynamic properties.
In all other browsers:#section9
- A
div
is rectangular. - All four corners of a
div
can be absolutely positioned on a page. - If the location of diagonally opposing corners has been determined, the width and height is implied.
Ah! Now that’s much more like it. As long as all of the above statements are true, we really should be able to put our entire template together using (almost) pure CSS.
Putting it all together#section10
Our wonderfully simple HTML looks like this:
<body>
<div id="header">
<p>Our header</p>
</div>
<div id="side">
<p>Our side panel</p>
</div>
<div id="right">
<p>Our main panel</p>
</div>
</body>
In modern browsers#section11
Our CSS for all modern browsers is now strikingly simple.
- We specify the width and height of the body as 100%. (This is actually only needed for our Internet Explorer solution, but there’s absolutely no harm in including it in our main CSS.)
- We hide the overflow in the
body
andhtml
because we never want to see those scroll bars again. - We set the
overflow
to “auto” for the left and right panels, and hide it in the header. - The header has a width of 100% and a constant height of 80px.
- For the side panel we specify the
top
(header height + padding),left
(padding), andbottom
(padding) positions. Then we give it a constant width of 200px. - For the right panel we specify the
top
(header height + padding),left
(padding + side panel width padding),right
(padding) andbottom
(padding) positions.
All of that is very easily translated into the following CSS:
<style type=”text/css”>html {
overflow: hidden;
}body {
overflow: hidden;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}#header {
padding: 0;
margin: 0;
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 80px;
overflow: hidden;
}#side {
padding: 0;
margin: 0;
position: absolute;
top: 100px;
left: 20px;
bottom: 20px;
overflow: auto;
width: 200px;
}#main {
padding: 0;
margin: 0;
position: absolute;
top: 100px;
left: 240px;
right: 20px;
bottom: 20px;
overflow: auto;
}</style>
Creating the exception for IE5 and IE6#section12
In IE5 and IE6 the bottom
and right
attributes of the main and left panels are just ignored.
This means that the top left corner is still pinned in place for each of our div
s, and we just need to define our widths and heights.
We want the height of both the main panel and the side panel to be 100% of the height of the page minus the header height and the top and bottom padding (100%-80px-20px-20px).
We want the width of the main panel to be 100% of the width of the page minus the width of the side panel, the left padding, the right padding, and the gutter padding (100%-200px-20px-20px-20px). The width of the side panel is a constant, and has already been defined, so nothing needs adding here.
By using a conditional comment we can include these expressions for IE5 and IE6. (Line wraps marked » —Ed.)
<!--[if lt IE 7]>
<style type="text/css">
#side {
height:expression(document.body.clientHeight-120); »
/* 80+20+20=120 */
}
#main {
height:expression(document.body.clientHeight-120); »
/* 80+20+20=120 */
width:expression(document.body.clientWidth-260); »
/* 200+20+20+20=260 */
}
</style>
<![endif]-->
Don’t forget: we specifically had to set the height and width of the body to 100% for this to work, but we didn’t need to hide that from other browsers, so it’s included in the main style sheet.
Beautiful#section13
And there we have the finished layout.
Okay, those dynamic expressions aren’t valid, but they are at least hidden from the browsers that don’t need them. Although they’re presented as CSS those dynamic expressions are in truth JavaScript, and as such they won’t work in IE5 and IE6 if JavaScript is turned off.
But then, none of the alternative solutions would work in that situation either.
{Although this technique was developed independently, an article that suggested many of the same methods was published in 2004 by Alex Robinson. —Ed.}
Known issues#section14
There’s a small and annoying bug in Opera 8. Although the side div
resizes correctly when the page first loads, it doesn’t dynamically resize when the window size is changed.
This seems to be because we’ve given it a constant width, and I have, so far, been unable to find a way around this issue. Happily, it’s fixed in Opera 9, and it isn’t a particularly critical bug to begin with.
Yet again we are limited by IE, and et again we have to implement another hack…
That is *sweet*. I had no idea you could do that, now I’m going “I wonder where I could use that…”
Ta muchly!
Doesn’t anybody ever read the specification? This magical surprising feature of CSS is very clearly defined. I’m only a college student working towards a computer science degree, and I’ve never worked on web design for anybody else, but even I knew about this.
Why is it that even on a site devoted to web design, none of the web developers know very much about the languages and APIs they’re using? I understand that web design is more artistic than programming, and as such web developers shouldn’t be expected to be as technically proficient, but if you’re going to make a living using something you should know something about it.
It always amazes me what poor programmers most web developers make. Are the two skills mutually exclusive or something? I know I’m certainly not very good at making a web page look very pretty.
James – it’s not just a matter of reading the specs, it takes time and effort to test each feature against each browser to see whether it is actually supported (many aren’t) and what workarounds, if any, are needed.
Rob,
thanks very much for that. I can have a three column, equal height layout, with a header and footer, and equally can present the contents in any order.
Simply beautiful. Thanks
Hi Rob,
Ok, box-height and CSS can be very tricky, but why not
laying out the template with good old pure-CSS?
(then you can opt additionaly for the height-js trick)
for example:
#header {height: 80px;}
#side {float:left;width:200px;}
#right {margin-left:210px;}
While this is indeed a beautiful solution, it creates another issue: The side bar gets a very un-desired scrolls, which remind the frames days.
Maybe it’s just a matter of implementation, and can be avoided if the side bars content’s width is known, but it certainly not good to have more than one scrollbar on a page.
Also, the position of the scroll bar (for the main content area) is not ideal. *People look for these scrolls* on the *side* of the screen, not somewhere *inside* it. Can this issue be addressed in the same manner?
As Marc van den Dobbelsteen already said, a simple margin on the right pane would also do the job. simply “width:auto”
and margin like the width of the left pane (or even more, if you want some space). Or did i miss something?
Just a quickie. I moved the menu and sidebar to after the content so that screen readers don’t have to skip the menu.
ISSUE: in all browsers if you set a div to 100% (used for certain effects)it takes the parent width and a horizontal scrollbar appears 🙁 Just not setting it 100% removes the problem but some of my skinning requires it.
Interesting method. There is a way to express 100%-20px without dynamic expressions that combines the use of width:100% and borders. I have a “crazy example”:http://experiments.mennovanslooten.nl/2005/FlexLayout/final.html of that. I’m looking forward to the CSS3 days of width:calc(100%-30px);
bq. but it certainly not good to have more than one scrollbar on a page.
I disagree. Many desktop applications have multiple scrollbars. I see no reason why browser-based applications should not.
@*James*
I put my hands up, I should have read the specifications when writing this article. It was an oversight not to check and reference them (as they suggest this very concept). It would have affected the tone of five sentences in the third section.
But it wouldn’t have changed any of the substance in the article. The point stands:
“In general, this little bit of CSS trickery seems to have been discarded due to its incompatibility with IE5 and IE6”
Specifications are wonderful, but their implementation often isn’t.
@*Marc and Stefan*
That was my initial approach too. Two main reasons for ditching it; firstly you have a lot more trouble with manipulating the layout. For example adding a footer. Secondly, as soon as you start playing with the ‘overflow’ attribute in the main div the interpretation of ‘margin-left’ begins to differ in various browsers.
@*Zohar*
It reminds me of frames too. There were some instances when frames actually worked quite well; such as when viewing documentation with a large tree view in the left pane and the content in the right pane, that was one of the instances that I needed this layout for.
If you don’t want scrolling in your sidebar and you’d rather keep the browser scrollbar than the overflow scrollbar, you’ll probably need a different approach.
@*Rob*
At least it’s fixed in IE7 🙂
@*Dan, Fritz and Jack*
Thank you
@*Lee*
Yes, you’re right. Throwing 100%’s into this causes further problems. It often does. Of course, you could probably just use the same techniques used in the layout to stretch the problamatic DIV to 100% without using percentages 😉
You should have posted this article one year ago. At that time I had to figure out all of this by my own 🙁
I came up with a solution that is nearly identical to yours.
Your article would have saved me a lot of work 2 weeks ago. Also the solution is a bit overkill for a 2-colums job, it is beautiful for 3 colums and more websites. Thanks for taking the time to explain everything.
Rob, this is absolutely fabulous! Well done. I knew that you could set the positions of all sides like this, had tried it once and got a wonderful page – until I tested it in IE, when I cried…
“Zohal”:http://www.alistapart.com/comments/conflictingabsolutepositions?page=1#7
bq. The side bar gets a very un-desired scrolls, which remind the frames days. Maybe it’s just a matter of implementation, and can be avoided if the side bars content’s width is known, but it certainly not good to have more than one scrollbar on a page.
The model needed was one where the sidebar is stationary on the page, while the content column scrolls. Under normal circumstances, I would expect such a sidebar to fit within the space available, so there wouldn’t be any scrollbars on it. But provision has to be made for the case when the content of the sidebar overflows the space available – if it’s fixed in position, you couldn’t ever see what was below the fold, so an independent scrolling mechanism is the only way to do that. But mostly I don’t see it being a problem.
If you don’t like the scrollbar within the text (I don’t think it’s an issue, I don’t think anyone will have trouble finding it), you could always set a zero margin on that side, and use padding to create the same gap. The scrollbar would then be on the right edge of the screen, although it wouldn’t be full height. (Disclaimer – I haven’t tried this, but I can’t see why it wouldn’t work!)
I don’t really need to say anything else! Can’t wait to have a proper play with this! My current thought is whether this is a potential alternative to faux columns? Although I love using them and have on many occasions, I have found them in some instances to be constricting when trying to achieve the desired layout.
can the conditional comments and “javascript” formula be contained in a style sheet that is separate from and linked to the main document?
Stephen: Sure. Conditional Comments are not limited to only having the style tags in them. They can have any HTML inside of them and IE will render them if they pass the logical test. There is no reason why you can’t have the content inside of the Conditional Comments simply a link to an IE only style sheet.
Rob:
Excellently written and very easy to understand!
This is a great concept, and I love how two inconsistencies actually work together in a way to provide a (mostly) non-JS alternative.
In this case, “two wrongs do sort of make a right”…
Atg
PS: Nice handling of the “brilliant CS student” too… 🙂
So what would happen if you just got rid of the over style? Wouldn’t it still work, but just fit better to the text inside each div?
@*Dylan*
I’m not sure I understand why you want to get rid of the overflow? The layout itself wouldn’t be affected, but the contents of the DIV’s would potentially become hidden if the browser window was resized, which means that the layout would be ‘broken’…
What I meant was if you just get rid of the overflow style, would the divs expand to accommodate the text inside of it. That would get rid of the usually unwanted scroll bars on the sides of the divs.
I thought I’d just offer a bit of a more constructive extension of James’ comment. (I thought it was a good article, but I just wanted to link the actual spec!)
Here it is:
“CSS 2.1 / 10.3.7”:http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width
This isn’t really a “special” feature or a “conflict”. The spec simply defines a whole lot of variables, such as “left”, “right” and “width”, throws them all into an equation, and the user agent is left simply to solve this equation for any unknowns. If left and right are specified, but width isn’t, it solves for width (that is what this article describes).
Specifically from the spec:
bq. 5. ‘width’ is ‘auto’, ‘left’ and ‘right’ are not ‘auto’, then solve for ‘width’
The same applies to the vertical context.
In your example, the HTML is labeled header, side, & RIGHT…
While your CSS is header, side, & MAIN.
Not a bad article, although I’m surprised that this is anything new and worth posting at a place like ALA. I’m sure many non-beginners here have come across a problem like this at least a year or three ago. I know I have.
Regardless, my comment is about the performance of the expressions you used in IE-specific style sheet. First of all, since you’re even considering IE5, it can be assumed that your lowest CPU denominator is around Pentium 3. I’ve done some extensive performance testing in the past on web applications that required CPUs as slow as 1.2Ghz and found that using even a single line of “expression” in the style sheet can make computer come to a crawl.
The cause of that is the huge inefficiency of IE’s implementation of expressions: instead of doing the checks only when the window size changes, the expressions are evaluated on virtually *every* event.
My fix for that was simple: instead of using expressions I wrote a few simple events that ran whenever the page was resized. Even though the event was called 4 times on every resize on IE (go figure!), it improved overall performance by a great amount.
The bottom line of this very long post: I recommend staying away from expressions, if possible, which, in this case, is.
Nice solution Rob. I hope nobody asks me to do the overflow auto scroll bars galore thing, but there’s a lot of beauty in how you went about doing what you did.
Great article.
One minor point: I know you’re creating invalid CSS anyway, but you may as well add in the correct units
height:expression(document.body.clientHeight-120 + ‘px’);
This article arrives at a funny time for me – I was just working on this very sort of thing. I didn’t have the same layout requirements as you, but close.
http://dillerdesign.com/random/fake_frameset.html
The difference between my method and yours, in IE: I use the IE’s wrong interpretation of the box model, in conjunction with a visual illusion (borders in a certain direction with a color that matches the body background).
Absolutely positioned elements don’t print well. All content that should overflow onto page 2 and following will be cropped. At very least you will need a print style sheet that uses a different technique to achieve the same layout.
The last time I heard a client wanting to achieve this is their excuse of, “I want everything to scroll within the webpage…”.
The browser already has a scrollbar so why add another or even more scrollbars to it?
I just don’t understand why do we even bother creating more scrollbars inside a window which already has a scrollbar.
Could anyone please give me a solid reason why and where would we want to implement this in a given scenario?
Regards.
I don’t particularly like the scrollbars on your example but I really like your technique for positioning both the top left and bottom right of an element. I never knew that was possible. Now that I do, it opens up amazing possibilities.
Cheers mate
Though web design is a craft, many of us learn alone, and by trial and error. And along the way we pick up assumptions (approximations that allow us to get the job on hand done). At the time we might realise that our understanding of the topic is a bit fuzzy but we probably tell ourselves something like, “Ok, as soon as I meet this deadline, I’m going to take the time to really get to grips with this!” Then there are more urgent projects, more deadlines, and at some point we forget that our understanding of a particular area is actually based on shaky foundations and we end up making assumptions that are completely erroneous. It takes some perspective to step back from things and question those assumptions and it is a good reflex to have I think.
By the way, Eric Meyer’s Cascading Style Sheets The Definitive Guide (Eric Meyer, O’Reilly Press) explains very nicely and thoroughly how positioning works.
@*Anatoly*
I wasn’t aware of that problem with expressions, thank you. I suppose I line has to be drawn somewhere…
@*Jake*
A fine point! Ta.
@*Drew*
Your example is _really_ interesting – good work! Great minds hey? 😉 I looked at using borders when I was first developing this, but couldn’t get them to play nicely with the background image I was using…
@*Roger*
Yes, a print style sheet is definitely a must for this. On the sites that I developed this for the print template printed the main div (the documentation contents) and hid the side div (the tree navigation for the documentation).
@*Danny*
Certainly. To give one example; I needed this layout for an online documentation page. The side div contains a very long tree structure referencing all of the methods and functions of the software, the main div contains the documentation pages itself. Based on the results of our initial usability testing the users wanted to be able to cross reference the table of contents with the documentation pages, this is only really attainable by using two scroll bars. This is a fairly standard convention for documentation (see, for example, the Firefox ‘Help contents’).
@*Everyone else*
Thanks for the comments
“Roger Roelofs”:http://www.alistapart.com/comments/conflictingabsolutepositions?page=3#28 :
bq. Absolutely positioned elements don’t print well. All content that should overflow onto page 2 and following will be cropped. At very least you will need a print style sheet that uses a different technique to achieve the same layout.
Well, yeah. I would have taken it as read that anyone clued-up enough to be reading ALA would be using a print stylesheet for anything apart from the most trivial of pages as a matter of course…
Sorry, it’s lost the end of the quote, let’s try again:
bq. Absolutely positioned elements don’t print well. All content that should overflow onto page 2 and following will be cropped. At very least you will need a print style sheet that uses a different technique to achieve the same layout.
Well, yeah. I would have taken it as read that anyone clued-up enough to be reading ALA would be using a print stylesheet for anything apart from the most trivial of pages as a matter of course… but not necessarily to achieve the _same_ layout … instead, to adapt the layout to one suitable for printing.
Very good article. One small error in the html you give the main panel an id=”right” but the css is calling #main.
Danny Foo: In-window scrollbars can be appropriate for certain types of web-based applications. Maybe true for certain “web pages”, but I’m mainly thinking about web apps. Imagine working in a word processor in which the entire menu and all navigation controls scrolled off the screen as you paged through your document…
I agree with you, j theis. I am building an security management webapp and need to follow traditional app conventions – think outlook or an IDE or iTunes. I resorted to a bunch of javascript to get around the IE limitations that don’t offer the same flexibility and simplicity. Very excited to see someone else was smart enough to figure this out and generous enough to share it. Thank you, Robert!
While, this works nicely for a very simple layout with no styling inside the left and main containers, it will not work for more complicated layouts.
1) You cannot use 100% widths inside the containers. It will create horizontal scroll bars in IE.
2) If you work around this problem by setting overflow-y to auto and overflow-x to hidden, then IE will just slap the scroll bar on top of the content if the content length dynamically changes or the browser is resized.
3) It breaks similarly if there is “float:right” inside the divs.
The solution I use is to set the overflows with
overflow:auto; — for safari
overflow-y:auto;
overflow-x:hidden;
Then add another div inside the container.
conditionally style this div for IE 6 & 7 with
padding-right:20px; (make room for the scroll bar)
That will prevent the scroll bar from placing itself on top of the content. With these changes, it should work much better with dynamic content.
If this is for a web app you might as well just use javascript , because web apps already require javascript.
I’ve been working on a website for almost a year now that has all sorts of pane-stretching, and so far we’ve been doing it all with all sorts of ugly JS. I can’t even begin to tell you how refreshing it is that there is a much more simple technique. Seriously, this just made my day/week. Much thanks and respect.
I have a similar goal on my page but different design requirements. My extra requirement is that the side bar move vertically along with the main box. This is because I have an ad in the side box, and it needs to come into view as people scroll down (thus menu also needs to be fixed not absolute) and because the menu blends into the main page and having a potential scrollbar there will be hideous. Does anyone know a tutorial or website that does this?
The best technique I could come up with uses javascript to resize the menu bar to be the exact pixel width. I don’t really mind using javascript, but my annoyance is that it is done after the page load and I think it has to be that way, so my page first draws with a % guesstimate based on a few key resolutions and then redraws with pixel perfect accuracy thanks to javascript. I couldn’t figure out a way to make the javascript that does this before the first draw because the javascript uses DOM to update the width and margins of a bunch of divs.
bq. Why is it that even on a site devoted to web design, none of the web developers know very much about the languages and APIs they’re using?
Perhaps because many of us are too busy making websites to study the specs comprehensively? Web design is one of those fields where you learn something when you need it, so overlooking what may seem like an obvious thing is quite easy. Besides, many people generally thought this wasn’t possible (probably through word and mouth) and felt no need to confirm it for themselves (why would they?).
Robert, a good referencing example indeed.
But I’ll only use this for a client on a very low budget or if the client requires a very quick reference guide.
Else for a ‘help’ feature, I’d rather advice them to implement a ‘smarter’ system to help produce a solution for a problem. 🙂
Still I really appreciate this tutorial. A good reference for me to keep for future. Regards.
Check out this method:
http://web.hc.lv/kods/css/raksti/2-kolonnu-majaslapas-izkartojums-ar-css/
Main content goes first in source, which is better for SEO, usability and accessibility.
this goes a bit pair shaped in safari for me — safari 1.3.2 (v312.6)
it’s the strangest bug — i’ve never seen it before, maybe it’s just a bug on my system not one everyone is likely to see? no idea:
clicking on the “finished layout” link gives the page, but the background, outside of the three main panels, remains what was on the preceding page. and changing the size of the window results in all sorts of pixel distortion and noise in the areas outside of the three main panels. quite a strange, changing as you change the size of the window, mess.
I have a recurring dream where I write an HTML page, apply CSS rules, and the page renders correctly no matter what the browser. Then I get chased down a corridor by a giant blue lowercase e and I wake up screaming.
Just wanted to post a thank you, this simplified a dynamic resize I had in a project, and also opened my eyes to a sweet new way of fill-up-page block structuring.
I particularly like the clarity of your thinking – taking things back to first principles. It is an object lesson in keeping things simple.
Your solution is just what I’ll need to implement some redesigns of old frame-based websites that I’ve been putting off.
Thanks. This was an interesting and helpful little article, Rob. Nice job!
Firstly, I have to say this is a fantastic solution; it never would have occurred to me to set more than two positions on an element. Very well-written, too, thankyou very much.
My first point is; *No Need for Dynamic Properties*
This is related to Anatoly Litsov’s point above (dynamic expressions can get very expensive since they constantly update). My solution is simply to use a few lines of javascript to do the same thing – get element by ID, do the math with document.body.clientHeight/Width, and have the whole thing wrapped up in a window.onresize event handler, and all of that within the existing conditional comment.
You mentioned several problems with javascript solutions, inluding problems with cross-browser event handlers; not a problem here. Your method (as you noted)is essentially serving javascript disguised as CSS, using a conditional comment, so why not serve up regular javascript? Critically, this wouldn’t have as much of a performance hit as dynamic expresions; and in my eyes, commits no more ‘crimes’ than the current method.
Secondly, *An attempt to fix the Opera bug*
That bug annoys me a lot, and I would really rather avoid it if possible (aiming for maximum possible backwards compatibility). So, I dreamt up a possible solution with just one HTML change; a container div around the sidebar, with the following CSS (note, my sidebar is on the right, with HTML source order adjusted accordingly)
#sideContainer {
position:absolute;
top:0px;
right:0px;
height:100%;
width:220px;
}
#side {
padding: 0;
margin: 0;
position: absolute;
top: 100px;
right: 20px;
bottom: 20px;
left:0px;
overflow: auto;
}
The idea being that the container div handles the 200+padding width, and the 100% height of the body (html needs 100% height too), and the sidebar is ‘pinned’ with conflicting absolutes within this box. This works in Firefox 2, Safari 3 winbeta, IE6…but in Opera 8, the behaviour is the same as before! Applying a background color to the container shows that it is, as one would expect, stretching all the way to the bottom of the window, including when the window resizes; but the sidebar within it refuses to pin to it’s bottom.
I’m stumped. I’m posting in the hope someone will spot a flaw, or be inspired to figure out some other way around this tedious bug.
There are 2 issues that the article does not address that will have people scratching their heads trying to figure out why things are not working. Both are covered in my article “Frames wihtout frames”
http://www.fu2k.org/alex/css/frames
1. When Microsoft released XP2, it upgraded IE6 so that javascript expressions within CSS are not executed if, and only if, the zone which a page resides within’s security is set to ‘High’. Even if javascript is enabled. By default that is usually set to ‘medium’, but in many corporate/institutional settings that’s not the case.
2. The expression that Rob uses will only work if IE6 is in quirks mode (the example document has an xml prolog which does the necessary quirkifying). See the “Standards Mode compatibility for IE 6” section in my article, for an extended expression that will work either way.
@John Campell, others —
I thought I had a way to fix the 100% & float problems inside the absolutely positioned elements in IE — add position: relative; to the .container divs.
However, that didn’t do it. But I was unable to find a problem with floats in IE, anyway, just with width: 100%.
Why stress about Opera 8? “I love Opera”:http://www.alanhogan.com/conversations/i-love-opera-the-browser , but don’t most users (and there are not many) use the latest version (9), in which there is no bug? And as noted in the article, it only shows on resize. That’s a user-initiated problem that is fixable by reloading, something an Opera user would likely be intelligent enough to try.
I didn’t realise that so many people were vague on positioning so its good that your article brings this to attention.
As a matter of interest you might like to know that the original example can easily be done without using expressions (and in standards mode)and I have converted one of my very (very old) demos to look like the authors.
http://www.pmob.co.uk/temp/2scroll2.htm
or an even older similar example.
http://www.pmob.co.uk/temp/3scrolling2.html
Instead of using expressions to subtract pixel heights from 100% you simply apply top and bottom padding to the html element and then IE interprets 100% height of the body from inside the padding thus giving you your gaps at the top and bottom of the page.
Of course it only works in 100% height scenarios and so is of limited use. I often find that these types of layouts (along with forced fixed positioning examples) only work well in certain situations but not for everything as there are quite often scrollbar issues.
I also notice this quote early in the article which is a little misleading:
[quote]
“Technically you can use both a right and a left property and leave the width as auto. But unfortunately IE does not support this”¦”?—css-discuss
[/quote]
That isn’t quite true and IE does support the properties left and right at the same time and you would soon see this if you tried it out.
#main {
position: absolute;
top: 100px;
left: 240px;
right: 120px;
background:red
}
The misconception arises because the background appears to only enclose the content but if there is enough content then it stretches correctly to the positions defined. In fact this can be cured by giving the inner content “haslayout” and then it works as it should.
Its only top and bottom positions that IE doesn’t understand when used together.
#44: the bug you describe does surely exist. I can confirm both the background from the preceding page and pixel distortion on window resize.
I am really interested in a solution to this problem. I would like to adopt this approach, but my company officially supports Safari 1.3.2 :=(
Sorry for the huge text in 55, it looked fine in the preview..
Scrolling does not work in Safari 1.3.2 – while the scroll bar is moving, the content is fixed, which means that you can never see any content below.
Excellently post and easy to understand.
This post has saved a lot of time. Thanks for your time to explain everything.
The fix is to add height:100% to html tag.
Has anyone tried using this technique to create a 2- or 3-column layout that goes beyond the bottom of the window and where both or all of the columns stretch to the same height as a “height-defining” column? I believe I’ve figured out how to do this in all browsers (no, I didn’t use faux columns or funky paddings or margins). I was wondering, Rob, if you’ve seen this before and if not, if you’d be interested in hearing my method. I read an article that said this would be the “holy grail” of CSS web design.
I just found Matthew Levine’s article.
I use this technique or variants very heavily, thanks to the frames without frames article published (and cited) a while back.
Be forewarned: VERY rarely, and usually inconsistently, Expressions can cause the IE browser to hang in an infinite loop. What appears to happen is the dimension gets calculated which causes the expression to trigger again, ad infinitum. There are some discussions of this, but I don’t have the links.
For me, it was the width being adjusted. In the end I had to pull it from the CSS,and put it in a javascript embedded in the footer of the page. I didn’t like doing so, because CSS is where it should be, but I had to. So people should be aware of this. While I was at it, I fixed the opera issues in JS too (window.opera is a good way to object sniff for opera)
Hi, i was looking for the same layout for some time ago, found the same solution with the absolute positioning of each corner, and ran in to the same problems in IE6 og earlier versions.. After a bid of work i actualy manged to find af solution that works alle the way down to IE5 in pure CSS without the need for Javascript. – Will put it online and post a link if anyone should be interessetet 🙂
Hi.. Haven’t had time to write an explanation, but the code should be pretty strait forward 🙂 (There is a small problem with the positioning og the right side scrollbar in IE6 that i haven’t been able to solve yet, but other than that i works as a charm as far as i can se 🙂
http://www.einventions.dk/kongknabe/frameset_layout.html
Rasmus – see my post 54 🙂
Sorrey.. Missed your post 🙂
Does anyone know of a way that I could achieve a similar effect using the “em” size unit?
I would like my header to be able to fully encapsulate its text, regardless of the text size the user has chosen.
I noticed that plenty have reported the problem with absolutely positions containers that incorrectly size containing DIVs with 100% widths.
I found that it no scrollbar appears in IE7/Win, FF2/Win, O9/Win, NN9/Win, S3/Win.
The problem I’m experiencing is that I cannot set the height of DIVs to 100% in IE7/Win. It works in all the above mentioned browsers.
Have anyone got a solutions for this problem?
Thanks for taking the time to write this great, clear article.
I’ve done this layout using pure CSS, but using individual BORDERS (as an earlier commenter noted) as if they were margins or padding. The neat trick he didn’t mention: you can set BORDER-COLOR to TRANSPARENT so no need to match background colors or designs. 100% fills the remaining calculated width. You might have to keep an eye on your z-index layering when constructing to prevent mouse events from being captured in the wrong DIV.
Whilst your CSS is clean and effective I thought I should point out a few difficulties that it exposes.
Firefox has a well known and long established print bug exposed by the use of absolute positioning – content is curtailed, usually to a single page.
Firefox mousewheel navigation (the autoscroll feature) is also broken.
Neither of these may be considered show stoppers for some but developers might like to be aware of these issues.
It looks like #main style is supposed to be the style for
Whilst the solution is neat and taught me things I didn’t know, I do have a worry about those users who can’t use a mouse for some reason.
As exampled it seems impossible to get the DIVs to scroll down using keystrokes. It seems to me that a sighted user who cannot use a mouse would be unable to access the text at the bottom of both the DIVs.
In a similar layout with frames tabbing would give focus to each frame in turn, and then the up and down arrow keys would scroll the individual frames.
Does anyone have any suggestions?
I really enjoyed the article.
One issue I’m having in IE7 is getting a nested DIV to respect the calculated height of the parent div. In Firefox, setting the height property to 100% yields the desired result; that is, a div that consumes the entire height of the underlying element. In IE7, the height is ignored, presumably because the element’s height is calculated rather than specified in CSS.
If someone has a workaround, I’d be grateful for tips.
Great article rob. Very clear and concise, eays to follow. Good job.
Thank you very much for this article. It solved me a month of headache.
Love this technique. Had no idea this was possible. TY!!!
The layout I’m stuck with has three fixed width columns. For over two years I have tried different ways to get IE6 (may it someday RIP) to extend the background of the right and left columns all the way to the bottom of the center column (where the varying height main content is). I don’t even have (or need or want) scroll bars.
Maybe there’s an expression-free method to accomplish this somewhere out there, but I haven’t been able to find it. I’m just glad this approach works perfectly for my purpose.
Thanks for taking the time to track down and explain a classic head-scratcher to this non-expert.
Thanks, even if we’re seeing IE6 fade away, it is still very much a reality with Asian users.
I have been looking for a cross-browser option of pinning a div to the viewport’s height, preferably without the use of jquery or equivalent.
This is brilliant.