views:

458

answers:

3

In a nutshell

I need a CSS solution for the following requirements:

  • Two vertically repeated background images, one aligned to the left, one aligned to the right
  • One centered column on top with fixed width and a minimum height of 100%
  • Cross browser compatibility

A little more details

Today a new requirement for my current web site project came up: A background image with gradients on the left and right side (replaces the current body background image). The challenge is now to specify two different background images while keeping the rest of the layout spec. Unfortunately the (simple) layout somehow doesn't go with the two backgrounds.

My layout is basically one centered column with fixed width:

#main_container {
  background-color: white;
  margin: 0 auto;
  min-height: 100%;
  width: 800px;
}

Furthermore it's necessary to stretch the column to a minimum height of 100%, since there are quite some pages with only little content. The following CSS styles take care of that:

html {
  height: 100%;
}

body {
  background-image: url('old-background.png');
  margin: 0;
  height: 100%;
  padding: 0;
}

So far so good - until the new body background image with gradients arrived. I tried the following solutions

  1. Two absolute positioned divs behind the main container
  2. One image defined with the body, one with the html CSS class
  3. One image defined with the body, the other one with a large div begind the main container

With either one of them, the dynamic height solution was ruined. Either the main container didn't stretch to 100% when it was too small, or the background remained at 100% when the content was actually longer

A: 

[revamp]

I'm silly. Very.
Problem: body needs to have bg images, #main_container needs to have 800 width and in the center.
(Lousy approach: I was doing #main_container with bg images, not centered, 800px.)

New approach: I suggest a div inside body and a span inside that new div:

<body>
<div>
<span>
  <div id="main_container">
    Regular contents.
  </div>
</span>
</div>
</body>

Then:

body {
  background: url(img/bg_left.gif) repeat-y top left;
}
body>div {
  background: url(img/bg_right.gif) repeat-y top right;
}
body>div: {
  text-align: center;
}
body>div>span {
  display: inline-block;
  /* IE only likes this rule on elements that are inline by nature, thus the use of span.
  I'm not sure 100% height will work on #main_container. */
}

And your regular rules:

#main_container {
  background-color: white;
  margin: 0 auto;
  min-height: 100%;
  width: 800px;
}
ANeves
The two background images are meant to be behind the #main_container. The #main_container itself has solid white background.I think the first version of my question wasn't accurate enough - sorry 'bout that. I rephrased it now.
laurent
I'm sorry, I don't understand. If you're saying that the `#main_container` has something inside with solid white BG that you can't change, then of course no background on any parent would ever show. Care to be more specific? I'll edit my answer to be more explicit.
ANeves
I was reading it all wrong... revamped the answer to actually **meet** your problems. Sorry for the mess-up.
ANeves
The `>` selector does not work in ie6. Just use a class to be safe.
Joel Potter
Thanks a lot for your inputs! I am afraid the minimal height of 100% doesn't work for the #main_container...
laurent
@Joel Potter: IE9 is around the corner... why must we still talk about IE6? =|
ANeves
@laurent: go for Joel Potter's solution. Simple, effective. I like that `margin: 0 auto;` thing, it's news to me. :)
ANeves
unfortunately Joel's solution doesn't properly handle the min-height requirement (see comments to his answer)
laurent
@sr pt, Because it's still a 10% browser unfortunately.
Joel Potter
Unfortunately - my point exactly.
ANeves
A: 

Using a "layout table", my issue can be solved. A pure CSS solution, however, would be preferred!

Here's a working table-based solution:

table.layout {
  border-collapse: collapse;
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}

table.layout td {
  margin: 0;
  padding: 0;
  vertical-align: top;
}

td.layout_left {
  background-image: url('background-left.png');
  background-position: top left;
  background-repeat: repeat-y;
}

td.layout_center {
  background-color: white;
  width: 800px;
}

td.layout_right {
  background-image: url('background-right.png');
  background-position: top right;
  background-repeat: repeat-y;
}

And the HTML code:

<table class="layout">
  <tr>
    <td class="layout_left">&nbsp;</td>
    <td class="layout_center">
      <!-- content -->
    </td>
    <td class="layout_right">&nbsp;</td>
  </tr>
</table>
laurent
+2  A: 

Modified:

<body>
  <div class="container"><div>
  <div id="main_content"></div>
</body>

With css:

html {
  height: 100%;
}
body {
  background: url(left.png) repeat-y top left;
  background-attachment:fixed;
  height: 100%;
  margin: 0;
  padding: 0;
}
div.container {
  background: url(right.png) repeat-y top right;
  height: 100%;
  width: 100%;
  position:fixed; /* This won't work in all browsers. May need a JS solution for IE6 */
}
#main_content {
  height: 100%;
  width: 800px;
  margin: 0 auto;
  background-color: white;
}

Edit:

This version works for browsers that support position:fixed (not ie6).

Example page: http://jsbin.com/ebozi3/4/edit

Joel Potter
Hi Joel, thanks for your answer. The problem with your solution is the div.container height. The container remains at 100% even if there's more content.
laurent
+1 @laurent: removing the `height: 100%;` from `div.container` should make it work as you want.
ANeves
removing the height or replacing it by min-height works with content longer than 100%. but then white column doesn't stretch when the content is smaller than 100%.
laurent