The impossible css layout?

I’ve been working with this for awhile and I’m pretty sure its unsolvable. Just thought I’d throw it out to find out if someone smarter than I can figure it out - without changing the markup :slight_smile:

The layout below is a typical table-less css based design with header and footer sandwiched between two columns (content and sidebar) using floats and relative positioning so that the footer is cleared and always flows below the tallest content container (sidebar or content) similar to a traditional table layout.

This particular layout is a WordPress theme that I’ve designed dozens of sites around solely with unique css and images. That’s why my requirement is that the markup remain as is.

The challenge…

I’d like the “avatar” div to stay anchored to the top of the header div regardless of the height of “featured” and without using “position:fixed” or changing the markup order. If you copy the code below and save it as an .html file, you’ll see that it does just that right out of the box. However, once you add or subtract height from “featured”, “avatar” will move accordingly up or down. That’s the challenge, I need avatar to stay at the zero position relative to the body, regardless of the dimensions of “featured”.

Some “easy” solutions…

  1. Obviously, changing the markup would make this an easily solvable challenge, but for the reasons above, I don’t want to do that.

  2. Setting “sidebar” to absolute positioning would be another obvious solution, however, it suffers in that it will screw up the flow of the footer div below content and sidebar (whichever is taller).

  3. Setting the avatar div to position:fixed is really easy to do, however, I don’t want to fix the div in that spot because as the document is scrolled it will overlay valuable content. If css had a “position:fixed-scroll” perhaps that would do the trick, but I’m pretty sure it doesn’t.

I’m thinking that the answer might lie in utilizing of one of css’s “table display” properties but that’s one area of css that I’ve largely left alone.

Here’s the code…

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US"> 
 <head>
  <title>CSS Float Challenge</title>
<style>
body {margin:0;padding:0;}
.header {height:100px; background:red; width:977px; margin:0 auto;}
.main {width:977px; margin:0 auto;}
.featured {background:green;height:50px;}
.content {float:left; min-height:300px; border:1px solid #777; width:700px;}
.sidebar {background:blue; width:250px; float:right; min-height:400px}
.footer {background:gold;height:100px;clear:both;width:977px; margin:0 auto;}
.clear {clear:both;}
.avatar { width:200px; background:orange; margin-top:-150px;}
</style>
 </head>
 <body>
 <div class="wrapper">
     <div class="header">header</div>
     <div class="main">
        <div class="featured">featured content goes here</div>
        <div class="content">content goes here</div>
        <div class="sidebar">
            <div class="avatar">avatar goes here. I need this to always be at the top of the screen, <b>regardless of the height of the "featured content" div</b>. Its set at 50px now and avatar rests neatly at the top. However, set it to 100 and watch avatar drop 50 (as expected with the current css)</div>
            <div>This content should flow below avatar relative to avatar's height</div>
        </div>
        <div class="clear">&nbsp;</div>
        <div class="footer">footer is here</div>
     </div>
 </div>
 </body>
</html>

If you take that and paste it into a fresh html page and preview, you can see that as is, it does exactly what I’m looking for. The avatar div is sitting nicely at the top of the header div.

However, as soon as the height of the featured div changes, avatar moves up or down in relative fashion. The trick I’m looking for (without changing markup and without using javascript or fixed position) is to have the avatar div stay anchored to the top of the page regardless of the content height of featured.

Again, I’m pretty sure its unsolvable, but I really want to be proved wrong…

You sir, are a stud.

Respect.

~ s

Hi,

Not really feasible as a usable layout but this fulfils the criteria for the exercise.

Ie8 and modern browsers only.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head>
<title>CSS Float Challenge</title>
<style>
body {
    margin:0;
    padding:0;
}
.header {
    height:100px;
    background:red;
    width:977px;
    margin:0 auto;
}
.main {
    width:977px;
    margin:0 auto;
}
.featured {
    background:green;
    height:350px;
    float:left;
    width:100&#37;;
    margin-right:-260px;
    display:inline;
}
.content {
    float:left;
    min-height:300px;
    border:1px solid #777;
    width:700px;
}
.sidebar {
    background:blue;
    width:250px;
    display:inline-block;
    min-height:400px;
margin-left:10px;
}
* html .sidebar{display:inline}
*+html .sidebar{display:inline}
.footer {
    background:gold;
    height:100px;
    clear:both;
    width:977px;
    margin:0 auto;
}
.clear {
    clear:both;
}
.avatar {
    width:200px;
    background:orange;
    margin-top:-100px;
    clear:both;
}
</style>
</head>
<body>
<div class="wrapper">
    <div class="header">header</div>
    <div class="main">
        <div class="featured">featured content goes here</div>
        <div class="content">content goes here</div>
        <div class="sidebar">
            <div class="avatar">Start avatar goes here. I need this to always be at the top of the screen, <b>regardless of the height of the "featured content" div</b>. Its set at 50px now and avatar rests neatly at the top. However, set it to 100 and watch avatar drop 50 (as expected with the current css)</div>
            <div>This content should flow below avatar relative to avatar's height</div>
        </div>
        <div class="clear">&nbsp;</div>
        <div class="footer">footer is here</div>
    </div>
</div>
</body>
</html>


Thanks Stomme, yes its definitely given in that spirit. Thanks for helping me clear on that point.

One thing I want to add as another point of clarification.

It might be tempting to set the scroll property on the featured div to auto and have it scroll its contents, thereby maintaining a predictable height which solves the problem as stated.

However, I need to clarify that “featured” is included and implemented into the markup as a sidebar widget.

So the user has descretion to include it or not. Therefore, if you go that route, you have to account for the case when featured is not present in the markup at all.

As a note to everyone, this is indeed to be taken as a challenge… a what can you do with CSS alone assuming you’re given this markup kinda thing.

late to the party…how about adding a position relative to wrapper div and absolute positioning the sidebar widget div. Here’s the css.


body {margin:0;padding:0;}
.wrapper {position: relative;}
.header {height:100px; background:red; width:977px; margin:0 auto;}
.main {width:977px; margin:0 auto;}
.featured {background:green;height:100px;}
.content {float:left; min-height:300px; border:1px solid #777; width:700px;}
.sidebar {background:blue; width:250px; float:right; min-height:400px; position: absolute; right: 185px; top:0 }
.footer {background:gold;height:100px;clear:both;width:977px; margin:0 auto;}
.clear {clear:both;}
.avatar { width:200px; background:orange;}

Good try:) However that method will fail because the sidebar is now absolutely positioned and no longer takes part in the flow of the document.

If you add content into the div under the avatar it will spill out over the footer and nt push the footer down the way that a floated column will.

Check the same result in my example and you will see that the flow of the document is maintained.:slight_smile: It was a tricky problem.

did not notice that…thanks for pointing out :slight_smile:

No problems but the main thing is that you had a go :slight_smile: