With the abundance of modal layers used throughout the web these days, I thought I would share my method of centering an element on the page. I've come across this question on the ASP.NET forums a couple of times and somebody emailed me the other day asking how I did it on this site, so here goes. For demonstrative purposes, click the "Admin" link on my navigational bar to the left and you will see a sample modal layer that I created. If you are using IE6, too bad! One of the several problems with IE6 is that it does not support the position:fixed style. That is the main reason why my modal dialogs on this site do not work in IE6. The centering technique explained in this post will work in IE6, as long as the element to be centered does not have fixed positioning (it should have position:absolute otherwise). The admin login dialog should popup in the middle of the screen when you click the link. Now resize the window. The layer should stay in the middle. Scroll up and down and it will still stay in the middle (because of fixed positioning). Pretty fancy, eh? I spent some time fiddling around in many different browsers trying to accomplish this task and I believe I have reached the best solution. It's not 100% accurate, but it is as close as I could get. It may be a couple of pixels off... give me a break!
Since Javascript is about as standardized as my shaving schedule, we will have to setup a function just to determine the size of the browser viewport (the window). Outrageous, right?! Without further ado, here is the function...
function getViewportDimensions() { var intH = 0, intW = 0; if(self.innerHeight) { intH = window.innerHeight; intW = window.innerWidth; } else { if(document.documentElement && document.documentElement.clientHeight) { intH = document.documentElement.clientHeight; intW = document.documentElement.clientWidth; } else { if(document.body) { intH = document.body.clientHeight; intW = document.body.clientWidth; } } } return { height: parseInt(intH, 10), width: parseInt(intW, 10) }; }
That function itself is rather useful in many different scenarios in which you need to find the size of the viewport. Note that viewport is not the same as screen resolution. Viewport is the space within the browser window. We need this value to account for the various number of toolbars, the size of the window title bar (could be different depending on operating system settings), full screen mode, etc. The function returns an object with two properties (width and height). Now that we can easily fetch the dimensions of the viewport, centering an element on the screen is not too difficult...
function centerElement(elem) { var viewport = getViewportDimensions(); var left = (viewport.width == 0) ? 50 : parseInt((viewport.width - elem.offsetWidth) / 2, 10); var top = (viewport.height == 0) ? 50 : parseInt((viewport.height - elem.offsetHeight) / 2, 10); elem.style.left = left + 'px'; elem.style.top = top + 'px'; viewport, left, top, elem = null; }
There is only one more bit to cover, and that is how to reposition the element when the user resizes the window. No sweat; that is relatively simple. All you have to do is assign the centerElement function to the window.onresize event handler. Of course you would only want to assign this when the element itself is actually visible. Examine the following sample...
function showModalLayer() { var modalElem = document.getElementById('divModalLayer'); if(modalElem != null) { centerElement(modalElem); modalElem.style.display = 'block'; window.onresize = function() { centerElement(document.getElementById('divModalLayer')); } } } function hideModalLayer() { var modalElem = document.getElementById('divModalLayer'); if(modalElem != null) { modalElem.style.display = 'none'; window.onresize = null; } }
And that's pretty much all there is to it! There is a little bit more work involved with using modal dialogs in combination with the "shadowy" background effect, but I plan to cover that in a future post. Stay tuned.
Hope this helps!

Guess What?
There are a few basic guidelines you should be aware of before leaving a comment…