Using overflow: for self clearing..!?

It seems magical. For yeahs we have all looked for pure-CSS ways of preventing a container of floated elements from collapsing on itself, then “lo and behold!” there is “overflow:hidden/ overflow:auto”. It does the trick cleanly, elegantly and it even works in IE!

Well I just have one tiny issue with this that I hope someone in the forum can help me with before I HAVE to resort back to using a shim div :(.

I have a wrapper that needs to contain two floated divs and a bg that needs to be visible, and thus needs to have some way of self clearing. The design also indicates that a visual element that heads the first div protrudes above the container div. I Suppose there are ways to do this with images in the element that precedes the wrapper, but it seems to me the most logical and semantic way would be to keep the the top element inside the floating div and then give that floating div either relative positioning or a negative top margin. the problem is since i have already used “overflow:auto” the parts that would other wise jot out of the container are not cropped by it.

Do I NEED to resort back to clearing with a div or clearfix for this kind of thing or is there something I am missing?

If you want to visualize what I am saying, take a look at this sample code:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Untitled Document</title>

<style>
	#side{ width:25%;  margin-top:-35px; float:left; background:yellow;}
	#main{ width:75%; margin-left:20px;  float:right; margin-right:-40px;; margin-top:20px; position:relative; right:2%; background:orange; }
	body{background: #A37700;margin:0 }
	.cwrap{padding-right:40px; width:920px; margin:0 auto;  background:pink; overflow:auto; }
	/*.cwrap:after{content:""; display:block; clear:both;}*/
	#hed{height:100px; background:#033}
</style>
</head>



<body>
     <div id="hed">
     <!--hed--></div>
     <div class="cwrap">
     <div id="main">ddd
     <!--main--></div>
          <div id="side">
               <h2>This is a headline</h2>
               <p>ss<br>ss<br>ss<br>ss<br>ss<br>ss<br></p>
               <p>ss<br>ss<br>ss<br>ss<br>ss<br>ss<br></p>
               <h3> am the last child now</h3>
          <!--side--></div>
     <!--cwrap--></div>
     <div class="">snsnsns</div>
</body>
</html>


I didn’t see paul’s solution when I wrote mine… happens when I open up ten tabs and then answer them in order.

Position:relative is a great solution too though I’d not use it how Paul did.

Position:relative with top/left/bottom/right only changes where the element is rendered and NOT where it’s actually positioned so far as document flow is concerned, you could do top:-35px to change where it’s rendered and the #cwrap box likely wouldn’t care or render upward… though you’d have 35px ‘blank space’ from where it was moved from… margin-bottom:-35px could then be used to shrink the flow box accordingly… though again the overflow state would chop that off.

It MIGHT be simpler to implement it as a 100% min-height layout with faux-columns either as a separate entity, or to just put it on the 100% min-height wrapper. Then you don’t need to worry about clearing on the columns themselves.

I wasnt concerned so much with the columns as with the container, as it may contain a b/g image, faux column or what not.

Well, your code is full of issues… trying to use % width columns being just one of the problems. Mixing margins with relative positioning on a percentage width float?!? That’s just asking for problems.

As a rule of thumb I prefer to explicitly say that IF something is going to poke out of a container, it shouldn’t be in the container in the first place. Your wrapping div for whatever reason probably can’t do this, but as a possible solution I’d pad the top of your content column and apply a background-image (or for simplicity to demonstrate I’ll use border) to push the content area back down.

I’m kind-of guessing this is what you were trying to do. You have a ton of contradictory margins and padding in there that seemed to be fairly pointless I got rid of. that’s -35 on the left column and -20 overlap on the right, correct?

When you can’t make the elements actually appear how you want, fake the appearance. It works with columns, it works here.

<!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"
	lang="en"
	xml:lang="en"
><head>

<meta
	http-equiv="Content-Type"
	content="text/html; charset=utf-8"
/>

<meta
	http-equiv="Content-Language"
	content="en"
/>

<title>
	wrapping demo	
</title>

<style type="text/css"><!-- 
body{
	background:#A37700;
	margin:0;
}

#side {
	width:25%;
	float:right;
	margin-left:-3px;
	background:yellow;
}

#main	{
	width:75%;
	float:right;
	background:orange;
	border-top:15px solid #033;
}

.cwrap{
	overflow:hidden;
	width:920px;
	margin:-35px auto 0;
	background:pink;
}


#hed{
	height:100px;
	background:#033;
}
--></style>

</head><body>

<div id="hed">
<!--hed--></div>

<div class="cwrap">

	<div id="main">
		ddd
	<!--main--></div>

  <div id="side">
		<h2>This is a headline</h2>
		<p>ss<br>ss<br>ss<br>ss<br>ss<br>ss<br></p>
		<p>ss<br>ss<br>ss<br>ss<br>ss<br>ss<br></p>
		<h3> am the last child now</h3>
  <!--side--></div>

<!--cwrap--></div>

<div class="">snsnsns</div>

</body></html>

It also helps to stack your floats the SAME direction, then you only need a negative of 3px on the non-stacking side to prevent perfect width drop.

Hi,

If you want visible overflow then you can’t use overflow:hidden or auto.

You could just use the :after{} rule to clear the container as in the clearfix and as you already have commented out in your stylesheet.

IE6 and 7 are already in haslayout mode and will auto clear.

You will need to add position:relative to #side or IE6 won’t show it.

Or you could create a new block formatting context with display:table which will auto clear floats also.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Untitled Document</title>
<style>
#side {
    width:25&#37;;
    margin-top:-35px;
    float:left;
    background:yellow;
[B]    position:relative;[/B]
}
#main {
    width:75%;
    margin-left:20px;
    float:right;
    margin-right:-40px;
    margin-top:20px;
    position:relative;
    right:2%;
    background:orange;
}
body {
    background: #A37700;
    margin:0
}
.cwrap {
    padding-right:40px;
    width:920px;
    margin:0 auto;
    background:pink;
  [B]  display:table;[/B]
}
/*.cwrap:after{content:""; display:block; clear:both;}*/
    #hed {
    height:100px;
    background:#033
}
</style>
</head>
<body>
<div id="hed">
    <!--hed-->
</div>
<div class="cwrap">
    <div id="main">ddd
        <!--main-->
    </div>
    <div id="side">
        <h2>This is a headline</h2>
        <p>ss<br>
            ss<br>
            ss<br>
            ss<br>
            ss<br>
            ss<br>
        </p>
        <p>ss<br>
            ss<br>
            ss<br>
            ss<br>
            ss<br>
            ss<br>
        </p>
        <h3> am the last child now</h3>
        <!--side-->
    </div>
    <!--cwrap-->
</div>
<div class="">snsnsns</div>
</body>
</htm


However display:table changes the way the element behaves so use with care.

Hi,

The position:relative in my example was just for an IE6 bug. I didn’t move anything with relative positioning. I just shifted the element with negative margins which does the job easily and with no extra changes needed.:slight_smile:

When you use negative margins in IE6 to pull stuff out of a container then 99% of the times you will need to add position:relative also because as you drag the element out of its container the part that should be visible seems to disappear under the background of whatever is above. It’s not the usual z-index issue but just a bug although z-index would come ito play if positioned elements were above and had greater z-index applied.

would dispaly:table work with older versions IE? It seems to have the same effect as overflow in FF

No, I think you have missed a vital part of the concept there;).

IE6 and 7 don’t understand display:table and they also don’t use overflow to clear floats. IE6 and 7 need haslayout applied and then they auto clear floats. For IE6 you will need a haslayout trigger such as a dimension or zoom (or one of the other triggers).

For IE7 the same applies but in IE7 overflow (other than visible) is also a “haslayout” trigger which is why the overflow method also appears to work for IE7.

The reason for other browsers that overflow clears float is because elements that create a new “block formatting context” will auto clear their child floats. i.e. overflow (other than visible), display:table, display:inline-block, position:absolute (table cells and table captions).

You could therefore clear floats using inline-block or even making it position:absolute but unlike overflow you are effectively changing the intrinsic behaviour of the element (which may not be a problem depending on circumstance).

Paul:

Thank you for you input. Yeah, I wasn’t sure if there was a trick or not to allowing a SPECIFIC element to protrude from an overflow.

just curious about as to why position:relative is needed for IE6. The reason I used margin was actually to avoid using positioning (this is a preference not an issue… I am just saying I could have accomplished the same with position:relative; top:-35px; and gotten rid of the margin declaration… if I had known about old IEs)

would dispaly:table work with older versions IE? It seems to have the same effect as overflow in FF , Ch , Saf and Op… I understand that it may have some unforeseen side effects. Anything I should look for?

Shadow:

Yea My code was HASTILY put together after i realized I had posted a purely conceptual question ( I had no example or goal, just mild annoyance at that aspect of overflow). In fact, it think i just truncated some old code i had where I was experimenting with the border-image property. So yeah… the rest of the layout aspects where kinda arbitrary, sorry.

I actually THOUGHT exactly the same thing …( though I am not trying for the content area to protrude into the head area … JUST THE SIDEBAR[ that being said I could use your method and increase #main’s top border]). but then I realized sometimes the content needs to protrude too. … the way I was envisioning the example… let’s say the desigs achieves the illusion of depth by having what looks as a swatch of masking tape within which the H2 content is written. so the “tape” and its contents visually over laps the header and the content area.

semantically ,however, it would make little sens ( or it would seem to be a concession of markup to appearance) to put the H2 within the header div and then push it down… even tho I can see that that would be one way of achieving this…

anyway, i just wanted to explain my crappy code … both solutions are clever.