RE: [cssom-view] small update

Hi Anne,

I think this is an interesting (although somewhat animated ;-) 
discussion about the offset properties and I think Garrett is
bringing up some good points.

I have studied some of the differences between the various
approaches and made some comparison tables below. There are
lots of data here so please excuse (and inform me) if something 
is not correct. The HTML file used for testing is at the end of 
this mail.

Explanation of labels:
- IE7/FF2: tested in Internet Explorer 7 / Firefox 2
- CSSOM: http://dev.w3.org/csswg/cssom-view, 11 March 2008
- [CB]: Containing Block according to CSS 2.1
- simple?: the simplest / most natural value if legacy was
  not to be considered (I realize there may be opinions about
  this so no flaming please ;-)

offsetParent
------------
This is the offsetParent returned for the respective elements
in the example file per browser/spec:

offsetParent for/in: IE7     FF2     CSSOM   [CB]    simple?
HTML                 null    null    null    ICB     null
 BODY                null    null    null    HTML    HTML
  div1(pos=rel)      HTML    BODY    BODY    BODY    BODY
   div2a             div1    div1    div1    div1    div1
   div2b             div1    div1    div1    div1    div1
    div3a(pos=abs)   div1    div1    div1    div1    div1
    div3b            div2b   div1    div1    div2b   div2b

Observations:

1) CSSOM differs from IE by letting div1 point to BODY instead
   of HTML. 

   Q: What was the rationale for this change? (I agree that it 
      is "cleaner" not to special-case children of BODY to
      instead point to HTML, but IE is the mother of these 
      properties so...)

2) IE points div3b to div2b (as opposed to div1 in CSSOM).
   In this respect IE matches the rules for Containing
   Block to determine offsetParent. I have the impression that
   the offset properties were designed in the "spirit" of 
   Containing Block for consistency with dimensional properties
   top, left etc. These are interpreted with respect to the CB 
   so it would make sense to let the corresponding offset 
   properties also do this. [The "simple?" column maps the CB 
   algorithm]

   Q: Did you consider using the CB algorithm for offsetParent
      and were there any hard problems?

   Q: Have you considered CSSOM's deviation with IE for div3b 
      above or is it something that needs to be fixed in the 
      spec?

offsetLeft (and others)
-----------------------
Note: the example file assigns margin, border and padding to 
all elements including the HTML element. Values of these 
properties are indicated below in parenthesis (m,b,p) and the
body of the table shows the value of offsetLeft:

offsetLeft for/in:   IE7        FF2        CSSOM      simple?
HTML(4m,2b,1p)       0          -2*        0          4
 BODY(32m,16b,8p)    39**       -16*       0          33/HTML
  div1(4m,2b,1p)     67**/HTML  47*/BODY   67***/BODY 12/BODY
   div2b(32m,16b,8p) 33         31*        33         33
    div3b(4m,2b,1p)  12/div2b   43*/div1   61/div1    12/div2b

*   The Firefox algorithm seems to be completely different and
    I have no guess on how to interpret this.
**  The BODY=39 and div1=67 values actually are not the 
    distance to the border edge of the |HTML| element but 
    rather the distance to its margin edge or to the 
    viewport's left edge.
*** The value 67 is actually not the distance to the border 
    edge of the |BODY| element but rather the distance to the 
    viewport's left edge.

Apart from where noted, all offsets in the table add up 
correctly according to the "padding edge to border edge" rule.

Adding some relative positioning, this is what happens:

offsetLeft for/in:   IE7        FF2        CSSOM
BODY left+10px       39->49     -16        0
div1 left+10px       67->77     47->57     67->77

So, to my observations: 

3) As can be seen in both tables IE returns useful values for
   BODY's offsetLeft property while CSSOM hardwires it to 0.

   Q: What was the rationale for this deviation from IE's 
      behaviour?

4) As can be seen in the upper table, CSSOM returns offsetLeft
   = 67 for div1, which is the distance to the viewport edge or
   margin edge of the |HTML| element, even though div1 reports 
   using BODY as offsetParent, thus:
     div1.offsetLeft = <distance to viewport/HTML>
     div1.offsetParent = BODY
   It would be more consistent to use
     div1.offsetLeft = <distance to HTML>
     div1.offsetParent = HTML
   or
     div1.offsetLeft = <distance to viewport>
     div1.offsetParent = null
   or
     div1.offsetLeft = <distance to BODY>
     div1.offsetParent = BODY

   This change from IE's behaviour leads to returning an 
   offsetParent that isn't the element used when calculating 
   offsets, which is inconsistent.

   Suggestion: use one of the suggested combinations above,
   probably best to return offsetParent = null or HTML.
   (This relates to observation 1 above.)

   [Btw it seems everybody is using margin edge instead of
   padding edge when measuring from the |HTML| element]

Finally, for comparison, the "simple?" column in the upper 
table shows what offset values would be returned from the 
simplest possible algorithm without special-casing 
certain elements. Unfortunately, and as expected, it is not 
compatible with IE for div1 and up.

Best regards
Mike Wilson

Example file:

<!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 {
				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>
	</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>
	</body>
</html>

Received on Friday, 14 March 2008 22:05:39 UTC