Ah, frames. We hated them when Netscape first offered them up around 1995; we deplored them when they became all the rage for a few short years; we wish they would go away and never darken our displays again. Well, maybe.
The debate on frame usage has been raging for eight years now, and while most experts come down solidly against their use in most instances, I won’t continue the debate here. I will say that in my experience on the Web, 90% of the sites that still use frames don’t use them well; I’m still a bit surprised when I find a site that works better with a frame than not.
Most people who have come late to Web design or are just learning it now get told, "Frames? Forget ’em! You won’t design a page in frames, they’re hard to get right, and it’s a waste of time for you to learn them." Now, there’s plenty of truth in this statement. It’s not a necessity to learn frame design: many professional Web designers have designed hundreds of elegant, functional sites without a single frame and will go right on designing without giving frames a thought. The percentage of framed sites out there is dropping steadily, especially now that more and more designers are moving towards CSS-based design, which essentially renders the entire concept of frames irrelevant. Note that while HTML 4 includes frames as part of the official code, HTML 4.01 Strict does not support frames, relying instead on style sheets.
For a nice compilation of the pros and cons of frames, see Tom Chaplin’s SitePoint article on the subject. It’s a few years old, but still pertinent.
There are times when a knowledge of frame design is necessary, however. Perhaps your business site uses frames and you’re constrained to operate within company parameters. Perhaps you’ve got a client, or an aunt, who is mad for frames and insists you use a frame-based design. Or maybe you’ve come up with a concept for a design that actually works better in a frame (unlikely as that sounds, it does happen).
Frames have their uses, infrequent though they are. So I’ve decided to provide some info on frame design for the novice or intermediate Web designer — some how-tos, along with some observations, caveats and warnings along the way. Frame technique is not that hard, though it’s tricky, and it is worth learning if for no other reason that you’ll know what all the fuss is about.
Frames disrupt the entire fundamental concept for the Web: a large collection of individual pages, linked together with hypertext. …Frames violate too many accepted Web standards to be a worthy information delivery system. — Ross Shannon
Frames: just say no. — Jakob Nielsen
It’s hard to argue with those statements. Frames do disrupt the flow of the Web. Ideally, the idea is to surf unencumbered from site to site and page to page without any problem navigating from one location to another. Point, click, peruse the content, point, click, go somewhere else.
The Web is inherently fluid in nature; frames disrupt that paradigm by adding static structure to Web pages. The fluid paradigm shifts the moment you enter a framed page. Content is displayed inside a "corral" of frames, locked inside a barricade of code. Navigation is disrupted; the usual "click in, click out" methodology no longer works. In some older browsers like Netscape 2, even the BACK button didn’t always get you out of a framed page. Thankfully, that little irritant is no longer a factor, since browsers that don’t handle frames well have all but disappeared from the pool of browsers currently in use, with the notable exception of Lynx, which displays the content of the NOFRAMES page and provides labeled links to the framed content.
Bookmarking doesn’t always work; instead of marking the specific URL of the framed content, you’ve just bookmarked the frameset, which may have a different URL and may not contain the same content upon your return. Copying a frame’s URL for use as a hyperlink in another page may not send a visitor to the proper page, since the framed page’s URL doesn’t display; only the frameset URL displays. Printing a framed page doesn’t always work well. Cookies don’t track frameset pages well. Framed content displays quite poorly on smaller screens such as notebooks and handhelds.
Probably the biggest irritant of frames is the occasional framed page that won’t let you out once you’ve entered; it insists (whether because of poor design or intent) on displaying every other page you go to within its own frameset. This last is a technically defensible choice for some commercial sites that want to keep their own navigational setup or advertising content always in front of visitors, but it’s not a good choice. Trapping visitors within your site’s frames is the best way to aggravate them into leaving your site as quickly as possible — even if that includes closing the browser completely and starting to surf from scratch.
There are also the considerations of additional server load and page maintenance. A framed page often takes up more server space than a non-framed alternative, and those frames also add load time to the page. A bunch of framed pages can be more difficult and time-consuming to modify. And when you create a new frameset, you’ll have a minimum of two (with just one frame — more if you have more frames) hits to the server from a single visit. With more framesets, you generate more hits to the server without generating additional page views. This can cause problems if you can accept a limited amount of traffic to your site; it can also can play havoc with your attempt to keep track of site visitations.
Now, there are some situations where frames represent a reasonable solution. One is the presentation of a long document divided into chapters or blocks. A simple, workable solution is to build a frameset with two columns, where the left side offers navigational links, while the right side displays the actual chapters of content. Clicking on a link in the left-hand frame causes a particular chapter to display in the right-hand frame. This avoids having a horribly long document that may take too much time to display, and displays the content in manageable chunks. Is using a frameset the only solution to such content? Of course not, but it is one feasible method.
A frameset used with an outsourced shopping cart is another useful possibility. If you use separate frames for your banner or logo, navigation, and content, and incorporate the shopping cart in the content page, even if the outsourced shopping cart doesn’t use your logo or navigational material, your site still works well and has the proper look and feel.
The point is, frames are considered bugbears of Web design not because they are useless, but because they’ve been so horribly misused in the past (and the present, and will probably be well into the future). Remember, the basic idea behind a frame is to keep some information permanently visible while viewing other information that is subject to change. When this works well, it allows the viewer to keep, say, a navigational window, a table of contents, an advertisement, or a title bar (or a combination of these elements) in place while they access different areas of the site. For commercial sites, this can be useful for keeping your company’s logo or navigation, or an advertisement in front of the viewer at all times. For non-commercial sites, this is probably most useful for keeping navigational or other information always handy, as opposed to placing a menu on each page (the choice of most designers, by the way).
At its worst, you can get locked into "frame hell," where badly designed or deliberately constrictive framesets lock you into a site with no way out. Back buttons don’t work like they ought to, navigating through the site itself is nightmarish, the frames replicate themselves one inside another, and even typing a brand new URL in the address bar opens the new site inside the old frame. Now that’s annoying.
If you’re going to use a frameset, make sure your content lends itself to framed display. Is there another way to display it? And think about your audience. While even though almost everyone now uses frames-capable browsers, some people don’t like frames and run like scalded cats when a frames site appears on their screen. For these people, frames are like Kryptonite to Superman. You won’t get far arguing with them; your best bet is to give them a
<noframes> alternative, or just design your site without frames from the outset.
Let’s say you want to build a site using frames, for whatever reason. Okay, how do you do it?
Note: I usually advocate trying the code out as we go along in your own HTML code editor. You should do this here, too, but you’re going to have to construct several HTML files to serve as the frame source files, otherwise you won’t see anything. Probably the easiest way to do this is to create a few simple HTML files with no
<body> content and different
<body> bgcolor attributes, just so something will show up.
To use the example code below, try constructing the following pages: your index.html page, which will be your frameset page, and six content pages:
- navigation.html, and
None of these pages needs any text or graphical content unless you really want to put some content in them. Just give them different background colors so they will differentiate themselves on your screen.
Basic Frame Construction
First off, you have to use the proper frames DOCTYPE. For HTML 4 documents, it’s:
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 FRAMESET//EN" "http://www.w3c.org/TR/html4/frameset.dtd">
This is a variant of the HTML 4 Transitional doctype.
For XHTML 1.0 documents, the doctype is:
<DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 FRAMESET//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">Remember, since earlier versions of HTML don't officially support frames, if for some reason you haven't disembarked from the Wayback Machine and are still writing pages to be viewed in HTML 3.2 or earlier, you don't need a specific doctype to write framed pages. Most modern browsers will support the frames and their content anyway, but don't expect 100% compliance by any means.
The starting point for any framed set of Web pages is the
<frame>tag, which usually uses the
srcattribute to point to a particular HTML document.
<frame>tag defines the content of a single framed page. The example above assumes that you want to have a file called mainpage.html displayed within the frame. The only required attribute for the
<frame>tag is the src attribute, which obviously tells the browser what file to display inside the frame. So far so good. You can also control the appearance of scrollbars inside the frame with the scrolling attribute:
<frame src="mainpage.html" scrolling="yes">
The default value for this attribute is auto, which lets the browser decide whether or not scrollbars are to be displayed. The other two values are yes and no, which are pretty self-explanatory. There is no closing
</frame>tag. You should not include any
<head>tag information in the mainpage.html file, since the file represents a larger document. Everything on this page should be included within the
<body>tags. Now you need to construct your frameset page. This page, usually called index.html for obvious reasons, contains the header information for the entire site as well as the
<frameset>tags that construct the skeletal design for the site. Here's a basic example, leaving out such necessities as
<html> <head> <title>Frames Document</title> </head> <frameset rows="50%,50%"> ***add framed pages here using the <frame> tags*** </frameset> </html>
Note that there aren't any
<body>tags in this document. The
<frameset>tags take their place (placing
BODYcode before the
<frameset>tag causes the frameset to be ignored). The
<frameset>tags have one necessary attribute,
S. The example above uses percentages to divide the available display space into two equal, horizontal areas. The
COLSattribute will do the same thing, but divide the available space into two equal, vertical areas:
A lot of Web designers like to divide their pages into three vertical columns, with the two outside frames being narrower than the center column, which will contain the main body of information (this layout emulates the traditional three-column style of site design). If you want to do this, try something like:
where the left- and right-hand columns are 100 pixels wide, and the larger center takes up the rest of the display space. As always, I recommend sticking with percentage widths (or heights) whenever possible, as people use a variety of display sizes. Note that the asterisk in the center of the above code simply means something like "the rest of the display." If you wrote it like so:
you would have a set page width of 700 pixels, which would leave a lot of display real estate unused for our friends with bigger displays. You can also organize your display in relative terms, which specifies the size of the frames relative to other frames. This example shows two columns, where the one on the right is twice the width of that on the left:
*is simply a placeholder. The above code tells the display, "cut the display into two columns, and make the right side twice the size of the left." If the
ROWSattribute is not set, the columns extend to the entire length of the page. If the COLS attribute is not set, the rows extend to the entire width of the page. If neither attribute is set, the frame takes up the exact area of the browser display -- and what's the use of that? (Maybe there is a use for a frameset with no COLS or ROWS attributes, but I can't think of one offhand. If you can, post it in the forums.) You can mix absolute, relative, and percentage measurements, but check them carefully to see how they display. In fact, you should carefully check all your column and row measurements to see how they display, and don't forget to check the layout in different display sizes and different browsers. Here are three examples of mixing measurements, cribbed from the W3C page on HTML frames:
<frameset cols="1*,250,3*> ***yadayada*** </frameset>
This example creates three columns: the center space fixed at 250 pixels, useful for a chunk of content with a known size such as a graphic or a Flash window, and two columns on either side; the left-hand column receives 25% of the remaining space and the right-hand column gets the other 75% of the remaining space.
<frameset rows="30%,70%" cols="33%,34%,33%> ***yadayada*** </frameset>
This example gives you a 2-by-3 grid of subspaces.
<frameset rows="30%,400,*,2*"> ***yadayada*** </frameset>
Here, you have a browser display divided horizontally in four separate areas. The first gets 30% of the display space. The second gets 400 pixels exactly. The other two split up the remaining turf between them, with the fourth area getting twice the amount of the third. If your display is exactly 1000 pixels high, unlikely as that is, the first row will get 300 pixels, the second 400, the third 100, and the fourth 200. Now let's put together a sample frameset page, using the example codes from above and a few more:
<html> <head> <title>Frames Document</title> </head> <frameset cols="100,*,100"> <frame src="leftside.html"> <frame src="mainpage.html"> <frame src="rightside.html"> </frameset> </html>
This gives you the three-column display, with the two side columns restrained to 100 pixels each, and the center column used for the main content. Remember that in each column, if your content exceeds the available width, you get horizontal scrollbars. Nobody likes horizontal scrollbars. Again, play with the column widths so that you can avoid scrollbars as much as possible. Using rows in your framesets gives you vertical scrollbars, which are more acceptable. Remember, frames can be resized by simply moving the cursor over the border, waiting until it changes to a double arrow, and dragging the frame border to where you want it. Text will adapt itself to the change; graphics and other rigidly-sized content will not, and scrollbars will appear. Don't want to let your visitors change your frames around? Use the noresize attribute (it has no values).
Always include a section with the
<noframes>tag for people without frames-compliant browsers (there are still a few out there). People with such browsers will only see the content displayed within the tags; the rest of us won't see it at all, as our frames-compliant browsers won't show it:
<noframes>Your browser won't handle frames. <a href="noframes.html">Go here for a better view!</a></noframes>
Of course, this noframes.html file should include all the content contained in the frameset, in a design that uses â€“ you guessed it -- no frames. Two sites in one... hmmm, here's an argument for designing without frames... Place the
<noframes>code just above the closing
</frameset>tag. Screen readers and audio browsers have a tremendous amount of difficulty with framed pages. This is reason alone to use a
<noframes>page, even if everyone who visits your page is using the latest in browser technology. Some screen readers can handle simple framesets, so this caveat is slowly becoming irrelevant, but there are plenty of folks out there using older screen readers that can't handle frames at all. Maximum accessibility is a necessity, not an option to be considered casually. Trickier Stuff You can "nest" one frameset inside another for more complex layouts. Start off with something simple:
<frameset cols=*,2*> <frame src="navigation.html"> <frame src="mainpage.html"> </frameset>
Here we've got two columns, the right one twice as big as the left. By the names of the files, you can deduce that we're going to use the left side for navigation and the right, larger column for content. Now, let's get tricky with it:
<frameset rows="20%,*"> <frame src="title.html"> <frameset cols="*,2*> <frame src="navigation.html"> <frame src="mainpage.html"> <frameset> </frameset>
This allows us to combine rows and cols together to create the classic "newspaper" site design: a horizontal "masthead" used as our title, and two columns, a narrow left-hand column for navigation and a wider right-side column for main content display. Note that the second
<frameset>, the one with the columns, is completely contained within the second row of the first
<frameset>. Want a two-column display with the larger, right-hand column divided into two rows? Just switch the rows and cols attributes above:
<frameset cols="20%,*"> <frame src="title.html"> <frameset rows="*,2*> <frame src="navigation.html"> <frame src="mainpage.html"> </frameset> </frameset>
If the left-hand column isn't wide enough, just change the value of 20% to 30% -- or whatever suits you. Margins HTML 4 provides two margin control commands, marginheight and marginwidth. The first specifies, in pixels, how much space is to be left between the frame's contents in its top and bottom margins. The second does the same for the left and right margins. There is no specific default. Borderless Frames You can add certain attributes to your
<frameset>tag to eliminate the frame borders, which display by default. Different versions of Netscape and Internet Explorer use different commands, so you may need all of the attributes below for proper site design, though the following code isn't quite standard HTML 4:
<frameset cols="*,*" framespacing="0" frameborder="0" border="0">
Both Netscape and IE use the
borderattribute, but it isn't valid HTML 4. Its value should represent the border's width in pixels.
framespacingis an IE-only attribute that, like Netscape's border, lets you define the border's size in pixels. It is not a valid HTML 4 tag.
frameborderworks with both Netscape and IE. Before HTML 4, the tag used different values for the two browsers: Netscape's values were
no. IE's were
0, which correspond to the yes and no of Netscape. The defaults are
1, which tells the border to draw the border. HTML 4 standardized the tag to use 1 and 0. If you're coding in HTML 4, use the
<... frameborder="0">tag if you want to keep your frames borderless. Colored Borders
bordercoloris a tag that lets you set your border's colors, like so:
<frameset cols="*,*" bordercolor="#F0F0F0">
Like the previous tags, bordercolor isn't official HTML 4, though it works with both Netscape and IE. Margin Width and Margin Height Not too many people bother to specify these attributes, which also go inside the
<frameset>tag. The tags determine the margin's height and width in pixels. Try the tags to see if they work for you.
Interactive Frames It's a good idea for framed pages to be able to interact with each other; that is, direct hyperlinks to the framed pages. You'll need to use the name and target attributes to do this. Start out by naming your framed content pages:
<frameset cols=*,2*> <frame src="navigation.html" name="frame1"> <frame src="mainpage.html" name="frame2"> </frameset>
Once you've named them, you can use the target attribute to direct hyperlinks to them:
<a href="moreinfo.html" target="frame2">More content</a>
If you place this hyperlink into the navigation.html page, when the user clicks on it, the mainpage.html file will be replaced by the moreinfo.html file on the right side. If you give a target that hasn't been defined with the name attribution, the page will open in a new browser window. But what if we want twenty different pages to cycle through the main content display? We could just write twenty different links in navigation.html all targeted to "frame2", or we could use a
<base>tag in the
<head>section of the navigation.html page:
This emulates having the
target="frame2"attribute in every hyperlink. Special Target Commands There are four special target commands, and they all begin with the wonderful, magical, mystical underscore:
_. Here they are:
target="_blank"- causes the URL to load into a new browser window.
target="_top"- targets the URL to the entire browser window and wipes out all of the previous frames; used mostly when you're linking from your own framed content to an outside site.
target="_self"- loads the URL into the same window (the default; if you want this to occur, there's no need to specify it in the code).
target="_parent"- loads the URL into the frameset's parent window; unless you're using nested framesets, this command works just like the
_topcommand. If you're using nested framesets, then this command loads the URL into the frame that is the "next step up" -- the parent window.
Some Other Commands
marginwidthdefine the amount of space, in pixels, that falls between the margins and the content. The
nameattribute is used to target the frame. The
scrollingattribute decides the condition of the scrollbars, when applicable. The values are
auto, the default. Unless you have a specific need to turn scrollbars on or off, this attribute is best left out of your code, and the display will choose whether or not scrollbars are needed. Note that the
noresizecommands can make it tough on users with smaller displays if the two are used in conjunction. If you use them together, test-drive your site in a 640x480 display to see how it looks.
titleattribute can contain a phrase that is used as the title of the iframe. Some browsers depict this information when the mouse hovers over the element, while others display the information in the right-click menu. If you want to include a longer description (usually for non-visual browsers), use the
longdesctag. It will provide a link to the longer description. Advanced Features IFrames IFrames, originally an Internet Explorer-only feature, are now viewable in Internet Explorer 2.x and above, Netscape 7, Mozilla, Opera 3 and 6, and even the WebTV/MSN browser. IFrames are included in the HTML 4.0 specifications as well as the XHTML 1.0 specs. IFrames are "inline" or "independent frames" that reside in the body of a regular HTML page, and can be nested in a page just like a graphic, and do not require the use of a frameset. They're easy to use and quite useful for sidebar and other information of interest that isn't directly relevant to the main body of content. The more you use them, the more uses you will find for them. When you're building your page and you reach the area where you want the iframe to be, simply use the following code (modified to your own uses, naturally):
<iframe src="sidecontent.html" width="200" height="100" align="right">Inside this tag is content contained within an iframe. Your browser may not display this material. You can click <a href="sidecontent.html">here</a> to see it for yourself, and use the BACK button to return to the main page.</iframe>
This gives you a little independently framed HTML page within the body of your main Web page, filled with whatever content you like. Non-compatible browsers will see the content within the two
<iframe>tags. Although the width and height attributes are considered optional, they are usually employed; you can choose pixels (as in the above example) or percentages for your sizing choices. Note that the
alignattribute has been deprecated in favor of style sheets. If you choose to use it, your main choices are:
bottom: the default; the bottom of the object is aligned with the baseline
left: the object is aligned along the left margin, with following objects arrayed to the right
middle: center of the object aligned with the baseline
right: the object is aligned along the right margin, with following objects arrayed to the left
top: the top of the object aligned with the baseline
You can also use the
scrollingcommands in an iframe. CSS users can use the
classand/or id attributes to define the contents of the tag according to the style class or the style ID. CSS users can also use absolute positioning, a floating
divtag, and stylesheet declarations to have an iframe element "float" on top of your main content. Check out Webmonkey's tutorial on how to accomplish this nifty little feat.
Layers Layers are somewhat similar to IFrames in concept, though not in execution or even appearance. They are strictly Netscape-only elements, and have never been included in official HTML specifications. Since they aren't supported by newer versions of Netscape/Mozilla, not part of the official HTML specs, and are fading into irrelevance, I won't go into details about their care and feeding here. Search Engine Placement
Frames cause big problems for search engines. Most search engines, including Google, have problems reading frameset pages. Some of them automatically hunt for "noframes" versions, and if they're not available, the search engine will often settle for indexing just the "master," or frameset, page. Like older browsers, many search engines ignore the instructions on producing the frame. Only information within the noframes tags is read -- information that a frames-capable browser will ignore. Hence the "this site uses frames but your browser doesn't support them" message that you often see in search engine results. You probably don't want the frameset page emphasized on the search engine; worse, you run the risk of having the engine display incomplete or misleading information about your site instead of the carefully crafted positioning message you intended to be shown on the engine listing. So how do you work around this?
<meta>tags included in the frameset page are one solution, but not a very good one, as most major search engines have all but abandoned support for
<meta>tags. Still, they're worth adding for the engines and intranets that do still use them. Note that there's a strong argument that
<meta>tags are no longer worth the time it takes to write them; I won't debate that here, but if you want to read more about the issue, check out Search Engine Watch's article, Death of a Meta Tag. The only major search engine to still use
<meta>tags is Inktomi, and according to their director of product marketing, they've never given the tags a great deal of weight. A better way to skin this particular cat is to include useful information in the
<noframes>instructions. Put the
<noframes>information immediately after the first
<frameset>tag, if you want the text to be placed as high as possible on the page. Note that placing the information above the first frameset tag will disable the frame information in some versions of Netscape. Don't forget to use
<body>tags on the frameset page, within the
<noframes>tags. Providing your frameset page a title is helpful, even though it won't appear when the page is viewed properly. Search engines do index titles; they are one of the most important elements your pages can have. Now that you've gotten this far, you've created a page that search engines can see and index properly. Great... so far. What you haven't done yet is give search engine users a page that is within your frameset; they have a page outside the normal frame constraints. This can be particularly troublesome with engines like AltaVista that are "frames-capable." These engines can link to any page within your framed site, and display it by itself, without the benefit of the frameset. You can easily strand visitors coming straight to a page inside your site if and when it doesn't display inside the frameset you designed. Fortunately, there's a simple answer to this. Just be sure to include a "Home" link at the top or bottom of every page that leads back to the main, frameset page. Make sure you use the
target="_top"attribute, like so:
<a href="index.html" target="_top">Home Page</a>
Final Tips Always include alternative navigational links for your framed HTML pages for those who don't have frames-capable browsers. Always, always, always add the
target="_blank"attribute to links to outside Web pages from within your framed pages. Otherwise, your frame may envelop the outside site within its frameset. That effect (sometimes deliberately inflicted upon poor innocent surfers by evil-minded Web designers, most often employed by commercial sites that want to keep their ad-heavy frameset in front of your face at all times) angers both Web surfers and site owners who don't want your frameset "hijacking" their content. There may even be legal repercussions to trapping other sites in your frames. Keep other folks' frames from engulfing your pages by including this
<meta>tag in the
<head>section of every page:
<meta http-equiv="Window-target" content="top" />
Bookmarking a framed HTML page is easy enough -- just right-click inside the frame, choose "Add to Favorites" or "Add Bookmark," and that framed page is bookmarked. Of course, most modern versions of Netscape and Internet Explorer can bookmark framed pages without the fuss of right-clicking. You can share data between several frames using the
<object>tag. This is a little more sophisticated than the rest of the material I've covered, so I'll leave it to you to find out more about how to use this command. Start with the W3C specifications. A suggestion relating to the