13.7 Centering an Element in a Window or Frame
NN 4, IE 4
13.7.1 Problem
You want to center an
element within the browser window or a frame of a frameset.
13.7.2 Solution
For optimum backward-compatibility, use the
DHTMLAPI.js library described in Recipe 13.3 to
support the following generalizable centerOnWindow(
) function in IE 4 or later and
Navigator 4 or later:
// Center a positionable element whose name is passed as
// a parameter in the current window/frame, and show it
function centerOnWindow(elemID) {
// 'obj' is the positionable object
var obj = getRawObject(elemID);
// window scroll factors
var scrollX = 0, scrollY = 0;
if (document.body && typeof document.body.scrollTop != "undefined") {
scrollX += document.body.scrollLeft;
scrollY += document.body.scrollTop;
if (document.body.parentNode &&
typeof document.body.parentNode.scrollTop != "undefined") {
scrollX += document.body.parentNode.scrollLeft;
scrollY += document.body.parentNode.scrollTop;
}
} else if (typeof window.pageXOffset != "undefined") {
scrollX += window.pageXOffset;
scrollY += window.pageYOffset;
}
var x = Math.round((getInsideWindowWidth( )/2) -
(getObjectWidth(obj)/2)) + scrollX;
var y = Math.round((getInsideWindowHeight( )/2) -
(getObjectHeight(obj)/2)) + scrollY;
shiftTo(obj, x, y);
show(obj);
}
13.7.3 Discussion
The primary challenge of centering an element in the browser window
occurs in Internet Explorer, which provides no direct
window object property for the
window's size, inside or out. Thus, we must turn to
other document-level objects and their measurements for clues about
the content region of the browser window.
All of this negotiation takes place in the DHTML API library with the
getInsideWindowWidth(
) and getInsideWindowHeight(
) functions. Although the process for obtaining these
measurements is the same for either axis, a small
document—which isn't as wide or as tall as the
window—might convey incorrect dimensions. Internet Explorer
provides
clientHeight and
clientWidth properties for all elements, which,
for the body element, reveal the dimensions of the
body space that is immediately visible through the browser window.
For IE 5 and later (including IE 6 in backward-compatible mode),
these dimensions for the body element supply the
full interior window dimension, even for a small document. This
changes, however, in CSS-compatibility mode for IE 6, where the
window space is revealed by the html element (the
parent element of the body). Thus, for browsers
that do not support the Netscape
window.innerHeight property (which pre-dates the
IE client properties), the two similar API support functions derive
the measures from the most revealing element, as in the one for
window height from Recipe 13.3:
// Return the available content height space in browser window
function getInsideWindowHeight( ) {
if (window.innerHeight) {
return window.innerHeight;
} else if (isIE6CSS) {
// measure the html element's clientHeight
return document.body.parentElement.clientHeight;
} else if (document.body && document.body.clientHeight) {
return document.body.clientHeight;
}
return 0;
}
Another factor to be concerned about is whether the document whose
positioning context you're using is scrolled along
either the horizontal or vertical axis. For example, as the user
scrolls the page downward, the 0,0 point of the positioning context
moves up, meaning that the y coordinate of the positioned element
must be increased by the number of pixels that the page has scrolled
in that direction.
As with most window-oriented properties, the W3C DOM Level 2 does not
offer properties for items such as document scrolling. Back in the
Version 4 browser days, Microsoft and Netscape developed their own
vocabularies and ways to access the scrolled position of a window.
Although Netscape 7 implemented the Microsoft properties
(scrollLeft and scrollTop) for
the sake of convenience, you can get more compatibility by branching
the scroll-awareness code for syntactical support for either the
Microsoft or Netscape way. The majority of lines in the
centerOnWindow( ) function in this recipe deal
with reading those factors, which are then applied to the final
coordinate values passed to the shiftTo( )
function of the DHTML API.
Centering
an element once, however, won't keep it centered if
the user scrolls the page or resizes the window. To compensate for
these typical user actions, you need event handlers that respond to
both window resizing and scrolling. A window-resizing event is
supported by all browsers capable of working with the DHTML API; a
scrolling event is restricted to IE 4 or later and Netscape 7 or
later. For these event handlers to work most smoothly, assign them as
event handler properties of the window object.
This means, however, that the functions invoked by the event handlers
are not capable of receiving arguments (i.e., the IDs of the
element(s) to keep centered). Therefore, the functions have to
further redirect execution to the centerOnWindow(
) function by passing the arguments manually, as in the
following example, which relies on a global variable
(isNN4) set in the DHTML API:
// Special handling for CSS-P redraw bug in Navigator 4
function handleResize( ) {
if (isNN4) {
// causes extra redraw, but must do it to get banner object color drawn
location.reload( );
} else {
centerOnWindow("banner");
}
}
// Keep centered during scroll
function handleScroll( ) {
centerOnWindow("banner");
}
window.onresize = handleResize;
window.onscroll = handleScroll;
To maintain a positioned element in a fixed-window position at all
times, the best solution is to make the element a fixed-position
element. You must still assign initial coordinates of the element
when the page loads because every browser window can be a different
size. Unfortunately, IE for Windows through Version 6 does not
support the fixed CSS position type.
13.7.4 See Also
Recipe 11.13 for controlling IE 6 CSS-compatibility modes.
|