13.6 Centering an Element on Top of Another Element
NN 6, IE 5
13.6.1 Problem
You want to position an
element so that it is vertically and horizontally centered in front
of an element in the main document flow.
13.6.2 Solution
The following centerOnElement(
) function takes two arguments: the ID
of the main document element and ID of the positioned element to be
placed there. The function is compatible with browsers that support
W3C DOM element reference syntax:
function centerOnElement(baseElemID, posElemID) {
baseElem = document.getElementById(baseElemID);
posElem = document.getElementById(posElemID);
var offsetTrail = baseElem;
var offsetLeft = 0;
var offsetTop = 0;
// account for IE 6 CSS compatibility mode
while (offsetTrail) {
offsetLeft += offsetTrail.offsetLeft;
offsetTop += offsetTrail.offsetTop;
offsetTrail = offsetTrail.offsetParent;
}
if (navigator.userAgent.indexOf("Mac") != -1 &&
typeof document.body.leftMargin != "undefined") {
offsetLeft += document.body.leftMargin;
offsetTop += document.body.topMargin;
}
posElem.style.left = offsetLeft + parseInt(baseElem.offsetWidth/2) -
parseInt(posElem.offsetWidth/2) + "px"
posElem.style.top = offsetTop + parseInt(baseElem.offsetHeight/2) -
parseInt(posElem.offsetHeight/2)+ "px"
}
13.6.3 Discussion
As simple as this operation may sound in theory, the code that
accomplishes it must compensate for a variety of compatibility issues
affecting various versions and compatibility modes of Internet
Explorer. Another key point that makes this function generalizable is
that it bases its measurements on the rendered dimensions of both the
static and positioned elements. If the elements contain content that
flows (such as text), the dimensions will likely differ with browser
window size and, in some browsers, font preferences that
aren't overridden by document style sheets. This
function reads the rendered dimensions before calculating sizes and
locations.
The first part of the calculations obtains the absolute position of
the base element, wherever it may render in the document. This is an
iterative process that accumulates the offsetLeft
and offsetTop measures of the base element and any
elements that report in as offset parent elements. For many browsers,
the base element's offset measures are sufficient.
But IE 6 for Windows in CSS-compatibility mode needs to add the
offset parent's dimensions to get accurate
coordinates. Looping through the offsetParent
trail takes care of the problem.
Next is an adjustment for an anomaly that affects IE for the Mac. In
that browser, the absolute location of an element in the main
document is impacted by the left and top margins of the
body element. Unfortunately, there is no guarantee
that this adjustment will either work or be needed in future versions
of IE for the Mac. Future versions may or may not correct this
anomaly, making it too hazardous to branch for a specific numbered
version of IE at this time. It's something to watch
out for in future IE/Mac releases.
With the absolute location of the base element in hand, the final
calculations establish the coordinates of the positioned element. To
arrive at the value along any one axis, the inset dimension is
calculated by subtracting half the size of the positioned element
from half the size of the base element. Adding that difference to the
absolute coordinate of the base element provides the absolute
coordinate of the centered, positioned element.
You must also take into account the possibility that the user might
resize the browser window in such a way that the flow of the base
content changes—along with the position of the underlying
element. Because there is no inherent connection between the elements
(as there is with nested relative- and absolute-positioned elements,
as in Recipe 13.2), you need to provide an
onresize event handler for the window (typically
embedded as an attribute of the <body> tag)
that reinvokes the centering function. If multiple positioned
elements are centered on multiple base elements, the
onresize event handler can invoke a function that
makes repeated calls to centerOnElement( ), each
with the necessary pair of arguments.
Bear in mind that the offset properties used in the
centerOnElement(
) function are not part of the W3C DOM.
But nothing in DOM Level 2 provides the kind of vital information
needed for this kind of operation (and many other positioning tasks).
Although the properties were Microsoft inventions (first used in IE
4), Mozilla-based browsers also implement them. Thus, the function
works perfectly well in Netscape 6 and later.
13.6.4 See Also
Recipe 11.13 for IE 6 CSS-compatibility issues and how to govern
which mode the browser follows.
|