In this edition of the Weekly Web Hack, I'll explain the difference between the four possible values for the 'position' CSS attribute, focusing on the meaning of position:absolute.
By the end of this article, you should be able to:
There are four possible values for the 'position' attribute, described briefly below:
This is the default. When an element has position:static, it will exist within the regular "flow" of the page. Elements with position:static may have values for their 'top' and 'left' positions, but they will be ignored.
When an element has position:relative, then the 'top' and 'left' values represents offsets from where the element would otherwise normally appear.
For example, if an element had position:relative and top:-10px, then it would appear on the page shifted up 10 pixels towards the top of the page from where it would normally appear.
An element which has position:fixed will remain at the same location, defined by its 'top' and 'left' attributes, relative to the viewable portion of the page. That is, if the user scrolls the page, any elements with position:fixed should remain in the same place with respect to the boundaries of the viewport.
A common mistake made by new HTML/CSS/JS developers is to assume that position:absolute means that the element will be positioned absolutely with respect to the document body. That is, that such an element will appear a static distance from the top and left of "the page" regardless of scrolling. This is only half true. An element with position:absolute will be positioned according to the coordinates specified in its 'top' and 'left' attributes, relative to the nearest positioned ancestor.Let's break that down a bit. An ancestor of an HTML element is any element upwards in the DOM tree. So in this example:
<ol><li><span>hello!</span></li></ol>Both the <ol> and <li> elements are both "ancestors" of the <span>. Because they both have no position attribute specified, the default of position:static is assumed, and therefore they are not considered to be "positioned".
Consider though that they are both positioned - say they both had "position:relative". In that case, the <span> element's nearest positioned ancestor would be the <li> since it's nearer than it's parent, the <ol>.
One problem with the above is the case where it is desired to take an HTML element and place it at a known coordinate relative to the page. This can be achieved by some gentle DOM manipulation. Consider this HTML fragment:
<div id="wrapper" style="width:600px;position:absolute;top:0;left:auto"> Main wrapped content. <div id="popup" style="display:none"> Some popup content. </div> </div> <div
As you can see, the "wrapper" div has a static 600 pixel width, with an automatically calculated 'left' attribute, and a 0 pixel 'top' offset. Let's say we want to display the "popup" div at a particular exact location relative to the page. Consider this snippet:
var popup = document.getElementById('popup'); popup.style.position = 'absolute'; popup.style.top = '100px'; popup.style.left = '100px';
The problem here is that since the popup div has a positioned ancestor (the wrapper div), it will not be placed at the 100x100 pixel location as expected.
The workaround is to reassign the popup div to the document body so that it's nearest positioned ancestor will be the document body itself. Here is the updated snippet:
var popup = document.getElementById('popup'); popup.style.position = 'absolute'; popup.style.top = '100px'; popup.style.left = '100px'; // Note: this will automatically detach popup from the "wrapper" div and reassign it to the document body document.body.appendChild(popup);
And that's it! Really, that's all it takes. I write this article in hopes that it helps someone else. Not understanding the nature of position:absolute and the necessity of reassigning members to the document body cost me a good chunk of time on an otherwise simple task recently.
Good luck! As always I'll be happy to answer any questions.
Got something to say?
or, read what others have said...