Forum Moderators: not2easy
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%;
}
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;
}
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;
}
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:
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;
}
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]
In a scientific test you only want to introduce one variable to the equation to see the effects on the system. Adding more than one and you'll have no idea which variable did what. That holds true with website design as well.
design in both Firefox AND IE simultaneously
The second problem is that IE is going to hold you back in what you can do, preventing you from doing anything beyond the most basic CSS. Instead of allowing you to use all the spectrum of what's possible and then give you the option to find in the end something that looks OK enough for these legacy versions.
Moreover IE constantly sets you on the wrong foot, slowing you down significantly.
Mixing in workarounds for legacy IE versions in the main CSS is also counterproductive in the long term as it encourages browser crafters to emulate the bugs in old versions IE.
The worst of it all: dealing with all the IE bugs just drives you nuts.
No IE. Yes, that's the start: ditch the browser of choice of the majority of your users. It's critical to do this if you value your sanity.
[edited by: kapow at 2:43 pm (utc) on Nov. 11, 2009]
Just one small note I want to add:
In IE8, if you resize your viewport to say half the height of your screen and then refresh the page, it looks good. But when you then drag the bottom of your window down so the viewport gets higher, the footer doesn't stick to the bottom. In order to fix this, you have to add height: 100%; to the body tag.
Yes, that's the start: ditch the browser of choice of the majority of your users.
That's where I stopped reading. Clients don't care about technical or political issues with browsers. They hire people to simply make it work. Most of the client stats that I look at still show 10% to 18% of all visitors use IE6.
However, after completing the development, I would definitely consider going through and testing/developing for IE 6. An alarming percentage of users still use IE 6, and you don't want to exclude them from interacting with your website.
I don't like IE 6 at all, but some of our largest clients use only IE 6. While it costs some sanity, being able to deliver a quality product speaks for itself.
Often times larger organizations resist updating their browser versions. This is because it can be a potential IT nightmare. Some of our clients are behind massive firewalls and are not able to even download basic flash updates.
The three industries I've see still using IE 6 are:
Construction,
Law (firms etc...),
Health Insurers
Granted not everyone in those industries is using IE 6, there are many that do.
On that note, here's an IE 6 hack that we use for min-height. I insert it into a separate style sheet that is placed between the <!--[if IE 6]> <![endif]--> .
.header {
min-height:110px;
height:auto !important;
height:110px;
}
Thanks,
-JB
I've tried to reproduce the problem you describe:
In IE8, if you resize your viewport to say half the height of your screen and then refresh the page, it looks good. But when you then drag the bottom of your window down so the viewport gets higher, the footer doesn't stick to the bottom.
Did you use the last code segment in the original post?
In order to fix this, you have to add height: 100%; to the body tag.
The min-height on the body takes care of it in this example. It changes if you use an additional wrapper, but in this case the min-height seems to work just fine in IE8 (even if you toggle it back to IE7). It's only IE6 that doesn't know what min-height is.
Yes, I used the last code segment in your original post. I'm able to reproduce the problem on another pc (and the 100% height fixes it again).
After you resize the viewport to half the height of your screen, make sure you refresh the page so the vertical scrollbar disappears. Then, drag the bottom of the IE window down so the viewport gets higher. My guess is that you didn't refresh the page?
I tried refreshing on large, small viewports, both vertically and horizontally both with and without scrollbars: I've not seen the effect you describe once.
I tried it with IE8 in IE8 and in IE7 mode: made no difference whatsoever.
I run a rather virgin IE8 on XPSP3 in a virtual machine (parallels).
Anybody else that can trigger this with IE8 and the code provided ?
why use .header etc rather than #header
So the question might be when to use a class or an id.
An id is only allowed once in a html document, a class can occur multiple times.
In this case an id would have done just fine, it can even be argued to be better.
I didn't stop to think about it (the goal was different), if I did I might actually have gone for an id in hindsight.
Thanks for that - I have been reading books on CSS and using CSS for a while and it was only last week that I eventually started to use class as well as id. Is this a common mistake when using CSS, to not understand how and when to use Class?
(not in your example, in my own use of ID and not using Class)
So the question might be when to use a class or an id.
An id is only allowed once in a html document, a class can occur multiple times.
In this case an id would have done just fine, it can even be argued to be better.I didn't stop to think about it (the goal was different), if I did I might actually have gone for an id in hindsight.
<body id="home">
<div id="header">
...
</div>
<div id="content">
<div class="article">...</div>
<div class="article">...</div>
<div class="article">...</div>
</div>
<div id="footer">
...
</div>
</div>
The important distinction is that id's must be unique and only appear once on a page. If you think you're styling a more general "class" of elements, then use class.
[edited by: swa66 at 11:38 am (utc) on Nov. 15, 2009]