One of the most exciting Netscape-only additions to HTML recently
has been the frames specification. Although submitted to the W3C,
frames, for now, remain almost exclusively Netscape-only. (Keep
watching the W3C to see when that may change. Even if it remains
a Netscape standard, more browsers should begin supporting frames.)
Note |
Late in the writing of this book, Microsoft announced that Internet Explorer 3.0 had begun alpha testing, and that it would support the Netscape frames specification. Other browsers are sure to follow. |
Frames aren't overwhelmingly difficult to add to your pages, although they do require a slight shift in thought. Although they seem similar to tables at first, frames are considerably more powerful. So much so, in fact, that frames can even divide your Web page so that it is accessing more than one URL at a time.
Netscape frames are basically another way you can create a unique interface for your Web site. By dividing the page into different parts-each of which can be updated separately-there becomes a number of different interface elements you can offer. Even a simple use of the frame specification lets you add interface graphics or a corporate logo to a site, while the rest of your page scrolls beneath it (see fig. 20.1).
Figure 20.1 : A simple frames interface
Using frames in this way takes you one step closer to the ideal Web interface, because it makes it as intuitive and universal as possible. Frames are ideal for the following:
Probably most unique among the HTML-style tags so far is the <FRAMESET> tag. This container is required for frames-style pages-but it also replaces the <BODY> tag completely on these pages. When you use frames then, you're committed to using them completely-you can't just add frames to part of your page. On a typical page, <FRAMESET> is added like this:
<HTML>
<HEAD>
...HEAD markup...
</HEAD>
<FRAMESET>
...Frames and other HTML markup...
</FRAMESET>
</HTML>
The <FRAMESET> tag can accept two attributes: ROWS and COLS. Both attributes accept either numerical values (size in pixels), percentages, or a combination of both. The value * can also be used to suggest that a particular row or column should take up the rest of the page. The number of rows or columns is suggested by the number of values you give the attribute. These attributes take the following format:
<FRAMESET ROWS="numbers,percentages,*" COLS="numbers,percentages, *">
An example like the following would create two rows: one 50 pixels long and another row that took up the rest of the page:
<FRAMESET ROWS="50,*">
(This would be useful for a page that displays a fixed map or graphic at the top.) The following example would create a Web interface with two columns: one on the leftmost 25 percent of the screen and one on the other 75 percent:
<FRAMESET COLS="25%,75%">
This would be a good way to set up a documentation (or FAQ) site, that offered contents in the first frame and actual text and examples in the second, larger frame.
Each <FRAMESET> statement will work with one attribute or the other. That means you can only create a frameset with either rows or columns. In order to create rows within columns (or vice-versa), you can nest <FRAMESET> statements. For instance, the following will create a page with two columns:
<FRAMESET COLS="25%,75%">
<FRAMESET ROWS="50%,50%">
</FRAMESET>
<FRAMESET ROWS="10%,90%">
</FRAMESET>
</FRAMESET>
The first column will be divided into two rows that take up 50 percent of that column a piece. The second column will be divided into two rows, the first taking ten percent and the second taking the rest of that column. Although this doesn't display anything in and of itself, it creates logical breaks in the page that look like figure 20.2. You'll come back to nesting <FRAMESET> tags as you develop more advanced frame interfaces in this chapter.
Figure 20.2 : The logical breaks created by nested <FRAMESET> tags.
The <FRAME> tag is used within the <FRAMESET> container to determine what will actually appear in a particular frame. Each <FRAME> tag is an empty tag-and it's not unlike the <LI> tags you add to HTML lists. It's simply there, within the <FRAMESET> container, to determine what URL or name is associated with the particular frame it defines. It takes the following format:
<FRAMESET COLS/ROWS="numbers">
<FRAME SRC="URL">
...
</FRAMESET>
The SRC attribute is used to tell the frame what URL should be loaded in that frame. For instance, the following would create two frame rows-one that loaded the URL index.html at the top of the Web page and one that loaded the URL help.html at the bottom of the page (see fig. 20.3):
Figure 20.3 : The <FRAME> tag assigns URLs to each frame window.
<FRAMESET ROWS="50%,50%">
<FRAME SRC="index.html">
<FRAME SRC="help.html">
</FRAMESET>
By using the <FRAME> tag, you create what's known as a frame window. Each window corresponds to a "row" or "column" definition in the <FRAMESET> tag, but nothing is drawn or displayed until an appropriate <FRAME> tag is used to define each individual window.
You'll essentially create the same document that was shown in the previous figure, but you should feel free to play with the numbers a bit to see how different percentages and even different attributes to <FRAMESET> changes how the page displays. Enter Listing 20.1 in your text editor.
Listing 20.1 smpframe.html Simple Frame Document
<HTML>
<HEAD>
<TITLE>Frame Example</TITLE>
</HEAD>
<FRAMESET ROWS="25%,75%">
<FRAME SRC="menu.html">
<FRAME SRC="help.html">
</FRAMESET>
</HTML>
While you're at it, you also need to create some files to put in those frames. If you have some HTML documents hanging around, you can rename menu.html and help.html to any HTML file you'd like to load. For this example, any HTML document names will work (see fig. 20.4).
Figure 20.4 : Loading separate HTML documents into a frame-based page.
If you'd like to experiment further, try changing the <FRAMESET> tag in Listing 20.1 to the following:
<FRAMESET COLS="25%,75%">
Or, change the percentages to see how that affects your layout.
Aside from SRC, the <FRAME> tag can accept the attributes NAME, MARGINWIDTH, MARGINHEIGHT, SCROLLING, and NORESIZE. All of these but NAME are appearance-oriented. Let's deal with them first and come back to NAME in a moment.
MARGINWIDTH and MARGINHEIGHT are used to control the right/left margins and the top/bottom margins of the text and graphics within a frame, respectively. Each takes a numerical value in pixels. For example:
<FRAME SRC="text.html" MARGINWIDTH="5" MARGINHEIGHT="5">
This creates a five pixel border between the contents of text.html and the frame edges.
SCROLLING can accept the values yes, no, and auto and is used to determine whether or not scroll bars will appear in the frame window. The default value is auto, and this is probably the best to use in most cases. Since users have all different screen resolutions and available browser window space, even short documents will sometimes need to be scrolled.
The NORESIZE attribute doesn't require a value assignment, and is used to keep the user from resizing a frame window. (Frame windows can be resized by dragging the frame with the mouse in the viewer window.)
An example of SCROLLING and NORESIZE would be:
<FRAME SRC="text.html" SCROLLING="yes" NORESIZE>
This container tag is used to contain HTML markup intended for browsers that do not support the frames specification. Text and HTML tags inside the <NOFRAMES> container are ignored by frames-capable browsers. All others should generally ignore the other frames tags (which they won't recognize), but display the text in between the <NOFRAMES> tags. The following is an example:
<FRAMESET ROWS="25%,75%">
<FRAME SRC="menu.html">
<FRAME SRC="index.html">
<NOFRAMES>
<P>This page requires a Frames capable browser to view. If you'd prefer,
you can access our <a href="2_index.html">HTML 2.0 compliant pages</a>
to view this information without the frames interface.</P>
</NOFRAMES>
</FRAMESET>
Now we'll create another example, this time using the attributes and additional tags you've seen since the last example. Create a new HTML document and enter Listing 20.2 (use your own HTML document names for <FRAME SRC> if desired).
Listing 20.2 frames2.html Frames and No Frames
<HTML>
<HEAD>
<TTLE>Frames Example #2</TITLE>
</HEAD>
<FRAMESET COLS="25%,75%">
<NOFRAMES>
<P>If you are seeing this message, then your browser isn't capable of viewing Frames. Please access our <A HREF="2_index.html">HTML 2.0 compliant</A> Web pages.</P>
<P>If you like, you can go directly to these pages in our site:
<UL>
<LI><A HREF="products.html">Product pages</A>
<LI><A HREF="support.html">Support pages</A>
<LI><A HREF="help.html">Help page</A>
</UL>
</NOFRAMES>
<FRAME SRC="index.html" MARGINWIDTH="5" MARGINHEIGHT="2" SCROLLING="no">
<FRAME SRC="info.html" MARGINWIDTH="5" MARGINHEIGHT="2" NORESIZE>
</FRAMESET>
</HTML>
Notice that you've used the attribute NORESIZE with the <FRAME> tags for the second column. What's interesting about this is that it forces the first column to also be non-resizable, since the columns share a common frame border (see fig. 20.5). This is the case with any <FRAME> tag.
Figure 20.5 : The <FRAME> and <NOFRAME> tags in action.
Experiment with different values for the <FRAME> attributes and see what makes a big difference in terms of margins, scrolling, and resizing. Also, if you have access to a browser that isn't frames-capable, load the page and see how the <NOFRAMES> markup looks (see fig. 20.6).
Figure 20.6 : The <NOFRAME> HTML message
So far, you've seen that frame windows offer you the ability to load URLs independent of one another, so that you can present two (or more) different HTML pages in the same browser window. But what good is this to you? In many cases, it may be useful to offer multiple documents at once.
For instance, with what you know now, you could use frames to add a button bar image map to the top of every HTML page you create. But that would get tedious-each link would have to point to a new frame document that would then load the button bar and the next document.
But what if you could just leave the button bar in the top frame window and load a new document in the other window? You can do just that, if you know a little about targeting.
First, you need to name your frame windows-at least, you have to name the windows you might want to change. This is accomplished with the NAME attribute to the <FRAME> tag, which takes the following format:
<FRAME SRC="original URL" NAME="window_name">
This shouldn't look too foreign to you, as it's a little like the way that the NAME attribute works for <A NAME> links. Once the frame window has a distinct name, you can access it directly from other frame windows. An example of this is the following:
<FRAME SRC="index.html" NAME="main_viewer">
Although you can pretty much name your frame window anything you want, there is one restriction: you can't start the name with an underscore character (_). If you do, the name will be ignored. But, there's a good reason for that.
The underscore is used to signal a number of "magic" target names. You'll get to those after you learn how to target regular browser windows.
With your frame successfully named, you're ready to target the name with a hypertext link. This is accomplished with the TARGET attribute to a typical <A> anchor tag. It follows this format:
<A HREF="new_URL" TARGET="window_name">link text</A>
The new_URL is the new document that you want to have appear in the frame window. The window_name is the same name that you used to name the frame windows with the NAME attribute to the <FRAME> tag. An example would be the following:
<A HREF="products.html" TARGET="main_viewer">View Products</A>
Now, you finally have a good excuse for using frames. Let's create a document with two frames (in rows). In the top frame, you can put a quick HTML menu of possibilities. In the second frame, put most of the information from your Web site. That's where you'll display the actual pages you've created. The top frame will just be for static controls.
This will take two different listings, and both need to be complete Web documents (see Listings 20.3 and 20.4).
Listing 20.3 control2.html Links for the Top Frame
<HTML>
<HEAD>
<TITLE>Controls</TITLE>
</HEAD>
<BODY>
<DIV ALIGN="CENTER">
<A HREF="index.html" TARGET="big_window">Index Page</A> |
<A HREF="products.html" TARGET="big_window">Products</A> |
<A HREF="service.html" TARGET="big_window">Customer Service</A> |
<A HREF="support.html" TARGET="big_window">Tech Support</A> |
<A HREF="about.html" TARGET="big_window">About Us</A>
</DIV>
</BODY>
</HTML>
That's the control document (save it as control2.html). Now, you'll create the main frame document that will contain both this control document (at the top) and whatever other documents it feels like tossing at the other frame, called big_window.
Listing 20.4 frames.html The Frames Document
<HTML>
<HEAD>
<TITLE>BigCorp World</TITLE>
</HEAD>
<FRAMESET ROWS="10%,90%">
<FRAME SRC="controls.html" SCROLLING="no" NORESIZE>
<FRAME SRC="index.html" NAME="big_window">
</FRAMESET>
</HTML>
Save the second file as frames.html-that's
the one you'll load in your browser window. Notice that you've
told the second frame (the one named big_window)
to load index.html initially.
While an empty frame is possible, you generally don't want to
do that-things work better with a default page in every frame.
You've also chosen certain attributes for the first frame. That's
just personal preference, but I'd rather have my viewer resize
their browser window to see all of the controls, so I won't allow
that window to scroll.
Tip |
Whenever possible, view your pages to make sure they're not abnormally wide or that you're forcing users to scroll constantly to read your pages. |
Finally, you can load frames.html in Netscape (see fig. 20.7). If all goes well, you should be able to click the menu items in the top frame, and change the content in the bottom one!
Figure 20.7 : Up top, it's always contro12.html; but below, it's an ever-changing URL.
Other link-related tags have been updated to accept a TARGET attribute along with the anchor tag. For instance, client-side image maps have their AREA tag updated to accept a target window, so that an area defined to access a certain link loads that page into the target. This is the format:
<AREA SHAPE="shape" COORDS="numbers" HREF="URL" TARGET="window_name">
Likewise, you can add a TARGET attribute to the <FORM> tag. Remember that it's the <FORM> container tag that tells the browser the URL for the script that is required to process the form data. In that same tag, you can also specify a target window for the results that are received from the server. If you want users to be able to use your form repeatedly (to allow them to generate different results), you can leave both the form and the results in separate frames. This attribute takes the following format:
<FORM ACTION="Script_URL" TARGET="window_name">
Note |
Just in case you're wondering why you haven't learned about these attributes before (like in the client-map and target chapters), it's because they don't necessarily exist. That is, a browser has to be specifically programmed to add these attributes to older tags. If a browser is programmed to deal with frames (and it happens to follow this early Netscape specification), then the browser programmers will add support for these tags. In other browsers, they'll (hopefully) just be ignored. |
The last example you went through (Listing 20.4) would have been a great candidate for this one type of target. What if you want the majority of your links to point to a particular frame window? In the early example, you created a file called control2.html that had nothing but hypertext links. Each one of those links required a TARGET attribute that pointed to the big_window. You could have made that easier with a <BASE> tag in the head of your document. Use this format:
<HEAD>
<BASE TARGET="window_name">
</HEAD>
A good example of this for the previous example would be:
<BASE TARGET="big_window">
You don't have to specify the target window in each individual
anchor in an HTML document that has this tag in its head. Now
all links will default to the target defined in the <BASE>
tag.
Note |
If you do use TARGET attributes, they will override the <BASE> tag for that particular link. |
Here's why you can't name frame windows with something that starts with an underscore. The "magic" target names all start with an underscore, which signals to the browser that they should treat this link extra special. The following are some examples:
Basically, these magic targets are designed to let you break out of the current <FRAMESET> structure in some way. Experiment with them to see how you can move around to different windows.
I personally have two problems with the frame interface, and both of them revolve around those browser control buttons that one gets used to after a few years of working on the Web.
First, using a frame-based document as an interface for your Web site makes the Back and Forward buttons on the user's Web browser program nearly useless. As far as the browser is concerned, no completely new pages have been loaded. So, if you click Back, you'll go to the site you visited before you loaded the frames document-no matter how long or far you've been surfing inside the frames.
The answer to this is simple. Take special care that you're providing your user with enough controls to move around in your Web site. If you're using a specific frame window for controls, remember to give your user as many links in that window as possible. Let them go directly to the main pages of your site and never bury a user five or six pages deep without giving them an easy way back.
The second problem is related. If you've ever spent any time accessing a site that uses a frames interface, you'll notice that the URL reported by the browser doesn't ever change. If you used a document called frames.html for instance, then the URL will reflect that for the entire time that a user accesses your site.
This many not seem like a problem, except that it defeats the bookmark option of many browsers and makes it impossible to cut-and-paste URLs into other applications (at least currently). The solution is simple-put the URL for each page somewhere in the document, perhaps somewhere close to the bottom of the page in a smaller font (use <H5> or <H6>). Hopefully, browsers will implement more elegant solutions in the near future. In fact, Netscape's Atlas version (in beta testing at the time of writing) is rumored to be an answer to some of these issues.
Now I'm not a huge fan of using a great number of frames, although I've seen some snazzy implementation of three or four frames on a page. Let's use three different frame windows. One will hold a client-side graphic for your site, one will offer a "table of contents" page, and one will display the actual information for your site.
You'll need a fixed window for the client-side map and two dynamic windows. One will load the parts of the table of contents, and one will load the information pages. Use Listing 20.5 for the client-side map.
Listing 20.5 control3.html HTML for a Client-Side Map
<HTML>
<HEAD>
<TITLE>Control Map</TITLE>
<BASE TARGET="toc_window">
</HEAD>
<BODY>
<DIV ALIGN="CENTER">
<IMG SRC="control.gif" USEMAP="#control">
</DIV>
<MAP NAME="control">
<AREA SHAPE="rect" COORDS="0,0,61,22" HREF="index_toc.html">
<AREA SHAPE="rect" COORDS="62,0,146,22" HREF="prod_toc.html">
<AREA SHAPE="rect" COORDS="146,0,222,22" HREF="serv_toc.html">
<AREA SHAPE="rect" COORDS="222,0,296,22" HREF="supp_toc.html">
<AREA SHAPE="rect" COORDS="296,0,359,23" HREF="about_toc.html">
</MAP>
</BODY>
</HTML>
Notice that this graphic isn't designed to change the main window. It's going to change the documents that show up in your table of contents window. Each of the TOC documents should be a simple HTML list of links that shows the branch that the users have traveled down. For instance, let's create the document serv_toc.html (see Listing 20.6).
Listing 20.6 serv_toc.html A Sample TOC Document
<HTML>
<HEAD>
<TITLE>Service Contents</TITLE>
<BASE TARGET="main_window">
</HEAD>
<BODY>
<UL>
<LI><A HREF="products.html">Main Products Page</A>
<UL>
<LI><A HREF="software.html">Software</A>
<LI><A HREF="hardware.html">Hardware</A>
<LI><A HREF="furniture.html">Furniture</A>
<LI><A HREF="access.html">Accessories</A>
</UL>
</UL>
</BODY>
</HTML>
See what I'm getting at here? The image map will change these controls, and then these links will change the main frame window. It gives a nice, easy interface to the whole site. Now let's create the frames page which we'll call main.html (see Listing 20.7).
Listing 20.7 main.html The Main Frames Interface
<HTML>
<HEAD>
<TITLE>BigCorp on the Web</TITLE>
</HEAD>
<FRAMESET ROWS="15%,85%">
<FRAME SRC="controls.html" SCROLLING="no" NORESIZE>
<FRAMESET COLS="30%,70%">
<FRAME SRC="index_toc.html" NAME="toc_window" MARGINWIDTH="3"
MARGINHEIGHT="3">
<FRAME SRC="index.html" NAME="main_window" MARGINWIDTH="3"
MARGINHEIGHT="3">
</FRAMESET>
</FRAMESET>
</HTML>
This one doesn't take up much space. Here's what you've done. The first <FRAMESET> created two rows-one for image map and one for the rest of the page. In that bottom row, you used another <FRAMESET> to create two columns within that row. The smaller is for the table of contents pages. In the other frame window, you put all of the main HTML documents. Get it? Look at figure 20.8 to see how the whole thing looks in Netscape.
Figure 20.8 : A three way interface is attractive, but it can be tough to manage.
Note |
For this example to work well, you may need to create some other files like index_toc.html, or rename files to work in your main window. |
Netscape frames are an elegant, if currently Netscape-specific, way to load multiple Web pages in a single browser window. Creating frames requires a few new tags, including the <FRAMESET> container and the <FRAME> empty tag. <FRAMESET> containers can be nested to create columns within rows for multiple frame windows on a single page.
Dealing with frames also introduces the concept of "targeting," which means naming frame windows and using the attribute TARGET to point anchor tags toward the named window. With targeting, however, comes the power of frames. With these two concepts, you can create detailed, elegant interfaces for your Web pages that really help you get a lot of information across quickly.