I think you can tell by my resume on Stack Overflow that I am no stranger to css and its behaviors. However, I just came across something I have not experienced before that seems completely incorrect--yet Firefox 27 and Chrome 33 and IE 11 all render it the same.
Here is the code (just two empty nested div elements is the html), which can be seen in this fiddle example:
CSS
div {
width: 50%;
height: 100px;
margin: 10px;
border: 1px solid red;
position: relative;
}
div > div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-color: cyan;
}
I would have expected the absolute
positioned div
to directly overlap the size of the relative
parent div
. I expected it would have had its positioning properties override the width
and height
and margin
positioning from the straight div
call. I would have expected this behavior (1) because it is more specific in its selector, and (2) because it is positioned absolute and given positioning calls to all four sides.
As you can see by the referenced fiddle above it in fact retains its width and height and seems to essentially "ignore" its positioning values all together. That is, I get the same positioning if the positioning values are taken out. I need to override the previously set properties like so...
width: auto;
height: auto;
margin: auto;
...to get the positioning to actually do something. This appears to be standard behavior given that all the main browsers are reacting the same. I suppose I have never noticed it before because normally my sizing of a wrapping div is done by a class and thus applies only to that div, while my positioning of the absolute child is done likewise, and I don't bother to set a width and height on it.
My question is seeking quote(s) and link(s) from the W3C documentation (or a highly respected source, such as from one of the major browser developers) that discusses why or that the width
or height
settings should override a setting of top
, right
, bottom
, left
, etc. settings. From the main page discussing absolute positioning, all I found was that either can be used to set the width/height, but the crux of my issue is that I would expect the more specific/last in cascade to take precedence no matter which way was defining the sizing. Yet this is not happening here.
@pjp found this sitepoint reference, stating:
Absolutely positioned boxes with both right and left having a value other than auto will effectively define the width of the element assuming that the element's width is auto. This may result in the element having no width at all if left and right positions occur at the same point or perhaps overlap. If the values for left,right and width are over-constrained and the direction property is ltr, right will be ignored. If direction is rtl, left will be ignored. Note that replaced elements with a width of auto will have the elements intrinsic width substituted and the preceding rules applied.
This exactly articulates the behavior I am seeing. It does not address why (officially) it is that way. I would have expected instead that either:
(1) A higher specificity or equal specificity but following in cascade order setting of width
and height
(whether explicitly by those properties or by the positioning properites) to take precedence.
(2) In the case of defining both at once (an illogical thing to do, but...):
div {
position: absolute;
width: 50%;
left: 0;
right: 0;
}
or
div {
position: absolute;
left: 0;
right: 0;
width: 50%;
}
That the last defining of width would supersede, so the first the positioning would win, and the second the width would win. This would be just like two definitions in the same block, like so:
div {
width: 50%;
width: 75%;
}
Here, width: 75%
wins because it is "last" defined for the property.
I think that your confusion comes from handling the specificity in an inteligent way.
It works on a mechanical way.
That is, every property that has a value is handled in a cascade way, without any consideration about what others properties are some how related.
The width property is inherited by the child as 50% because there is no width set on the child. forget about the posibility of calculating the width from the left and right properties, there is no width property defined, and that is it.
Then, you have also the left and right properties, both set to 0. (no discussion here, I think).
And then, in the w3c docs, you see
If the values are over-constrained, 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.
That is a cite with almost the exact words of the cite in your question, but coming from an authorative source
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With