Frame-Based Site

Although frames are very much out of fashion in web site design, this is exactly the sort of application that they were designed for. We have a table of contents that remains constant for the entire site, with a content page that changes to show each topic.

Click here to open the demo in a new window:

Frame-Based Site Demo


  • JavaScript only required for contents and index highlighting.
  • Works with old Web browsers.
  • Browser next and previous buttons supported.


  • Bookmarks don't work without extra code.
  • Not search-engine friendly.


This version of the help comprises the following files:

Filenames Description
01-Intro.html, 02-Site.html, etc. The HTML files for each topic.
nav.html The table of contents file.
ind.html The index file.
header.html The header file.
blank.html A blank file.
index.html The frame definition file.
basic.css, hilite.js CSS and JavaScript definitions.

The design is based on four frames:


The blank frame is there to prevent the content frame from expanding to fill the width of the browser, and is loaded with a blank page.

Here's the frameset definition:

<frameset rows="44,*">
  <frame src="header.html" id="header" scrolling="no" noresize frameborder="0">
  <frameset cols="180,720,*">
    <frame src="nav.html" id="nav" name="nav" noresize frameborder="0">
    <frame src="01-Intro.html" id="content" name="content" noresize frameborder="0">
    <frame src="blank.html" id="blank" noresize frameborder="0">


The table of contents is in a separate file nav.html.

Links in the table of contents need to include "target=content" to make the linked topic appear in the correct content frame. They have a unique id consisting of "p" followed by the file number:

<a id="p01" href="01-Introduction.html" target="content">Introduction</a>

Contents highlighting

To highlight the current topic in the table of contents we include the following call in the onLoad event in the body tag of each topic file, which takes the id of the current file as a parameter:

<body onload="HighlightContents('p01')">

Here's the JavaScript function HighlightContents():

function HighlightContents(id) {
  var p = parent.nav.document.getElementById('nav').className;
  parent.nav.document.getElementById(p).className = '';
  p = id;
  parent.nav.document.getElementById(p).className = 'on';
  parent.nav.document.getElementById('nav').className = p;

The id of the previous highlight is saved as the class of the div with id nav. The JavaScript routine HighlightContents first removes this highlight, then highlights the current topic, passed in the parameter id.


The index is in a separate file ind.html. For information about how the index entries are inserted in the topic files see Index Entries.

Links in the index include a hash tag to the "a name=" anchor:

<a href="06-Statistics.html#a06-5" target="content">Statistics, spot</a>

Index highlighting

To highlight index entries we add a call to a JavaScript routine HighlightIndex() in the body onScroll event:

<body onload="HighlightContents('p06')" onscroll="HighlightIndex()">

Here's the definition of HighlightIndex():

var yellow = '';

function HighlightIndex() {
  if (yellow != '') { 
    document.getElementById(yellow).className = '';
    yellow = '';
  if (document.location.hash != '') { 
    yellow = document.location.hash.substr(1);
    document.getElementById(yellow).className = 'hi';

This first removes any previous highlight, in case we are linking to a different location on the page that's already loaded. It then highlights the index entry corresponding to the hash part of the current URL. The id of the currently highlighted anchor is stored in the global variable yellow.

Note that this index highlighting isn't perfect; it doesn't work if the page doesn't scroll to show the index entry. Any suggestions?

Cross references

Cross references within files and between files work automatically using standard "a href=" links. A cross-reference between files causes the onLoad event in the new file to update the grey highlight in the contents.

blog comments powered by Disqus