More CSS weirdness - position 

Displaying notes 1 - 3 of 3

Joined:
02/21/2009
Posts:
163

July 13, 2009 02:56:04    Last update: July 15, 2009 15:56:53
The CSS 2.1 spec has these definitions about the position property:
  • static: The box is a normal box, laid out according to the normal flow. The 'top', 'right', 'bottom', and 'left' properties do not apply.
  • relative: The box's position is calculated according to the normal flow (this is called the position in normal flow). Then the box is offset relative to its normal position. When a box B is relatively positioned, the position of the following box is calculated as though B were not offset.
  • absolute: The box's position (and possibly size) is specified with the 'top', 'right', 'bottom', and 'left' properties. These properties specify offsets with respect to the box's containing block. Absolutely positioned boxes are taken out of the normal flow. This means they have no impact on the layout of later siblings.
  • fixed: The box's position is calculated according to the 'absolute' model, but in addition, the box is fixed with respect to some reference.
    In layman's terms: the left, top, right, bottom parameters are relative to the browser window. (My explanation, not from the spec.)


Let's start with this page:
<!doctype html public '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
<html>
<head>
	<title>Weird CSS Position Behavior</title>
	<style type="text/css">
		body {
			font-family: serif;
		}

		#container {
			font-family: sans-serif;
			width: 120px;
			background-color: #ddd;
			color: green;
		}

		#content1 {
			color: blue;
		}

		#content2 {
			color: red;
		}
	</style>
</head>

<body>
	Body text
	<div id="container">
		Container text
		<div id="content1">
			Content 1
		</div>
		<div id="content2">
			Content 2
		</div>
	</div>
</body>
</html>


It renders nice and neatly in all browsers:



Weird things happen when you apply absolute positioning to one of the inner divs:
#content2 {
	color: red;
	position: absolute;
	top: 0;
	left: 0;
}


In all browsers I tested (IE, Firefox, Chrome), it rendered like this:



Now the question is, what is the containing block for #content2? By the rendered position, it must be body. But if the containing block is body, why did #content2 inherit the font from #container?

The hack: add a position property to #container:
#container {
	font-family: sans-serif;
	width: 120px;
	background-color: #ddd;
	color: green;
	position: relative;
}




Addendum (07/15/2009): It turned out that the browsers are working to the spec. My hack is actually following the spec to get the desired behavior. It is the spec that is weird! I'll rest the case if I can get one useful example that an element need to nest deeply in a document structure, but its presentation has to bubble up all the way to the initial containing block while retaining other properties from its parent element.
Share |
| Comment  | Tags
 
Joined:
04/09/2007
Posts:
775

July 14, 2009 17:08:05    Last update: July 14, 2009 20:51:22
Hooray James!

I tested in Opera and it behaved the same! So is the spec wrong or the implementation wrong? Or, may be they are both right. But why?
Share |
| Comment  | Tags
 
Joined:
04/09/2007
Posts:
775

July 15, 2009 01:13:47    Last update: July 15, 2009 02:18:37
James,

I posted your note to reddit and the feedback was that the browsers are behaving correctly by the spec. Look at the definition of "containing block". Especially, point 4:

If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way...If there is no such ancestor, the containing block is the initial containing block.
Share |
| Comment  | Tags