Forum Moderators: not2easy

Message Too Old, No Replies

Realistic to use floats for page templates?

         

waveform

7:36 am on Jul 25, 2010 (gmt 0)

10+ Year Member



I have been playing with a page template which is very simple, just a header area at the top and a menu area on the left which is floated to the left of the body area. Eg:

----------------
header
----------------
menu | body


However, I have found that any use of "clear:both" anywhere within the body document with also clear the float used in the template! That is, a "clear:both" clears every float on the entire page.

I kind of expected "clear:both" to be restricted to either the last float encountered, or only floats at the same DOM level (ie. its previous siblings).

An HTML example below. Basically this means I shouldn't use "float" to define a template, right? Because it seems any "clear" in a document will ruin the template float. Is the how it's supposed to be? Seems rather impractical if so, but maybe I'm doing something wrong?


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="language" content="english">
<meta http-equiv="Content-Style-Type" content="text/css">

<title></title>

<style type="text/css">

body {
margin: 0;
padding: 0;
font: normal 1em arial,helvetica,sans-serif;
}

#tpl-header {
height: 100px;
background-color: #3287C7;
color: #FFFFFF;
}
#tpl-leftmenu {
float: left;
width: 200px;
padding: 10px;
background-color: #ffff00;
}
#tpl-body {
padding: 10px;
margin-left: 220px;
}

</style>

</head>

<body>

<div id="tpl-header">
this is the header
</div>

<div id="tpl-leftmenu">

this is the left menu<br/>
it floats to the left<br/>
of the content<br/>
<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>
menu item<br/>

</div>

<div id="tpl-body">

this is the body of the page<br/>
it displays to the right<br/>
of the floated menu.<br/>
<br/>
content<br/>
content<br/>
content<br/>
<br/>

<div style="float:left">this floats left...</div>
<div style="float:left">and so does this</div>
<div style="clear:both">this clears the above float <b>and the template menu float</b>!</div>
<div>which is why I am down here and not just below the above floats. sad face.</div>
<div>How am I supposed to use floats for a page template when any "clear" will destroy the template?</div>

</div>

</body>

</html>

SuzyUK

2:24 pm on Jul 25, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes it's very realistic, it always has been really, but in the past those poor floats have got a bad name because of their containment issues and IE's little quirks, however it's now OK, honest! :)

Is the how it's supposed to be? Seems rather impractical if so, but maybe I'm doing something wrong?


Yes I'm afraid it's is how it's supposed to be ;)
it's something to do with the parents containing (becoming responsible for is probably a better way to think of it) their floated children.. in this case the body does not know it contains the nav menu just like the tpl_body element does not know it contains those two floated children divs..

the boring theory is right here: 9.5.2 Controlling flow next to floats: the 'clear' property [w3.org] with the pertinent bit ref: clear:both; being (my bold!):

The clearance of the generated box is set to the amount necessary to place the top border edge below the bottom outer edge of any right-floating and left-floating boxes that resulted from elements earlier in the source document.


In short since this rule was written, all things float related have progressed a lot and their is now another property , it was a necessity eventually, which allows us to isolate one area of the page from another , though technically it just forces a parent to become responsible for it's own children


in your code there is no parent element which is actually being responsible for (containing) its floated children, so its defaulting to the above rule, and you are seeing is what you are supposed to see - as soon as you set that clear property it is doing exactly what it's supposed to and clearing ANY previous floats

OK skip past the boring bit.. the solution is to make the tpl_body responsible for (contain) it's own floated children, in the old days this wasn't so easy as the best way was to also float the main content element and likely set a width on it too to force it to be responsible, this then meant you couldn't let your main content column be the width of the page minus the width of the nav bar (i.e. an implicit width) which ruined the flexible width layouts - so the seeming "should be easy", flexible width, two column layout got unnecessarily complicated, and the whole situation made people think floats were unstable, that and the associated IE bugs/problems.. gave floats a bad name.. but that was then..

The solution is actually to use the same property on tpl_body that you would need if you were visually vertically trying to to contain the floated children, essentially the same technique for achieving vertical containment (e.g. faux columns) is also used for horizontal containment (flexible width)

add : overflow:hidden; to tpl_body

(the actual proper explanation is to use overflow with it's value set to anything other than visible (default), hidden is obviously best used when an elements height is not restricted as it might result in inaccessible content however overflow:scroll would do the same thing but might produce a scroll bar to allow hidden content to remain accessible, hiding an elements overflow to avoid say extra long long urls or large images breaking layouts is another logical and legitimate using for hidden over scroll, you can decide what's best for your templates!)

- this relatively new method of containing floats is backward compatible to IE7, but for IE versions before that you will still need add
zoom: 1;


If you do want that backward support you could that IE "hack" in a separate ie.css if you have one, it won't do any harm in the main.css but it will not validate as it's an IE proprietary property - "zoom:1;" is simply telling IE to display the page as 100% zoom (i.e. the default) but by declaring it explicitly it triggers their infamous hasLayout property which in this case we can use at it achieves the same effect of containing floats for those older IE versions

Now the other thing about this is that if you use this method you have actually made this template even more flexible than before, you actually do not need that left margin either - so if and when needed you can change the left column width without having to remember to change another bit too :) - because that tpl_body div has been forced to contain not only vertically but horizontally, it is now ignoring the left floated nav completely and will not flow around it as per a usual float scenario so it now only thinks it "area" is page width less the nav width - this is really cool for many scenarios where people want an element to be an unknown width but also be self contained (i.e. think a floated image of unknown width where you would like the caption no matter how long it is not to flow around the image, but instead to take up whatever space is left over) - then of course for Older IE's or IE in quirks who
just got floats and margins wrong anyway this proper way of doing things actually avoid the need to use margins thus avoiding the more complex hacks that used to be required, completely! ;)

anyway, I'm sorry this got way longer than I meant it to but I realised that this is probably something a few people don't know about, I can't find too much on this horizontal containment out there in the blogosphere, so perhaps us "here and now" CSS users should be educating on them so we can help people start to lose the "old clearing hacks" - I know it seems counter intuitive in this situation, but bearing in mind the more convoluted methods of containing floats, or achieving flexible width templates that have come and gone in the past - it's not bad if all that's left is a one line css hack for the soon to pass IE6..

Summary: when templating with floats you really just need to remember to tell the parents (main areas) to be responsible for their own "floaty" children.

waveform

4:03 pm on Jul 25, 2010 (gmt 0)

10+ Year Member



Ahhhhhhhhhhhhhh!

Thought I should add an extra long ahh in respect to your incredibly useful answer, I'm very very thankful indeed! You've explained it well. So it seems to be down to triggering some arcane internal rendering setting.. whether it's "hasLayout" or whatever the W3C-spawned equivalent is. People curse "haslayout" but here is the W3C equivalent!

I never thought to use "hidden", as it does have undesirable side effects as you mentioned, as does "overflow:auto" I found (scoll bars in some circumstances). Argh.. it's a pity that physically setting "overflow:visible" doesn't do the trick, that would have been perfect.. why doesn't the W3C think of these things?

I have, after some experimenting, found that setting "position:absolute" and "position:fixed" do the same thing. The clears are constrained to the positioned parent, yay! (I just went and tried every single property in the book) :) At least that gives people an option if overflow:hidden is undesirable.

W3C has given us a standard at least.. but some more consultation with developers & designers in the real world would have helped I think!