Frames--exquisitely tasteful, never overdone

Frames are mostly used to improve navigability within websites, by keeping a table of contents page stationary while the main content page changes.  Do you promise to do frames well, and not to clutter up you own pages with frame borders or leave people stuck in your frames after they leave your site?

Okay, the basic idea is you create a master page with one or more <FRAMESET> tags instead of the usual <BODY> tag.  The following sample code creates a master page with several frames, then the separate pages that load in each frame.  Note that the frameset defining the row frames on the right is nested inside the frameset creating the column frames.  The left column is 200 pixels wide, the right column gets the rest of the page width, and is split into three row frames.  The first row is 100 pixels high, the second is 25 percent of the page height, and the third row gets the remainder of the page height.

<HTML><HEAD><TITLE>Master Frame Page</TITLE></HEAD>
   <FRAME NAME="left" SRC="leftcol.html">
   <FRAMESET ROWS="200,25%,*">
      <FRAME NAME="row1" SRC="ugly2.gif">
      <FRAME NAME="row2" SRC="middlerow.html">
      <FRAME NAME="row3" SRC="">

Here we put a local GIF image of me in the top row, someone else's page in the bottom row, and write our own HTML files for the left column and middle row frames:

<BODY BGCOLOR="#000000"><FONT COLOR="#FF9999"><H1>The Left Column</H1></FONT></BODY></HTML>

<BODY BGCOLOR="#99FFFF"><FONT COLOR="#FF0000"><H1>The Middle Row</H1></FONT></BODY></HTML>

Okay, it's not pretty, but it's a start.  The following example shows how to eliminate clunky frame borders, mamage other frame attribute, and make frames interactive by targeting links in one frame to another frame (that's why we name our frames).

How this site's frames were created

To create the frames for this site, I began by sketching a layout deisgn: a left index column, a header row and a main frame for the actual content.  The user is supposed to click a blue topic button in the left column which will load the appropriate topic page into the main frame and also load a matching header page with sub-topic links to anchor targets at various places within the main page.  So I created a master frame page that divides the parent window into two column frames (red).  The right frame contains a second-level frame page that sub-divides that frame into two row frames (green) with no discernible border.

How can a single link in the master page change the contents of two second-level frames at once (without resorting to Javascript)?   Well, it doesn't.  Each link in the left column loads a different second-level frame page into the right column frame, and the contents of the two row frames are specified in the second-level frame page.

Here's the code for the master page (index.html) which illustrates a number of <FRAMESET> tag attributes:

<HEAD><TITLE>Mad Dog's HTML Reference</TITLE></HEAD>
   <FRAME NAME="left" MARGINWIDTH=2 SCROLLING=NO SRC="left_col_index.html">
   <FRAME NAME="right" SRC="frames1.html">
   <A HREF="">
   <CENTER>Browser doesn't handle frames?
   Click here for the no-frames version of this page.</CENTER></A>

As noted above, the <FRAMESET> tags replaces the usual <BODY> tag, and framesets can be nested to create sub-frames in frames.  Specify frame dimension (ROWS or COLS) as percent (of parent frame's dimension) or in pixels; specifying dimensions in pixels gives you much better control.  You can specify both ROWS and COLS in a single <FRAMESET> tag if you want the same number of frames in each row and column.  Here the <FRAMESET> tag attributes specify frames without borders and zero margins between frame edge and contents in order so that the frames themselves aren't immediately obvious.

In this example we divide the master page into a 91-pixel wide left column and a second column that spans the rest of the page (*).  The "left" frame is specified with a 2-pixel MARGINWIDTH which overrides the zero MARGINWIDTH specified in the <FRAMESET> tag.  This provides a small amount of padding at the sides of photo image and buttons.  Specifying SCROLLING=NO suppresses a scrollbar even if it's needed, so we'll have to make sure this frame's contents all fit into it; the default is SCROLLING=AUTO which turns scrollbars on and off as needed.  The picture of Mad Dog and the blue buttons that go in the left column are 83 pixels wide, and after some trial-and-error, the 91-pixel frame width looked best.

The "left" frame loads the left_col_index.html page.  The "right" frame loads the first of eight second-level frame pages, frames1.html.

Since some people may be using older browsers that don't support frames (i.e., don't recognize the <FRAMESET>, <FRAME> and <NOFRAMES> tags), it's nice to include a brief <BODY> within a <NOFRAMES> tag that lets them access your stuff directly.  The <NOFRAMES> tag tells frames-capable browsers to skip the embedded BODY section.

Each second-level frame page specifies a uniform frameset defining an 88-pixel high "header" row frame and a "main" row frame occupying the rest of the window:    In each of the eight second-level frame pages the SRC attributes of the two <FRAME> tags reference different files; otherwise the second-level frame pages are identical.

Here's frames1.html:

<HEAD><TITLE>Mad Dog's HTML Reference</TITLE></HEAD>
   <FRAME NAME="header" BGCOLOR="#FFFFFF" SRC="top_row_index1.html" SCROLLING=NO>
   <FRAME NAME="main" SRC="html_ref1.html">

The borders are suppressed again.  The height of the "header" frame was sized by trial and error to 88 pixels so it just holds the title image in "top_row_index1.html" (72 pixels high) without needing a scrollbar, so scrolling is suppressed.   (An 84-pixel high top row looked okay with Netscape Navigator, but Internet Explorer cut off the bottom edge.)  Its background color (white) is specified as a FRAME attribute, although the color specification in the BODY tag of top_row_index1.html would override this.

As above, we could have simply nested this <FRAMESET> within the <FRAMESET> of the master page, in place of the <FRAME> tag creating "right", but then we'd need some Javascript to target each button to two target frames at once.

Now we create the subsidiary pages with the actual content to be displayed in the frames.  The left_col_tindex.html page includes the linked button GIF's targeting various second-level frame pages to the right column.  Its HEAD section (not shown) includes a simple style specification and Javascript for the mouse-over changes to the buttons--more about that later.

The targeting of links to specific frames is achieved with a TARGET attribute within each link tag.  I have omitted the link attributes that define the mouseover behavior; we'll discuss these later on.

Here's part of the BODY section of left_col_index.html:

<BODY bgcolor="#FFFF66">
<img height=88 width=83 alt="Of course you can trust me!  I'm a doctor, aren't I?" src="ugly2.gif"

<A TARGET="right" HREF="frames1.html">
<IMG SRC="button_intro.gif" ALT="HTML basic concepts" BORDER=0></A>
<A TARGET="right" HREF="frames2.html">
<IMG SRC="button_tags.gif" ALT="HTML tags and links" BORDER=0></A>

<!--  ...other 6 linked buttons here...  -->

<DIV ALIGN=right>
<P>copyright 2000
<BR><A HREF="">J. Mackenzie</A>
<BR><A HREF="" TARGET="_top">SpatLab</A>
<BR><A HREF="" TARGET="_top">FREC</A> /
    <A HREF="" TARGET="_top">CANR</A>
<BR><A HREF="" TARGET="_top">University of&nbsp;&nbsp;&nbsp;
<BR>Newark, DE

The button links targeted the second-level frame pages to the "right"frame.  The links at the bottom are targeted to "_top" (must be lowercase) which opens this link in the full browser window without your frames.

Now all we need are the page content files for the second-level frame pages to reference.  Here's top_row_index1.html, which loads into the second-level frame "header".   The HEAD section includes a simple style specification that eliminates link underlining

<TITLE>Header 1: Mad Dog's HTML Reference</TITLE>
<style content="text/css">
a {line-height:10pt; font-family:Arial; font-weight:bold; font-size:10pt; text-decoration:none}

<IMG ALIGN=LEFT SRC="mad_dog_header2.gif">
<A HREF="html_ref1.html#top" TARGET="main">Why learn HTML</A>
<BR><A HREF="html_ref1.html#editor" TARGET="main">Use a plain text editor</A>
<BR><A HREF="html_ref1.html#tags" TARGET="main">Basic page elements</A>
<BR><A HREF="html_ref1.html#color" TARGET="main">Body tags and colors</A>

Here the links are targeted to anchors in html_ref1.html (what you're reading now) which occupies the other second-level frame "main".

Frame strategies

When you get into designing frames, you should design for good performance on a range of monitor resolutions, using 640 x 480 as the base size to work with.  Remember that in the worst case, since the browser frames take up space, your clients may only have 600 pixels of width in which to display your content, frame borders,scrollbars and all.  The scarcity of screen space explains why most sites with frames use zero borders and keep frame content small to minimize the need for scrollbars.  (Most scrollbars are 12 pixels wide.)

To prevent clients from resizing your frames and perhaps messing up the layout, you can include a NORESIZE attribute in your <FRAME> tag.

One of the most obnoxious design errors is targeting external sites' pages to one of your frames, so that clients are still stuck inside your frames even after they leave your website. Here's what happens with a mis-targeted link.  Pretty dumb, huh?  Links in your framed pages that reference external sites should always be targeted to "_top" (which clears the frames and loads the page in the top-level window) or "_blank" (which opens the linked page in a new browser window).

Other TARGET options are "_parent" which opens the page in the parent frameset if the nested framesets are in different documents, and "_self" which opens the page in the same frame.  "_self" is the default target.

Keeping other people from jamming your beautiful framed site into one of their own frames is a little trickier, but you can prevent this with a little JavaScript included in the <HEAD> section of you top-level page.  :

  <SCRIPT LANGUAGE="JavaScript">
  <!--  if (top != self)
        top.location.href = location.href;  -->

One tricky use of frames is pre-loading images.  Image pre-loads can improve the apparent performance of your site by loading larger images into the client's cache in advance of his or her need for it.  The trick is to load the set of images, referenced in an HTML document the client  doesn't see, into a zero-height frame below the frame containing the introductory content.  The images download while the client is checking out your introductory material, and are local and immediately available when the client actually requests them.

     <FRAME SRC="intro.html">
     <FRAME SRC="imagepreloads.html">

A few downsides of frames

Frames have a few disadvantages you should be aware of.  First, as noted above, not all browsers are frame-capable, but you can satisfy them with <NOFRAMES> material..

A more significant problem is that visitors to your framed site can't bookmark individual pages at your site, just the master frame, and only in its initial state.  This isn't necessarily bad, but this limitation also makes framed pages difficult for search engines to find and index.

A related problem is that, if a search engine does index pages at your site, it's generally not in the context of their framesets, so the document may appear confusing or incomplete.  So you should try to design each documents so that it makes sense on its own, and include a link to the correct opening frameset.  You can improve your site's coverage by search engines if you include indexing information in a <NOFRAMES> section of your page (which search engines will read), and include descriptive <TITLE> and <META> tags with suitable keywords.

Another problem is that IE and Navigator browsers handle frame margins and borders slightly differently.  To turn frame borders off for both types of browsers:
The first two attributes control borders of Internet Explorer, the second two control borders for Netscape Navigator.  Note that Navigator will still keep a 1-pixel margin around the frame content, while IE won't.