TJKDesign: Home Page

ez-css Putting the 'less' in table-less layouts. css-101 logo
Bookmark this article at these sites:

Creating and Positioning an Overlay using the YUI

Hacking the container script

I must say that the YUI Library is awesome! Scripts are so well commented that even a Javascript newbie like me can hack his way ;-)

While checking examples of overlays, I noticed a few things about the centered overlay:

  1. when the page scrolls, the overlay jitters (check using the mousewheel)
  2. when the window is resized, the overlay jumps
  3. when the overlay is taller than the viewport, part of it is not accessible

I realized that "position:fixed" and negative margin would be great candidates to solve issues #1 and #2, while CSS expressions could help make things look as good in IE 5 and 6 (note that CSS expressions are an option that can be removed).

This frameset will help you compare the original script with the "enhanced" version. Clik on the "show" button in both windows to reveal the overlays and then scroll the page and/or resize your browser window to see how things differ.

How things work

The methods:

Replace the methods you find in "container.js" with the ones below (note that the methods I edited were from version 2.3.1).
Check the comments to see what to edit in case you prefer not to use CSS expressions.

/**
* Center event handler used for centering on scroll/resize, but only if
* the Overlay is visible and no taller than the viewport height
* @method doCenterOnDOMEvent
*/
doCenterOnDOMEvent: function () {
// If the viewport is not tall enough, we do not vertically center the overlay
  var winHeight = (document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientHeight : document.body.clientHeight;
    if (this.cfg.getProperty("visible") && (this.element.offsetHeight < winHeight)) {
        this.center();
    }
},

/**
* Centers the container in the viewport.
* @method center
*/
center: function () {
  var elementWidth = this.element.offsetWidth,
    elementHeight = this.element.offsetHeight,
    viewportHeight = (document.compatMode && document.compatMode=='CSS1Compat') ? document.documentElement.clientHeight : document.body.clientHeight;
// Is the overlay smaller than the vieport?
  var highEnough = (viewportHeight > elementHeight);
// We use negative margin to center the overlay
    this.element.style.left = "50%";
    this.element.style.marginLeft = - (elementWidth / 2) + "px";
    // UnComment the following line if you prefer not to use CSS expressions
    // this.element.style.top = (highEnough) ? "50%" : Dom.getDocumentScrollTop() + "px";
  if (typeof document.body.style.maxHeight == "undefined") {
    // Uncomment the following line if you prefer not to use CSS expressions
    //this.element.style.marginTop=(highEnough) ? - (elementHeight / 2) + Dom.getDocumentScrollTop() + "px" : "0";
  }else{
    // Comment out the following line if you prefer not to use CSS expressions
    this.element.style.top = (highEnough) ? "50%" : Dom.getDocumentScrollTop() + "px";
    this.element.style.marginTop = (highEnough) ? - (elementHeight / 2) + "px" : "0" ;
    (highEnough) ? this.element.style.position = "fixed" : this.element.style.position = "absolute";
  }
  this.cfg.refireEvent("iframe");
},

The CSS rules:

If you prefer not to use CSS expressions, then ignore the rules below entirely (except "position:absolute" for the overlay) and make sure to edit the javascript above as explained in its comments.

<style type="text/css">
.yui-overlay {position:absolute;}
</style>
<!--[if IE 6]>
/* Usual hack to reduce jittering in IE 6 */
html {background:url(nada);}
<style type="text/css">
.yui-overlay {
top: expression((documentElement.clientHeight > this.offsetHeight) ? documentElement.scrollTop + (documentElement.clientHeight / 2) : documentElement.scrollTop);
margin-top: expression((documentElement.clientHeight > this.offsetHeight) ? - this.offsetHeight / 2 : - documentElement.scrollTop);
}
</style>
<![endif]-->
<!--[if IE 5]>
<style type="text/css">
.yui-overlay {
margin-top: expression((document.body.clientHeight > this.offsetHeight) ? - this.offsetHeight / 2 : - document.body.scrollTop);
top: expression((document.body.clientHeight > this.offsetHeight) ? document.body.scrollTop + (document.body.clientHeight / 2) : document.body.scrollTop);
}
</style>
<![endif]-->

What's the deal with CSS expressions?

CSS expressions are used here to help IE 5/6 to keep the overlay *fixed* in the viewport, the same way better browsers do. Not using CSS expressions and relying on the script alone will make the overlay behaves exactly the way it does with the original script (in IE 5 / 6). The only difference with the original script is that if the overlay is taller than the viewport, then IE 5 / 6 will not keep it vertically centered, making sure its content is fully accessible.

Yahoo! says, avoid CSS expressions:

The problem with expressions is that they are evaluated more frequently than most people expect. Not only are they evaluated when the page is rendered and resized, but also when the page is scrolled and even when the user moves the mouse over the page. Adding a counter to the CSS expression allows us to keep track of when and how often a CSS expression is evaluated. Moving the mouse around the page can easily generate more than 10,000 evaluations.

Please use this contact form to send feedback and report errors.