MightyMeta

SuperStretch

SuperStretch! — A Vertically Fluid Layout Using CSS

| 25 Comments

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

Demo (resize browser window to see effect)

Download Source Files

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.

<div id="wrapper1">

<div id="wrapper2">

<ul id="nav">
   <li><a id="nav-select">Home</a></li>
   <li><a>Page 2</a></li>
   <li><a>Page 3</a></li>
   <li><a>Page 4</a></li>
   <li><a>Page 5</a></li>
   <li><a>Page 6</a></li>
   <li><a>Page 7</a></li>
</ul>

<div id="content-box">

<div id="content-top">
   <h1>SuperStretch!</h1>
</div>

<div id="content-bottom">
   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...
</div>

</div><!-- end content-box -->

</div><!-- end wrapper 2-->

<div id="copyright">
   <strong> Copyright Info Here.</strong> Demo created by <a>MightyMeta</a>
</div>

</div> <!-- end wrapper 1-->

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!

If you enjoyed this post, please consider sharing it using the above buttons, leaving a comment or subscribing to the RSS feed.

25 Comments

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

  2. Pingback: SuperStretch! – A Vertically Fluid Layout Using CSS | RefreshTheNet

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

  4. Pingback: A Vertically Fluid Layout Using CSS » Web Design

  5. Pingback: SuperStretch! – A Vertically Fluid Layout Using CSS | Devon Web Design and Development – MightyMeta « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit

  6. Thanks, this is great :)

  7. Pingback: Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks « Son of Byte & Web Design & Development Magazine

  8. Pingback: Image Student Forum | Blog | Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks

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

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

  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!

    • @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

  12. Pingback: Liquid, Fluid and Elastic Layout Templates, Tools and Frameworks :Speckyboy Design Magazine

  13. Pingback: 40 Essential CSS Templates, Resources and Downloads | Speckyboy Design Magazine

  14. Very clever. I spent all day yesterday trying to figure out this exact same scenario. Thankyousir!

  15. Thanks a lot. I achieved what i wanted. although my layout was very different and i did not implement any of the technique you explained here, but this technique helped me to get rid of a bug i had in my design.

    Thanks again.

  16. 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!

    Have you made any progress with this as this is exactly what I am looking for.

    I will start with your template above as it seems to be the best fluid css template I’ve found to date. Thanks for this.
    Paul

    • Hi Paul.

      Haven’t updated this in a while and what with the current trend in responsive layouts it could probably do with a refresh with some of these new techniques in mind. Having said that, the approach given here works in older versions of IE that don’t recognise @media queries…

      Tweak away, and let me know what you come up with!

  17. I’m not sure if this is appropriate to be asking this here, but I’ve been trying all day to get the nav container to be the only one with white borders. I can seem to get the top, left, right done but not the bottom without showing the border extend the length of the wrapper2 which is what I don’t want. I realise that the nav is inside the wrapper2 div but I tried nesting another div around the nav list and that didn’t work either. Any ideas?

    • Giving #nav a height of 99% instead of 100% should do the trick, the bottom border is currently cropped by the containing div because borders are applied to the outside of a box, via the CSS box model.

  18. Well that was too easy, I’m a little embarrassed. Not used to percentages however just px and fixed templates. The box model always did confuse me a little. Love to learn new things though. Thanks again.

  19. Just upgraded to Firefox 3.6.22 and it no longer works when I shrink the browser to cell phone size. Still works in IE 8, Opera 11.51, Chrome 14.0.835.186 and Safari 5.0.3 though. Firefox must have changed something.

  20. So what if instead of having the scroll-bar, you wanted the height of the #content-bottom to expand to accomodate its contents? What would you have to change?

Leave a Reply

Required fields are marked *.


MightyMeta, 8 St Lawrence Lane, Ashburton, Devon, UK, TQ13 7DD

Powered by WordPress | Theme Derived From "Yoko" by by Elmastudio

Scroll To Top