layouthandler - standards compilant 100% width and 100% height tableless web page layout template
layouthandler is an example how to create a web page that uses 100% screen
space in web browser and validates against standards. If you have ever built a web
page for a tool with fancy layout then you probably have struggled with <table
width="100%" height="100%">. "width" part usually works but "height" on another
hand usually has some problems. Very often the easiest way to make things work is
to ignore the standards and remove the <!DOCTYPE> from page. The example is
different. It is tested with Internet Explorer, Firefox and Google Chrome but it
should work with other browsers.
Here is how it works.
If not already there, enter the <!DOCTYPE> into the page header as follows:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<title>Test Page</title>
</head>
<body>
...
</body>
</html>
Create page layout. For this example I am using classic layout:
|
Header/Banner/Main menu
|
|
Submenu
|
Content with autoscroll
|
|
Footer
|
Following table illustrates source code. The code is as clean as possible. Each
key element has CSS class specified. No element has width or height specified in
html code. <!-- html comments --> are placeholders where actual content would
be.
<div class="BannerLayer">
<!-- Header/Banner -->
</div>
<div class="MenuLayer">
<!-- Submenu -->
</div>
<div class="ContentLayer">
<!-- Content -->
</div>
<div class="BannerLayer">
<!-- Footer -->
</div>
Create a style sheet. First we set the html and body elements to use all the space
we have. It is important to remove all paddings, margins and borders because these
have different defaults and are rendered differently in different browsers. We also
hide scrollbars with overflow parameter.
html, body
{
margin: 0px;
padding: 0px;
border: none;
width: 100%;
height: 100%;
overflow: hidden;
}
Next we set up a BannerLayer CSS class. Important key is to make sure the height
will never change depending on window size. For this we make sure that wrapping
is turned off. The actual height is determined by the content inside and should
not be specified here.
.BannerLayer
{
white-space: nowrap;
clear: both;
}
The BannerLayer class is used twice on provided html example. For both table rows
the html code is actually exactly the same. There is no limit on how many rows like
these there are.
Now we have the MenuLayer the place for submenu. There are two parameter we need
to set for this class. The "width" in this case would need to be set. Another parameter
is the overflow. There are two choices auto turns on the scrollbars if needed, hidden
disables scrollbars completely. The height would use all available space but we
do not specify this here.
.MenuLayer
{
width: 160px;
overflow: auto;
float: left;
}
And the last element is ContentLayer. This is the part of the page that would adjust
the size to all available space. At this point it is a good idea to enable the scrollbars
when needed.
.ContentLayer
{
overflow: auto;
float: left;
}
Now create the script that initializes the layout. This is most difficult part to
describe. First we need to get the list of <DIV> elements from page. The code
proposed here would be slightly slower compared to getElementById but it would be
easier to use on ASPX pages for example.
var Layer = document.getElementsByTagName('div');
Now we need to find out how much available space we have:
var DynamicHeight = document.body.clientHeight;
var DynamicWidth = document.body.clientWidth;
Next we iterate through all <DIV> objects and calculate available space for
each element with specified class name.
for (var i = 0; i < Layer.length;
i++)
{
...
}
First we subtract all BannerLayer heights from available space. This means something
like "content height" = "screen height" - "banner height" - "footer height".
if (Layer[i].className == 'BannerLayer')
DynamicHeight -= Layer[i].offsetHeight;
Second we subtract all MenuLayer widths from available space. This means something
like "content width" = "screen width" - "submenu width".
if (Layer[i].className == 'MenuLayer')
DynamicWidth -= Layer[i].offsetWidth;
Now we know the size of ContentLayer this is the scrolling part of the page. Now
we just set the sizes in pixels for each element. For BannerLayer we need to set
the width to all available space on screen. We do not change the height.
if (Layer[j].className == 'BannerLayer')
Layer[j].style.width = document.body.clientWidth +
'px';
For MenuLayer we need to set the height to all space left. The "width" is already
set to 160px by style sheet.
if (Layer[j].className == 'MenuLayer')
Layer[j].style.height = DynamicHeight + 'px';
And the last thing we set is the ContentLayer. It gets all the space left.
if (Layer[j].className == 'ContentLayer')
{
Layer[j].style.width = DynamicWidth + 'px';
Layer[j].style.height = DynamicHeight + 'px';
}
Last thing left to do is attaching the code to browser events and link the the script
to the page. It would be good idea to delay execution of the script. This would
minimize the impact while running it together with other scripts.
function DelayedInitLayout()
{
self.setTimeout('InitLayout()', 1);
}
For Internet Explorer the syntax of attaching the event is different than other
browsers.
if (window.addEventListener)
{
window.addEventListener("load", DelayedInitLayout,
false);
window.addEventListener("resize", DelayedInitLayout,
false);
}
else if (window.attachEvent) // ie
{
window.attachEvent('onload', DelayedInitLayout);
window.attachEvent('onresize', DelayedInitLayout);
}
To link the script and the style sheet we need to enter following code to <HEAD>
of the page.
<script type="text/javascript" src="layouthandler.js"></script>
<link type="text/css" rel="Stylesheet"
href="layouthandler.css"
/>
On ASPX page the location of the script can be calculated with VirtualPathUtility
if used on MasterPage, or on base Page class.
<script type="text/javascript" src="<%=VirtualPathUtility.ToAbsolute("~/layouthandler.js")%>"></script>
<link type="text/css" rel="Stylesheet"
href="<%=VirtualPathUtility.ToAbsolute("~/layouthandler.css")%>" />
To control if the submenu is visible or not (again on ASPX page) change the DIV
element to run on server and set the visibility to false. This removes it from the
output and releases the space to ContentLayer.
<div id="MenuLayer" class="MenuLayer"
runat="server">
To set padding for a Layer use another DIV inside it and specify the style or class
for the DIVs inside. Do not set the padding to the Layer DIV directly.
<div class="BannerLayer">
<!-- Footer -->
<div
style="padding: 5px; ">
Footer with 5 pixel padding
</div>
<!-- Footer -->
</div>
That is all.
Preview an example with 2 column layout
Preview an example with 3 column layout