[ Team LiB ] |
13.7 Centering an Element in a Window or FrameNN 4, IE 4 13.7.1 ProblemYou want to center an element within the browser window or a frame of a frameset. 13.7.2 SolutionFor 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 DiscussionThe 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 AlsoRecipe 11.13 for controlling IE 6 CSS-compatibility modes. |
[ Team LiB ] |