homepage Welcome to WebmasterWorld Guest from 54.211.201.65
register, free tools, login, search, subscribe, help, library, announcements, recent posts, open posts,
Subscribe to WebmasterWorld

Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / CSS
Forum Library, Charter, Moderator: open

CSS Forum

This 42 message thread spans 2 pages: < < 42 ( 1 [2]     
CSS example: 100% height, footer stuck on bottom
swa66




msg:4015933
 10:44 pm on Oct 29, 2009 (gmt 0)

A step-by-step example of how to build your design.

It's not just the end result that I aim for, I aim probably more at showing the thought process of how to build your design without tearing out the last few hairs you've left :)

No IE

Yes, that's the start: ditch the browser of choice of the majority of your users. It's critical to do this is you value your sanity.

Chose any other browser: FF, Safari, Opera, ... I'll use Firefox for it has plug-ins like the web developer toolbar and firebug. But the others will work too as long as it's not "that" browser from Microsoft.

Start

I'm using a template for the html to start from.
Make it as strict as you can cause it will increase the number of errors you get from a code validation and make your code a lot better as a result.

I usually start from this in these guides:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

The main thing I'd do different in a real life case is that I'd make the CSS a <link>. But for simpler cutting and pasting in this tutorial this will do.

HTML

Yes: make the html first.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div class="header">
<a href="#"><img src="1.jpg" alt="logo" /></a>
<h1>title</h1>
</div>
<div class="middle">
<h2>heading</h2>
<p>Lorem ipsum ...</p>
<p>Add more content to make sure you can scroll as you need.</p>
</div>
<div class="footer">
<p>Footer text goes here</p>
</div>
</body>
</html>

Now does that validate ?

Yep it does!

Does it make sense without CSS ?

It does!

HTML done

I'll consider the HTML finished now. All the rest will have to be done in the CSS.

The 100% height framework

First let's center our body and give it a different color from the background

html {
background-color: #ccc;
}
body {
background-color: white;
width: 770px;
margin: 0 auto;
}

Why does this center it ?
Well the block element <body> is given a width and told to calculate it's left and right margin itself.

Next let's stretch it vertically to be at least the height of the viewport

html {
height: 100%;
}
body {
min-height: 100%;
}

The 100% height trick is all about: the 100% references the height of the direct parent, provided the parent has an explicitly set height different from "auto".
The exception is the root element that has the height of the viewport.

min-height instead of height is what makes it at least as high as the content (and not cut our body off where the viewport stopped).

Try it with different sizes of viewport and different sized content a bit.

Now what would happen if we were to add a border or padding or vertical margins to <body> ? Try it !
So remember we need to avoid adding anything that's going to add to the height of the body. The 100% sets the height of the content, not the overall height.

So we'll need to add the border in a different fashion then.

Stick the footer to the bottom

By stick to the bottom in this case I meant stick it under the content if the content is longer than the viewport, and stick it at the bottom if the content isn't long enough to fill the viewport.

You can also stick it always at the bottom of the viewport: you use position fixed instead of position: absolute in that case.

Absolute positioning:

body {
position: relative;
}
.footer {
position: absolute;
background-color: yellow;
bottom: 0;
left:0;
}

Nice, but the footer is lacking the width it needs.
I'm sure after the talk about 100% height most would wonder about 100% width:

.footer {
width: 100%;
}

And it will work to get the footer the width of it's parent (the body).
But there is a bit of an issue if we're not careful: try adding padding on the footer and it'll grow to be too large horizontally to fit anymore.

There are ways to deal with that (and we'll show them where we deal with IE6 much later).
The reason the width get's too large is cause we derive the overall width from the width of the content (which we can set), and then the padding is added around that.
But when we use absolute positioning, setting the overall with is more than easy enough:


.footer {
position: absolute;
background-color: yellow;
bottom: 0;
left:0;
right:0;
}

Yes, we set left and right and the width will adapt to what's needed.
We can now set the padding as we like. Try it!

Layout the header

I need to fix the header (mostly cause my test image is way too large), but also to show some neat tricks.

Let's remove that ugly blue border:

a img {
border:none;
}

This will remove borders on all images that are inside a link.

Let's also position and size the header:

.header {
background-color: orange;
position: relative;
min-height: 110px;
}
.header a img {
width: 150px;
height: 100px;
position: absolute;
top: 5px;
left: 5px;
}
.header h1 {
padding: 20px 0 0 160px;
}

notice that I didn't have to control the width of the header: it's using the width of it's parent.

You can lay it out as you like, it's just one way, nothing more.

Fix the overlap

If your content is larger than the viewport, the footer is sitting on top of the content itself. This needs fixing.
But the footer is absolutely positioned so it has no influence over the in-flow elements.
The solution is to make sure the content has whitespace that sticks out below the footer:


.middle {
padding-bottom: 2em;
}

The 2em is a bit much, we can adapt that later (or the footer might use some padding and might not even be enough.

Now why does this work?
The middle div isn't stretched ?
Nope but it's got a padding sticking out beyond it's content that leaves room for the footer to overlap should it want to do that.

To visually see it at work: add a background color on .middle and resize your browser window.

Adding some padding

Where to add padding is tricky:

  • you can't add top or bottom things on the body or it breaks
  • you can't add left or right things to the footer or it breaks (if we choose to set the width instead of setting the left and right position)
  • we can't add left or right padding on the body or it disconnects the header and footer from the sides (and that's what we'll need for the border later)

So what works ?

.middle {
padding: 0 5px 2em 5px;
}
.footer p {
padding: 5px;
font-size: 80%;
}

I've collapsed the 2em bottom padding into the shorthand padding on the .middle

The .footer p can have padding, its width isn't set.

I already took care of the header above.

Adding a border

A border is just as tricky as the padding above, but we can add left and right borders on the body and we can add a top border on the header and a bottom border on the footer:

body {
border-left: 1px solid #888;
border-right: 2px solid black;
}
.footer {
border-bottom: 2px solid black;
}
.header {
border-top: 1px solid #888;
}

Colors and thickness are easy enough to adjust.

Removing the background colors showing us where the elements are and putting it all together we end up with:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
html {
background-color: #ccc;
height: 100%;
}
body {
background-color: white;
width: 770px;
margin: 0 auto;
min-height: 100%;
position: relative;
border-left: 1px solid #888;
border-right: 2px solid black;
}
.footer {
position: absolute;
bottom: 0;
left:0;
right:0;
border-bottom: 2px solid black;
}
a img {
border:none;
}
.header {
position: relative;
min-height: 110px;
border-top: 1px solid #888;
}
.header a img {
width: 150px;
height: 100px;
position: absolute;
top: 5px;
left: 5px;
}
.header h1 {
padding: 20px 0 0 160px;
}
.middle {
padding: 0 5px 2em 5px;
}
.footer p {
padding: 5px;
font-size: 80%;
}
</style>
</head>
<body>
<div class="header">
<a href="#"><img src="1.jpg" alt="logo" /></a>
<h1>title</h1>
</div>
<div class="middle">
<h2>heading</h2>
<p>Lorem ipsum ...</p>
<p>Add more content to make sure you can scroll as you need.</p>
</div>
<div class="footer">
<p>Footer text goes here</p>
</div>
</body>
</html>

Test

Let's test it first in the other standards compliant browsers:

Seems to work fine in FF, Opera, Safari and Chrome.

So this is another milestone like the one where we declared the html done. The CSS is now done.

I can hear you think: but you didn't even test it in IE ! How can it be done ?

Yes it's done. We'll add conditional comments to work around issues that IE has.
The reason for not adding anything back into the main CSS is to keep it all simple and possible to wrap our head around. And mainly not to have to care why IE does what it does.

Work around IE bugs

To work around the bugs in IE we need to test it first. Easiest is IE8 in most cases, most difficult is IE6 in virtually all cases.

IE8: does OK as expected
IE7: does OK as well (I had hoped to have something to fix to be honest)
IE6: there's no chance it'll do it properly

IE6 doesn't understand min-height, but its height is broken enough to be able to be a good substitute.

And the setting of both sides on the footer isn't working either (expected)

Adding the conditional comment to fix it:

<!--[if IE 6]>
<style type="text/css">
body {
height: 100%;
}
.header {
height: 110px;
}
.footer {
width: 100%;
}
</style>
<![endif]-->

This yields:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
html {
background-color: #ccc;
height: 100%;
}
body {
background-color: white;
width: 770px;
margin: 0 auto;
min-height: 100%;
position: relative;
border-left: 1px solid #888;
border-right: 2px solid black;
}
.footer {
position: absolute;
bottom: 0;
left:0;
right:0;
border-bottom: 2px solid black;
}
a img {
border:none;
}
.header {
position: relative;
min-height: 110px;
border-top: 1px solid #666;
}
.header a img {
width: 150px;
height: 100px;
position: absolute;
top: 5px;
left: 5px;
}
.header h1 {
padding: 20px 0 0 160px;
}
.middle {
padding: 0 5px 2em 5px;
}
.footer p {
padding: 5px;
font-size: 80%;
}
</style>
<!--[if IE 6]>
<style type="text/css">
body {
height: 100%;
}
.header {
height: 110px;
}
.footer {
width: 100%;
}
</style>
<![endif]-->
</head>
<body>
<div class="header">
<a href="#"><img src="1.jpg" alt="logo" /></a>
<h1>title</h1>
</div>
<div class="middle">
<h2>heading</h2>
<p>Lorem ipsum ...</p>
<p>Add more content to make sure you can scroll as you need.</p>
</div>
<div class="footer">
<p>Footer text goes here</p>
</div>
</body>
</html>

[edit]Edit: spelling, grammar and layout[/edit]

[edited by: swa66 at 12:13 pm (utc) on Nov. 11, 2009]

 

GryphonLeon




msg:4025346
 9:21 pm on Nov 15, 2009 (gmt 0)

Ok, here's a fix proposal. I've tested this with IE6, IE7, IE8, FireFox 3.5.5 and Google Chrome 3.0.195.33

First, wrap the entire body contents in an extra div like so:



<div id="wrapper">
<div class="header">
<a href="#"><img src="1.jpg" alt="logo" /></a>
<h1>title</h1>
</div>
<div class="middle">
<h2>heading</h2>
<p>Lorem ipsum ...</p>
<p>Add more content to make sure you can scroll as you need.</p>
</div>
<div class="footer">
<p>Footer text goes here</p>
</div>
</div>

Then, add the following code just above </head>:

<!--[if IE 8]>
<style type="text/css">
#wrapper {height:100%;display:table;}
</style>
<![endif]-->

Let me know if that works!

webdesign bedrijf




msg:4025751
 12:27 pm on Nov 16, 2009 (gmt 0)

There are a lots of differences use for example more css files to fix the browserproblems>

astupidname




msg:4025952
 6:26 pm on Nov 16, 2009 (gmt 0)

Anybody else that can trigger this with IE8 and the code provided ?

It was giving me the problem on IE 7 & 8, that if you re-size the viewport smaller, refresh and then pull the bottom of the window down (increase viewport size vertically) the footer does not follow, just stays stuck. I added: height:100%; to .middle, works now for me, without even needing the wrapper GryphonLeon suggests.

swa66




msg:4026069
 8:58 pm on Nov 16, 2009 (gmt 0)

Yes it only happens if you resize it using the bottom edge of the browser (not if you resize using the corner (like I always do -mac users all resize that way I guess-)

The thing is I've not seen it in IE7.

But the fix to give IE8 a relative height somewhere that's got no direct parent with an explicitly set height (and hence computes to auto) is simple and remind me of the old hasLayout triggers (it's not a hasLayout related bug AFAIK)

So that gives:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
html {
background-color: #ccc;
height: 100%;
}
body {
background-color: white;
width: 770px;
margin: 0 auto;
min-height: 100%;
position: relative;
border-left: 1px solid #888;
border-right: 2px solid black;
}
.footer {
position: absolute;
bottom: 0;
left:0;
right:0;
border-bottom: 2px solid black;
}
a img {
border:none;
}
.header {
position: relative;
min-height: 110px;
border-top: 1px solid #666;
}
.header a img {
width: 150px;
height: 100px;
position: absolute;
top: 5px;
left: 5px;
}
.header h1 {
padding: 20px 0 0 160px;
}
.middle {
padding: 0 5px 2em 5px;
}
.footer p {
padding: 5px;
font-size: 80%;
}
</style>
<!--[if IE 6]>
<style type="text/css">
body {
height: 100%;
/* min-height not working */
}
.header {
height: 110px;
/* min-height not working */
}
.footer {
width: 100%;
/* setting left and right at the same time not working */
}
</style>
<![endif]-->
<!--[if IE 8]>
<style type="text/css">
.middle {
height: 1%;
/* min-height not updating on vertical enlarging of the window */
/* parent has no explicit set height so the computed value will */
/* be auto */
}
</style>
<![endif]-->
</head>
<body>
<div class="header">
<a href="#"><img src="1.jpg" alt="logo" /></a>
<h1>title</h1>
</div>
<div class="middle">
<h2>heading</h2>
<p>Lorem ipsum ...</p>
<p>Add more content to make sure you can scroll as you need.</p>
</div>
<div class="footer">
<p>Footer text goes here</p>
</div>
</body>
</html>

There is another bug I discovered while looking revisiting this: opera has a weird one: it doesn't do the min-height: 100% on first load, but does so when you reload. (I had missed it due to reloading the page instead of loading it)
I've found complex solutions out there with a float that's generated from the :before, but I'd love a simpler one.

astupidname




msg:4026140
 10:55 pm on Nov 16, 2009 (gmt 0)

The thing is I've not seen it in IE7.

Hmmm.. you are right, I could have sworn I had the problem in IE7 also earlier, but when I check now (without 'the fix') it's not a problem (in IE7).

(it's not a hasLayout related bug AFAIK)

Yes, I can confirm that it seems to be a hasLayout bug (with hasLayout being false == bad thing in IE8 in this case). I tested some more, and in both IE7 & IE8 it alerts false for hasLayout without the height fix applied (and footer works in IE7 but not in IE8), and true with the height fix applied for .middle (footer works in both). You can play with checking this with the following script, add before closing head tag in your latest post (swa66), and then play with removing and re-adding the IE8 conditional css:


<script type="text/javascript">
window.onload = function () {
var div = document.getElementsByTagName('div')[1];
alert('div.className = '+ div.className +'\ndiv.currentStyle.hasLayout = '+ div.currentStyle.hasLayout);
};
</script>

Incidentally, I believe the fix presented is known as the 'holly hack'.

swa66




msg:4026184
 12:35 am on Nov 17, 2009 (gmt 0)

Aha: my favorite way to trigger hasLayout (zoom:1) in IE doesn't trigger it anymore in IE8.
And they still have that hidden property in IE8, one would have hoped they'd gotten rid of it after all the headaches it gave in IE6 and IE7.

So it's something that's fixed by giving hasLayout to a child of the element that's not stretching in IE8 ...

The header and footer already had hasLayout. So the middle not having it was apparently enough to trigger this bug.

Wonder what else we'll find of hidden flashbacks from the past in IE8.

UserFriendly




msg:4028035
 2:38 pm on Nov 19, 2009 (gmt 0)

Is IE6 use really still so widespread that you need to break your back to accommodate out-of-touch users?

According to my Analytics for the last month, 33.72% of all visits were made using any version of Internet Explorer. Of the Internet Explorer visits,

48% were using IE8
34% were using IE7
17% were using IE6

So only 6% of all visits were made using IE6. I don't doubt that the figure varies from site to site, but surely they're a dying breed? Why not give them a push in the right direction?

Of course, I'm not selling anything, so I can afford to treat IE6 users like lepers.

swa66




msg:4028261
 7:23 pm on Nov 19, 2009 (gmt 0)

Last I checked I saw 12% of my visits to be from IE6 users.
A tab bit too much to tell them to take a hike.
Moreover customers needing a design still very much want IE6, I'll need to be able to proof far lower number before they switch into forgetting about IE6.

The advantage of doing IE last is that you can do those that you care about. Ad you can put as much effort it in as you want (in this case: we know IE6 doesn't do min-height, and we know an easy fix, so why not?)

vincevincevince




msg:4028503
 2:44 am on Nov 20, 2009 (gmt 0)

We have been supporting IE6 only to usable levels for some time; that means page are not always consistent with other browsers, tidy or neat... but they are usable.

Those using IE6 are already finding much of the internet both broken-looking and broken functionally so if your site is broken but functional, you are serving IE6 users well.

UserFriendly




msg:4028761
 1:30 pm on Nov 20, 2009 (gmt 0)

Well, I have to confess that I only use Linux for serious work (Windows is only installed on my machine so I can play DirectX games). And because Microsoft build their browser into their operating system, rather than release a standalone browser package that I can run in Linux (under Wine, for instance), I have no way of testing any version of Internet Explorer in Linux.

So I just stick to W3C standards, test in Firefox, Opera, Lynx, etc, and don't bother testing in IE at all. If MS can get their browsers to render standards-based markup properly, great.

As I said, it really helps that I'm not selling anything.

astupidname




msg:4031398
 9:54 am on Nov 25, 2009 (gmt 0)

See recent posts of interest by SuzyUk and me in the other 'branch' of this thread: here [webmasterworld.com] in regards to the now-apparently-not a hasLayout issue.

Drag_Racer




msg:4059300
 8:20 pm on Jan 12, 2010 (gmt 0)

great work to all involved on this.

on a side note about IE6. It is not going away anytime soon folks, so get used to it. There is specific functionality that only IE6 can provide and too much corporate software written for this fuctionality. It is estimated to be a player for another 8-10 years.

This 42 message thread spans 2 pages: < < 42 ( 1 [2]
Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / CSS
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved