views:

3359

answers:

11

How to implement a web page that scales when the browser window is resized?

I can lay out the elements of the page using either a table or CSS float sections, but i want the display to rescale when the browser window is resized

i have a working solution using AJAX PRO and DIVs with overflow:auto and an onwindowresize hook, but it is cumbersome. Is there a better way?

  • thanks everyone for the answers so far, i intend to try them all (or at least most of them) and then choose the best solution as the answer to this thread

  • using CSS and percentages seems to work best, which is what I did in the original solution; using a visibility:hidden div set to 100% by 100% gives a way to measure the client area of the window [difficult in IE otherwise], and an onwindowresize javascript function lets the AJAXPRO methods kick in when the window is resized to redraw the layout-cell contents at the new resolution

EDIT: my apologies for not being completely clear; i needed a 'liquid layout' where the major elements ('panes') would scale as the browser window was resized. I found that i had to use an AJAX call to re-display the 'pane' contents after resizing, and keep overflow:auto turned on to avoid scrolling

+10  A: 

instead of using in css say "width: 200px", use stuff like "width: 50%"

This makes it use 50% of whatever it's in, so in the case of:

<body>
 <div style="width:50%">
  <!--some stuff-->
 </div>
</body>

The div will now always take up half the window horizontaly.

Fire Lancer
this basically works for the initial layout, but you have to adjust the percentages to account for borders in different browsers, and also use ajax triggered by window resizing to resize the contents of the divs
Steven A. Lowe
+5  A: 

Unless you have some specific requirement here I'm not sure why JS is needed here. Tabular layouts are the easy (and archaic) way to make fluid layouts in html, but div layouts with css allow for fluid layouts as well, see http://www.glish.com/css/2.asp

Loren Segal
javascript is required to refresh the contents when the browser window resizes
Steven A. Lowe
+4  A: 

Yep sound like you want to look at a fluid CSS layout. For resources on this, just google fluid CSS layout, should give you a whole lot of things to check. Also have a look at this previous question for some good pointers.

Ola Karlsson
+2  A: 

Something else to consider is that JavaScript won't update continuously while the window is being resized, so there will be a noticeable delay/choppiness. With a fluid CSS layout, screen elements will update almost instantly for a seamless transition.

Zach
javascript is required to trigger content refresh, the page is not all static
Steven A. Lowe
which is fine, I was referring to using JavaScript with the onresize event.
Zach
+1  A: 

The best way that I have seen to do this is to use the YUI CSS Tools and then use percentages for everything. YUI Grids allow for various fixed width or fluid layouts with column sizes specified as fractions of the available space. There is a YUI Grids Builder to help lay things out. YUI Fonts gives you good font size controls. There are some nice cheat sheets available that show you how to lay things out and useful things like what percentage to specify for a font size of so many pixels.

This gets you scaling of the positioning but scaling of the entire site, including font sizes, when the browser window resizes is a bit trickier. I'm thinking that you are going to have to write some sort of browser plugin for this which means that your solution will be non portable. If you are on an intranet this isn't too bad as you can control the browser on each client but if you are wanting a site that is available on the internet then you may need to rethink your UI.

Peter Kelley
thanks for the links, very interesting tools!
Steven A. Lowe
+3  A: 

It really depends on the web page you are implementing. As a general rule you're going to want 100% CSS. When sizing elements that will contain text remember to gravitate towards text oriented sizes such as em, ex, and not px.

Floats are dangerous if you're new to CSS. I'm not new and they are still somewhat baffling to me. Avoid them where possible. Normally, you just need to modify the display property of the div or element you're working on anyway.

If you do all of this and scour the web where you have additional difficulties you'll not only have pages that resize when the browser does so, but also pages that can be zoomed in and out by resizing text. Basically, do it right and the design is unbreakable. I've seen it done on complex layouts but it is a lot of work, as much effort as programming the web page in certain instances.

I'm not sure who you're doing this site for (fun, profit, both) but I'd recommend you think long and hard about how you balance out the CSS purity with a few hacks here and there to help increase your efficiency. Does your web site have a business need to be 100% accessible? No? Then screw it. Do what you need to do to make your money first, then go hog wild with your passion and do anything extra you have time for.

Justin Bozonier
the site's already done - it was for a client - but looking back at it i don't like what i had to do to get it work
Steven A. Lowe
+1  A: 

After trying a solution by the book I got stuck with incompatibility's in either Firefox or IE. So I did some tinkering and came up with this CSS. As you can see, the margins are half of the desired size and negative.

<head><title>Centered</title>
<style type="text/css">
body { 
        background-position: center center;
        border: thin solid #000000;
        height: 300px;
        width: 600px;
        position: absolute;
        left: 50%;
        top: 50%;
        margin-top: -150px;
        margin-right: auto;
        margin-bottom: auto;
        margin-left: -300px;
    }
</style></head>

Hope that helps

Florian
interesting solution, but i can't set the body to a fixed size
Steven A. Lowe
A: 

Use percentages! Say you have a "main pane" on which all your page's content lies. You want it to be centered in the window, always, and 80% of the width of the window.

Simply do this:
#centerpane{ margin: auto; width: 80%; }

Tada!

stalepretzel
i want the page content to always fill the window, and resize itself when the window resizes
Steven A. Lowe
A: 

Thanks for all of the suggestions! It looks like the ugly stuff i had to do was necessary. The following works (on my machine, anyway) in IE and FireFox. I may make an article out of this for CodeProject.com later ;-)

This javascript goes in the <head> section:

<script type="text/javascript">
var tmout = null;
var mustReload = false;

function Resizing()
{
    if (tmout != null)
    {
        clearTimeout(tmout);
    }
    tmout = setTimeout(RefreshAll,300);
}
function Reload()
{
    document.location.href = document.location.href;
}
//IE fires the window's onresize event when the client area 
//expands or contracts, which causes an infinite loop.
//the way around this is a hidden div set to 100% of 
//height and width, with a guard around the resize event 
//handler to see if the _window_ size really changed
var windowHeight;
var windowWidth;
window.onresize = null;
window.onresize = function()
{
    var backdropDiv = document.getElementById("divBackdrop");
    if (windowHeight != backdropDiv.offsetHeight ||
        windowWidth != backdropDiv.offsetWidth)
    {
        //if screen is shrinking, must reload to get correct sizes
        if (windowHeight != backdropDiv.offsetHeight ||
            windowWidth != backdropDiv.offsetWidth)
        {
            mustReload = true;
        }
        else
        {
            mustReload = mustReload || false;
        }
        windowHeight = backdropDiv.offsetHeight;
        windowWidth = backdropDiv.offsetWidth;
        Resizing();
    }
}
</script>

the <body> starts off like this:

<body onload="RefreshAll();">
    <div id="divBackdrop" 
        style="width:100%; clear:both; height: 100%; margin: 0; 
            padding: 0; position:absolute; top:0px; left:0px; 
            visibility:hidden; z-index:0;">
    </div>

the DIVs float left for the layout. I had to set the height and width to percentages just shy of the full amount (e.g., 99.99%, 59.99%, 39.99%) to keep the floats from wrapping, probably due to the borders on the DIVs.

Finally, after the content section, another javascript block to manage the refreshing:

var isWorking = false;
var currentEntity = <%=currentEntityId %>;

//try to detect a bad back-button usage;
//if the current entity id does not match the querystring 
//parameter entityid=###
if (location.search != null && location.search.indexOf("&entityid=") > 0)
{
    var urlId = location.search.substring(
        location.search.indexOf("&entityid=")+10);
    if (urlId.indexOf("&") > 0)
    {
        urlId = urlId.substring(0,urlId.indexOf("&"));
    }
    if (currentEntity != urlId)
    {
        mustReload = true;
    }
}
//a friendly please wait... hidden div
var pleaseWaitDiv = document.getElementById("divPleaseWait");
//an example content div being refreshed via AJAX PRO
var contentDiv = document.getElementById("contentDiv");

//synchronous refresh of content
function RefreshAll()
{
    if (isWorking) { return; }  //no infinite recursion please!

    isWorking = true;
    pleaseWaitDiv.style.visibility = "visible";

    if (mustReload)
    {
        Reload();
    }
    else
    {
        contentDiv.innerHTML = NAMESPACE.REFRESH_METHOD(
            (currentEntity, contentDiv.offsetWidth, 
             contentDiv.offsetHeight).value;
    }

    pleaseWaitDiv.style.visibility = "hidden";
    isWorking = false;
    if (tmout != null)
    {
        clearTimeout(tmout);
    }
}

var tmout2 = null;
var refreshInterval = 60000;

//periodic synchronous refresh of all content
function Refreshing()
{
    RefreshAll();
    if (tmout2 != null)
    {
        clearTimeout(tmout2);
        tmout2 = setTimeout(Refreshing,refreshInterval);
    }
}

//start periodic refresh of content
tmout2 = setTimeout(Refreshing,refreshInterval);

//clean up
window.onunload = function() 
{
    isWorking = true;
    if (tmout != null)
    {
        clearTimeout(tmout);
        tmout = null;
    }
    if (tmout2 != null)
    {
        clearTimeout(tmout2);
        tmout2 = null;
    }

ugly, but it works - which i guess it what really matters ;-)

Steven A. Lowe
+1  A: 

use ems. jontangerine.com and simplebits.com are both amazing examples. Further reading - The Incredible Em & Elastic Layouts with CSS by Jon Tan

Andy Ford
thanks andy! I did end up using ems for fonts in this project after calculating font sizes in px on a previous project [which worked, but not well!]
Steven A. Lowe
A: 

< body onresize="resizeWindow()" onload="resizeWindow()" > PAGE < /body >

    /**** Page Rescaling Function ****/

    function resizeWindow() 
    {
        var windowHeight = getWindowHeight();
        var windowWidth = getWindowWidth();

        document.getElementById("content").style.height = (windowHeight - 4) + "px";
    }

    function getWindowHeight() 
    {
        var windowHeight=0;
        if (typeof(window.innerHeight)=='number') 
        {
            windowHeight = window.innerHeight;
        }
        else {
            if (document.documentElement && document.documentElement.clientHeight) 
            {
                windowHeight = document.documentElement.clientHeight;
            }
            else 
            {
                if (document.body && document.body.clientHeight) 
                {
                    windowHeight = document.body.clientHeight;
                }
            }
        }
        return windowHeight;
    }

The solution I'm currently working on needs a few changes as to width otherwise height works fine as of so far ^^

-Ozaki

Thqr