- From: Mike Wilson <mikewse@hotmail.com>
- Date: Fri, 14 Mar 2008 23:04:55 +0100
- To: "'Www-style'" <www-style@w3.org>
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