SuperStretch! – A Vertically Fluid Layout Using CSS

May 14, 2010 by MightyMeta

Here’s a technique I created a while back that I have revisited and tidied up a bit. It results in a layout that stretches both horizontally and vertically to the browser viewport. It includes a vertical navigation bar where button heights also stretch. It works in FF, Safari, Chrome, Opera, and IE 6-8

Demo (resize browser window to see effect)

Download Source Files

You can also see the technique being used on this live site: www.webstersheryn.com

Examples

SuperStretch Wide

SuperStretch Tall

As you can see, the idea is that the layout should be able to adapt to different screen resolutions and configurations.

It is probably also worth mentioning that only HTML and CSS is used. JavaScript is only employed for IE6 compatibility.

HTML

Nothing too unusual here, except that two ‘wrapper’ elements are required to get the spacing around the viewport edge to work. Sorry, semantic web. Additionally, the navigation elements each need to have their own class attribute, to enable them to be given different positioning values.

SuperStretch!

Enim odio dolore dignissim eu enim dolore consequat ex tation lobortis enim molestie diam ut odio illum, nostrud ea. Aliquam feugait et te diam, erat iriure vulputate, consequat facilisi facilisis feugait illum. Et suscipit nisl ut lobortis iusto in ea nisl ea esse consequatvel. Etc...

CSS

Most of this works by using a combination of absolute positioning and percentage dimension values.

Firstly, we need some reset declarations to remove the default margins and padding around the viewport that browsers add in. We also need to ensure that the height of the page is set to 100% of the viewport, and that scrollbars do not appear if anything pokes out beyond the viewport edge:

ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, body, html, p, blockquote, fieldset, input
{ margin:0; padding:0 }
h1, h2, h3, h4, h5, h6, pre, code { font-size:100%; }
html, body { height: 100%; overflow: hidden; }

Next, we set up some basic text styles and a background image:

body {
font-family: Arial, Helvetica, sans-serif;
line-height: 140%;
color: #fff;
background: #301849 url(../images/gradient.png) repeat-x;
}

h1 {
font-size:3em;
padding:0 20px 0 0;
line-height:160%;
text-align:right;
text-shadow:#000 2px 2px;
}

p {
font-size: 1em;
padding-bottom: 1em;
padding-top: 0.8em;
}

a {
color: #fff;
text-decoration: underline;
font-weight: bold;
}

a:hover {
text-decoration: none;
}

Now the fun begins! With absolute positioning, you can only declare a single vertical and single horiztonal value. So, {top:20px;} together with {bottom:20px;} will not work, only the {top} property will be parsed. To get around this a couple of nested div elements are used.

With #wrapper1 we make it the relative element and give it 100% width and height, but position it 20px away from the top left corner. This means that 20px of this box is pushed beyond the right and bottom edge of the browser viewport.

#wrapper1 {
position: relative;
top: 20px;
left: 20px;
width: 100%;
height: 100%;
overflow: hidden;
}

#wrapper2 is then positioned 40px from the bottom right, to bring things back into view and create a box that has a 20px margin around the viewport edge. In the demo here, the bottom edge is actually moved up by 60px, to make room for the footer text. Interestingly, you need to give #wrapper2 {left} and {top} values of ’0′ to get the box to stretch and fill #wrapper1. I’m not quite sure why this works, and whether it is contrary to the W3C spec, but all browsers seem to be okay with it…

#wrapper2 {
position: absolute;
top: 0px;
right: 40px;
bottom: 60px;
left: 0px;
overflow: hidden;
border: 2px solid #fff;
}

The styling for the navigation works as follows:

The #nav is positioned to the top left of #wrapper2 and given a fixed width (theoretically this could also be fluid).

#nav {
height: 100%;
width: 100px;
border-right: 2px solid #fff;
overflow: hidden;
position: absolute;
left: 0px;
top: 0px;
list-style-type: none;
}

All the a elements within #nav are set to {display:block;} and {position:absolute;}, with an {overflow:hidden;} for good measure. Included below is the additional text and :hover styling:

#nav  a {
font-size: 0.9em;
font-weight: bold;
text-transform: uppercase;
text-decoration: none;
text-shadow:#000 1px 1px;
display: block;
position:absolute;
overflow: hidden;
width: 86px;
padding-right: 10px;
padding-left: 4px;
background: url(../images/nav-bg.png) repeat;
}
#nav  a:hover {
background-image: none;
background-color: #ffcc66;
}
#nav  #nav-select {
background-image: none;
background-color: #ff9900;
}

Then, each individual a is given a percentage height, with the total heights adding up to 100%. To position them, each a needs to have a {top} value that is the sum of the heights of any a elements that are above it.

For example:

.nav1 {top:0%} (because there are no other nav elements above it, it is the first one)
.nav2 {top:18%} (because .nav1 was 18% high)
.nav3 {top:25%} (because .nav1 was 18% high and .nav2 was 7% high, 18+7=25)

The CSS that relates to this example would be:

.nav1 {
height: 18%;
top: 0%;
}
.nav2 {
height: 7%;
top: 18%;
border-top: solid 2px #fff;
}
.nav3 {
height: 8%;
top: 25%;
border-top: solid 2px #fff;
}

The positioning of #content-bottom works along a similar principle, with the sum of its {top} and {height} equalling 100%

#content box is another strange one that I have discovered more through trial and error than anything else. It seems that we need both ’0′ bottom and right values plus ‘auto’ width and height values for it to stretch and fill the available space.

The scrollbar is achieved quite simply by adding {overflow:auto;} to #content-bottom.

#content-box {
position: absolute;
height: auto;
width: auto;
top: 0px;
left: 102px;
bottom: 0px;
right: 0px;
}
#content-top {
position: absolute;
top: 0px;
right: 0px;
}
#content-bottom {
position: absolute;
width: 100%;
height: 67%;
top: 33%;
bottom: 0px;
overflow: auto;
border-top: 2px solid #fff;
background: url(../images/main-bg.png) repeat;
}
#content-bottom   p {
padding-top: 15px 20px 0 20px;
}

IE6

This can be made to work in IE6 if Dean Edwards’ ie7.js script is employed. Without it, the ’0′ values on #wrapper2 are ignored and the whole layout collapses into a box that has no width or height. Nice!

I have also used Drew Diller’s DD_BelatedPNG script to get the alpha-transparent background PNGs to render correctly. Although ie7.js includes a method for this, it relies on alphaImageLoader, which causes the links on the menu to stop working.

Conclusion

I hope this might be of interest to some people. Granted, it’s not appropriate for everything, but in particular I am interested in tweaking this further with the aim of creating a flexible meta-layout that can work equally well on laptops, notebooks and mobile devices. Stay tuned!

Share This Post:
  • Digg
  • del.icio.us
  • Facebook
  • StumbleUpon
  • Technorati
  • Twitter

12 Comments »

  1. Bravo! hope had seen it 2 years ago…

    Comment by Yang — May 15, 2010 @ 2:04 am

  2. [...] Super­Stretch! – A Ver­ti­cally Fluid Lay­out Using CSS | Devon Web Design and Devel­op­ment… [...]

    Pingback by SuperStretch! – A Vertically Fluid Layout Using CSS | RefreshTheNet — May 17, 2010 @ 5:16 pm

  3. Good idea. Setting the position absolute, and use percentage for height is creative. Nice tutorial. Thanks for sharing.

    Comment by Deluxe Blog Tips — May 18, 2010 @ 11:14 am

  4. [...] A Vertically Fluid Layout Using CSS [...]

    Pingback by A Vertically Fluid Layout Using CSS » Web Design — May 20, 2010 @ 8:41 am

  5. [...] SuperStretch! – A Vertically Fluid Layout Using CSS | Devon Web Design and Development – Mig…mightymeta.co.uk [...]

    Pingback by SuperStretch! – A Vertically Fluid Layout Using CSS | Devon Web Design and Development – MightyMeta « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit — May 20, 2010 @ 10:05 am

  6. Thanks, this is great :)

    Comment by Robine — May 20, 2010 @ 10:37 am

  7. [...] SuperStretch! – A Vertically Fluid Layout Using CSS [...]

    Pingback by Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks « Son of Byte & Web Design & Development Magazine — June 9, 2010 @ 2:08 am

  8. [...] SuperStretch! – A Vertically Fluid Layout Using CSS [...]

    Pingback by Image Student Forum | Blog | Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks — June 18, 2010 @ 6:57 am

  9. On first sight I see little use for it but good job anyway.

    Comment by David — June 19, 2010 @ 5:08 pm

  10. Interesting post. I have been looking for a really elastic layout. Thanks.

    Comment by Matt Davidson — June 19, 2010 @ 7:02 pm

  11. almost worked but I have a content-top with fixed height!

    Any ideas for that. Basically fixed height content-top height (say 200px) and then liquid height for the content-bottom…

    I have not been able to find a way to do that!

    Comment by Richard — August 10, 2010 @ 3:38 am

  12. @Richard – mixing element of fixed and liquid heights is next to impossible, but you’ll notice that there is a fixed 10px margin at the top of this layout – maybe this can be adapted for your needs? You’d just need to increase the {top;} value for #wrapper1 and then adjust the {bottom;} value of #wrapper 2 to compensate, and move your fixed top content into the new space that is created

    Comment by MightyMeta — August 26, 2010 @ 1:51 pm

RSS feed for comments on this post. TrackBack URL

Leave a Comment