IE7beta position:relative bug on top value

Note: This bug has been fixed in IE7 Release Candidate 1. If you still see the described effect, download the latest release here: http://www.microsoft.com/ie.

The html for the below examples is as follows:

<div id="container">
   <h2>heading</h2>
   <div id="outer">
      <div id="inner">
	<pre>
	text content
	</pre>
      </div>
   </div>
</div>

Note that all examples below display correctly in modern browsers, including IE5.01 (!), and to see the effect you need to view this page with IE7beta. (fixed in IE7 RC1)

Nothing wrong yet

The inner div with the red border shows 10px to the top and left of its original position.

#container1{
	position:relative;
	padding:30px;
}
#outer1{
	border:2px dashed black;
}
#inner1{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Adding a border on a container

There's a 1px change in the offset, but hardly noticeable yet.

#container2{
	position:relative;
	padding:30px;
	border:1px solid pink;
}
#outer2
	border:2px dashed black;
}
#inner2{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Changing border-width on container

I've chosen a border-width of 10px, which matches the negative offset on the inner div. The result is no vertical offset at all.

#container3{
	position:relative;
	padding:30px;
	border:10px solid pink;
}
#outer3{
	border:2px dashed black;
}
#inner3{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Worse even

Here you see that it's not just a matter of the negative top value being ignored, but it being deducted from the border-width of the container. A border-width of 25px, plus the negative top value of -10px, results in a positive offset of 15px.

Note: the same bug effects positive top value, but I used the negative value in the examples because they show the effect clearer.

#container4{
	position:relative;
	padding:30px;
	border:25px solid pink;
}
#outer4{
	border:2px dashed black;
}
#inner4{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Simple remedy?

Add position:relative to the outer div almost seems to fix it, but not quite. The following example superficially looks correct, but there is still a difference in offset between left and top values.

#container5{
	position:relative;
	padding:30px;
	border:25px solid pink;
}
#outer5{
	position:relative;
	border:2px dashed black;
}
#inner5{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Exaggerating to see it better

Again, making the parent's border wider, to see the real effect. The black border is 30px wide. Deducting the -10px of the top:value, gives it a positive offset of 30-10=20px. (if the top value would be +10px, the positive vertical offset would be 30+10=40px)

#container6{
	position:relative;
	padding:30px;
	border:25px solid pink;
}
#outer6{
	position:relative;
	border:30px dashed black;

#inner6{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Work-around

Adding a border-less relatively positioned wrapper between the #outer and #inner div solves it.

#container7{
	position:relative;
	padding:30px;
	border:25px solid pink;
}
#outer7{
	position:relative;
	border:30px dashed black;
}
#wrapper7{
	position:relative;
}
#inner7{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
	

Extra info

In short, the bug causes the borderwidth of a relatively positioned ancestor to be added to the positive or negative value of a relatively positioned child element. It only occurs if an ancestor (even multiple 'generations' back) has position:relative [1] as well as a border.

[1] only position:relative has effect; position:fixed, absolute, and floating have no influence.

The following example is to demontrate the effect of the bug with multiple elements in between cause and effect of this bug. I placed 4 nested divs around the outer div, with class="extra8". The trigger is still the 25px wide pink border on the relative positioned #container8.

#container8{
	position:relative;
	padding:30px;
	border:25px solid pink;
}
#outer8{
	border:2px dashed black;
}
#inner8{
	position:relative;
	top:-10px;
	left:-10px;
	border:2px dashed red;
}
.extra8{
	border:1px solid black;
	padding:10px;
}