[CSS21] 10.3.7 & 10.6.4 - Absolutely positioned elements and incompatible offsets

CSS2.1 is careful to ensure that all possible cases are covered when
calculating the widths, heights and margins of absolutely positioned
elements for all possible values of 'left', 'right', 'top', 'bottom',
'margin', 'width' and 'height'.  However, the description of one of
these cases seems to be flawed.

<div style="position:relative; width:100px">
 <div style="position:absolute; left:60px; right:60px;">
</div>

(See test cases [1,2].)

As described in 10.3.7 Absolutely positioned, non-replaced elements,[3]
the constraint that determines the used values is:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width'
+ 'padding-right' + 'border-right-width' + 'margin-right' + 'right' =
width of containing block

According to the spec, in the situation given by the test case we must
set 'auto' values for 'margin-left' and 'margin-right' to 0 and, since
Rule 5 applies, we solve for 'width'.

Alas, this gives rise to an illegal 'width' used value of -20px.

The analogous situation for 'top' and 'bottom' with auto height exists
in 10.6.4 Absolutely positioned, non-replaced elements[4] where Rule 5
again requires solving for 'height'.


New and not-so-new versions of all major browsers agree on the visual
appearance of this situation (IE6 expansion of hasLayout blocks
notwithstanding), which is that 'left' is honoured and 'width' is set to 0.

With the exception of Firebug for Firefox, the browsers' developer tools
still leave something to be desired, and it's difficult or impossible to
discover the used values of 'right' and 'margin-right'.  IE8 fails to
report anything useful; Opera doesn't show which one of 'right' or
'margin-right' has been adjusted; and Safari doesn't show any
adjustments and reports 'width' as -20px.

Only Firefox shows that 'right' is adjusted and 'margin-right' remains
0.  This is reasonable to expect, and it seems likely that this is what
all browsers are doing.

All browsers are consistent in their handling of the horizontal and
vertical cases.


Accordingly, I propose the following amendments.

In 10.3.7, replace
   # 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
   # for 'width'
with
   | 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
   | for 'width'; if the resulting value for 'width' is negative then set
   | 'width' to 0, ignore the value for 'left' (in case the 'direction'
   | property of the containing block is 'rtl') or 'right' (in case
   | 'direction' is 'ltr') and solve for that value


In 10.3.7, replace
   # 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', then
   # 'auto' values for 'margin-top' and 'margin-bottom' are set to 0 and
   # solve for 'height'
with
   | 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', then
   | 'auto' values for 'margin-top' and 'margin-bottom' are set to 0 and
   | solve for 'height'; if the resulting value for 'height' is negative
   | then set 'height' to 0, ignore the value for 'bottom' and solve for
   | that value


Note that in both cases, the "ignore the value for..." phrase has been
copied from the paragraph above the list of the 6 rules.  Concerning
this phrase, shouldn't it say "solve for that *property*" rather than
"solve for that value"?


[1]
http://dev.moonhenge.net/css21/test-cases/positioning/incompatible-horizontal-offsets.html
[2]
http://dev.moonhenge.net/css21/test-cases/positioning/incompatible-vertical-offsets.html
[3] http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width
[4] http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height

Cheers,
Anton Prowse
http://dev.moonhenge.net

Received on Monday, 26 April 2010 07:09:30 UTC