W3C home > Mailing lists > Public > www-style@w3.org > April 2008

RE: [cssom-view] Why is body's offsetParent null ?

From: Mike Wilson <mikewse@hotmail.com>
Date: Wed, 23 Apr 2008 13:37:43 +0200
Message-ID: <BAY116-DAV18B261CFA1E7DA4B499FBA4E30@phx.gbl>
To: "'Anne van Kesteren'" <annevk@opera.com>, "'Www-style'" <www-style@w3.org>
Cc: "'Daniel Glazman'" <daniel.glazman@disruptive-innovations.com>
Message-ID: <016d01c8a536$72050dd0$0a01a8c0@mikedeskxp>

[sorry, this was sent prematurely due to fat fingers]

Anne van Kesteren wrote:
> On Wed, 23 Apr 2008 12:28:30 +0200, Mike Wilson 
> <mikewse@hotmail.com> wrote:
> > Though, the CSSOM scheme will break down if you want to know the
> > offset to the body element as there is no way to get at this
> > information.
> >
> > In particular, as Garrett pointed out, this offset is available 
> > in all browsers except Opera (and CSSOM) when using 
> > position:relative on the body element:
> > http://www.nabble.com/Re%3A--cssom-view--small-update-p16063070.html
> 
> Following that (special casing position:relative on the HTML 
> body element)  
> would break finding the position of an element within the page, as I  
> explained here:
> 
>    http://lists.w3.org/Archives/Public/www-style/2008Apr/0366.html

That's only the current behaviour of Firefox you're talking about, right? 
The Firefox algorithm is admittedly broken 
https://bugzilla.mozilla.org/show_bug.cgi?id=255754
and according to Boris Zbarsky they are waiting for your IE reverse-
engineering (done for this spec) before they do any changes or fix the 
bugs.

The offset behaviour in (standards mode) IE, when you have 
position:relative on the body element, will give you both offset between
body and viewport edge and between body and other elements:

offsetParent for/in: IE7        CSSOM
HTML                 null       null
 BODY                null       null
  div1(pos=rel)      BODY       BODY
   div2a             div1       div1
   div2b             div1       div1
    div3a(pos=abs)   div1       div1
    div3b            div2b      div1

offsetLeft for/in:   IE7        CSSOM
HTML(4m,2b,1p)       0          0
 BODY(32m,16b,8p)    39         0
  div1(4m,2b,1p)     12         67
   div2b(32m,16b,8p) 33         33
    div3b(4m,2b,1p)  12/div2b   61/div1

Note 1: IE gives you both BODY's offset against viewport and div1's
        offset against BODY while CSSOM skips over BODY.

Note 2: IE gives an ideal offset and offsetParent chain that will work
        with any recursion wherever it stops.
        (although ignoring most things on the root element)

Note 3: IE honors the Containing Block algorithm for div3b for its 
        offsetParent choice.

I think the above IE algorithm would be much preferred compared to the
broken FF algorithm that CSSOM partly derives from.

Best regards
Mike Wilson

The example used for the above test is:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1">
		<title></title>
		<style type="text/css">
			* {
				border-color: gray;
				border-style: solid;
			}
			html {
				margin: 4px;
				border-width: 2px;
				padding: 1px;
			}
			body {
				position: relative;
				font-family: verdana, arial, helvetica,
sans-serif;
				font-size: 77%;
				margin: 32px;
				border-width: 16px;
				padding: 8px;
			}
			div {
				height: 30px;
				overflow: hidden;
				text-align: right;
			}
			#div1 {
				position: relative;
				height: auto;
				margin: 4px;
				border-width: 2px;
				padding: 1px;
			}
			#div2a {
				margin: 32px;
				border-width: 16px;
				padding: 8px;
			}
			#div2b {
				height: 60px;
				margin: 32px;
				border-width: 16px;
				padding: 8px;
			}
			#div3a {
				position: absolute; 
				left: 64px; 
				top: 64px; 
				margin: 4px;
				border-width: 2px;
				padding: 1px;
			}
			#div3b {
				margin: 4px;
				border-width: 2px;
				padding: 1px;
			}
		</style>
		<script type="text/javascript">
			function printOffsetData( elem ) {
				document.write( "Element: " + (elem.id ||
elem.tagName) + "<br>" );
				document.write( "offsetLeft/Top: " +
elem.offsetLeft + "/" + elem.offsetTop + "<br>" );
				document.write( "offsetParent: " +
(elem.offsetParent && (elem.offsetParent.id || elem.offsetParent.tagName)) +
"<br>" );
				document.write( "<br>" );
			}
		</script>
	</head>
	<body>
		<div id="div1">
			<div id="div2a">div2a</div>
			<div id="div2b">
				<div id="div3a">div3a</div>
				<div id="div3b">div3b</div>
				div2b
			</div>
			div1
		</div>
		
		<script type="text/javascript">
			printOffsetData( document.documentElement );
			printOffsetData( document.body );
			printOffsetData( document.getElementById("div1") );
			printOffsetData( document.getElementById("div2a") );
			printOffsetData( document.getElementById("div2b") );
			printOffsetData( document.getElementById("div3a") );
			printOffsetData( document.getElementById("div3b") );
		</script>
	</body>
</html>
Received on Wednesday, 23 April 2008 11:38:45 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:55:05 GMT