Compatible And Browser-Specific Pages
Each browser, as we've seen, can support a different set of
features and has different capabilities. This obviously makes creating pages
that will display correctly on all your visitor's browsers a difficult
proposition. There are generally three ways to tackle this; you can:
q
Use only the basic features that are supported in the
vast majority of browsers
q
Attempt to automatically adjust the contents of each
page to best suit the particular browser
q
Create separate versions of each page, and send the
most appropriate one back to the user
Using the table we provided earlier in this chapter, you can
figure out roughly what percentage of the total number of visitors' browsers
support the different feature categories, adjusting the values of each browser
to match the demographics of your own site. We'll see how you can collect the
information to do this in Chapters 9 and 10. Then you can just offer pages that
use the appropriate features set for all those browsers.
However, this will generally mean giving up most of the
things that make your pages more exciting, more attractive, and easier for
visitors to use. Instead, you may prefer to either build compatible pages that
work acceptably on most browsers yet take advantage of newer features, or build
separate pages for different types of browser and send the most appropriate one
back to the user.
Building A Compatible Page
Building compatible pages means knowing which features each
browser supports, and how you can adjust the page to suit most of them. We
won't be going into the mechanics of this in depth here, because it's a huge
subject on its own. However, the following sections describe some of the things
you might like to look out for:
Formatting Issues With Standard HTML Tags
HTML as a language was designed to avoid direct formatting
of page content. The original plan was that you would just use text (and
possibly images) to convey technical information. Formatting was limited to the
use of tags like <EM> for emphasizing a point, or <DL>
to create a definition list. As the language developed, browser manufacturers
added lots of new tags that control formatting and presentation of information,
such as <FONT>,
<SMALL>,
<BLINK>,
<MARQUEE>
etc.�
Browsers will ignore any elements or element attributes that
they don't recognize. For example, if you use the <BLINK>
element, you'll only annoy Navigator users. Internet Explorer users will just
see the content as normal static text. And, of course, Navigator users will be
spared the effort of reading the oscillating text in your <MARQUEE>
elements, as it only scrolls from side to side in Internet Explorer.
If we're aiming to achieve maximum compatibility from a
single set of pages, we will probably decide to use the <FONT>
element to provide all the basic formatting we need, plus the standard and
almost universally supported <B> and <I>
elements. If the browser doesn't recognize <FONT>, the worst that will
happen is that all the text will appear in the same default font and size. Not
ideal, but acceptable.
The one possible discrepancy between different <FONT>
implementations is that Navigator 2 will not recognize the FACE
attribute for the <FONT> element � you can control the size and
color but not the font face itself.
Omitting Closing Element Tags
In HTML, many closing element tags are optional, for example
the </TD>
and </TR>
tags in a table. The browser knows where a cell or row ends, because the next
tag will be an opening cell or row tag or the closing </TABLE>
tag. However, you should avoid this shorthand technique, which can cause
formatting problems � in particular Navigator can lose cells at the end of a
table in some circumstances.
<TABLE>
�
<TR>
���
<TD>
�����
cell content here
���
</TD> <!-- optional, but safer if always included -->
�
</TR>�� <!-- optional,
but safer if always included -->
</TABLE>
Unsupported Attributes In Supported Elements
Even though a browser may support a particular element, you
cannot assume that it will recognize all the attributes of that element. For
example, the <TABLE>
element provides a WIDTH attribute, to let you specify the overall width of
the table. This is supported as far back as version 2 by Navigator, but only
from version 3 onwards in Internet Explorer.
Also, try not to depend on the use of the more esoteric
attributes (such as BORDERCOLORDARK in Internet Explorer to change the inner
border of a 3D table). Instead, look to find other ways of achieving the same
end.
Controlling Margin Width And Height
By default, the browser provides a margin of some 10 to 20
pixels around the actual content of a page when it renders it. For a 'busy'
page, this is wasted space. If you're a confirmed Internet Explorer user,
you'll probably avoid this by setting the TOPMARGIN and LEFTMARGIN
attributes in the opening <BODY> tag.
However, this isn't going to do much good in any other
browser. Only Internet Explorer supports these attributes. Instead, in
Navigator 2+, and now in version 4.0 of HTML, we can use the MARGINWIDTH
and MARGINHEIGHT
attributes of the <FRAME> tag to do the same (providing we host the page
within a frameset). Internet Explorer only supports this from version 3
onwards, however. The easy answer, as we often do in our pages, is to use both:
we're covered then for browsers that support either method. We define the MARGINWIDTH
and MARGINHEIGHT
in the frameset, and then add the TOPMARGIN and LEFTMARGIN
attributes to the opening <BODY> tag.�
In the frameset page:
<FRAME SRC=".." MARGINWIDTH=3
MARGINHEIGHT=5>
and in the page that appears within that frame:
<BODY BGCOLOR="#FFFFFF"
TOPMARGIN=3 LEFTMARGIN=5>
Defining Colors
Some older browsers will not recognize color names either,
or at least not the less popular ones. Rather than using:
<BODY
BGCOLOR="lavenderblush">
you'll get a more universal level of support with:
You can find the equivalent color values using the Color Chooser page that we describe
later in this chapter, or with a graphics program such as PaintShop Pro or Windows' own Paint application. Define a custom
color then read off the values in the Custom
Color dialog and convert them into hexadecimal � you can use the
Windows Calculator application
for this.
Inserted Objects And Inclusions
The situation is often complicated with inserted objects, or
inclusions.
You've more chance of a browser recognizing an <APPLET>
element and a Java applet, than an ActiveX control in an <OBJECT>
element. We can tell the user what went wrong with the page by including
alternative content within the <APPLET> or <OBJECT>
element, but outside any <PARAM> elements:
<OBJECT NAME="MyControl"
CLASSID="...">
�<PARAM NAME="param1" VALUE="value1">
�There should be an ActiveX control here. If you see this text
�instead, your browser can't display the object. Sorry...
</OBJECT>
Client-Side Scripting Issues
There are occasions when we really need to do some work in
script code to provide the maximum usability for our pages, but we want to
ensure that they will work on non-script enabled browsers as well. Through some
careful design and planning, this is quite possible to achieve. For example, we
can use script to automatically submit a form in response to an event such as
selecting a value in a list. This can make the page much more intuitive. At the
same time, if the browser doesn't support scripting, our code will automatically
display a normal SUBMIT button so that the user can click this to submit
the form.
Submitting A Form With And Without Script
The <NOSCRIPT> element is
particularly useful for controlling the appearance of a SUBMIT
button on a form. The theory is simple enough:
<FORM
ACTION="http://myserver.com/scripts/doit.asp" NAME="MyForm"
METHOD="POST">
�<INPUT TYPE=CHECKBOX NAME="MyCheck"
ONCLICK="document.MyForm.submit();">
�<NOSCRIPT>
�
<INPUT TYPE=SUBMIT VALUE="Do it now">
�</NOSCRIPT>
</FORM>
Browsers that support scripting should also support the <NOSCRIPT>
element, and ignore its content. This means that they won't display the SUBMIT
button, but will run the code specified in the ONCLICK
attribute of the checkbox <INPUT> tag when the user
clicks on the checkbox. This code can carry out any tasks required, then submit
the form for processing by calling its submit() method.
Browsers that don't support scripting won't know about <NOSCRIPT>,
so they will ignore the tags and display the content. The user gets a SUBMIT
button, which is handy because clicking the checkbox will have no effect (other
than changing its value). Their browser won't recognize the ONCLICK
attribute either, so will ignore the script code it contains. This technique is
used in the HTML Reference Database
on our own Web site (at http://webdev.wrox.co.uk/html4db/):

One point to be aware of is that versions of
Opera prior to version 3.6 have a problem with this technique if the SUBMIT
button is not the last control on the form. They don't send the values of any
controls defined after a <NOSCRIPT> section back to the
server. We discovered this when our HTML Reference Database refused to
work in this browser. We solved it by including ASP code in the page that
detects if the browser is Opera, and prevents the <NOSCRIPT>
and </NOSCRIPT>
tags being included in this case. The problem has been fixed in Opera 3.6.
It's also worth adding an instruction for script-enabled
browsers, which indicates to the user that the form is being submitted when
they click on any of the controls (remember they won't see any visual
indication of how to submit the form). So, in all the controls on the form we
can add code that displays a message in the browser's status bar:
ONCLICK="window.status='Searching...';document.MyForm.submit();">
This displays the message Searching...
in the browser's status bar (to show something is happening) and submits the
form to the address in the ACTION attribute of the <FORM>
element � just as though a SUBMIT button had been clicked.
Scripting In JavaScript
As you can detect the browser version client-side using
script, you can change the appearance of the page to suit the particular
browser easily � as we demonstrated earlier in this chapter. Browsers that
support scripting offer a huge opportunity to create interactive pages, and
most sites these days use client-side scripting to some extent. As we mentioned
earlier, for maximum compatibility you should aim to use JavaScript unless you
are creating pages that are only designed to be used on Microsoft browsers.
However, even though most browsers support JavaScript, there
are still issues to be aware of. Navigator 4 supports a new version of
JavaScript, version 1.2, which adds extra capabilities that Internet Explorer
doesn't recognize. If you aim to stick to the JavaScript 1.1 or 1.0 standard,
you will avoid these difficulties.
In the case of Internet Explorer, the language
interpreter is actually JScript, and you can use SCRIPT="JScript"
in the opening <SCRIPT>
tag. However, for compatibility with Navigator and other browsers such as
Opera, you should stick to SCRIPT="JavaScript", which
IE recognizes and passes to its JScript interpreter. There is a new language
definition called ECMAScript (from the European Computer Manufacturers
Association) which is designed to be JavaScript 1.1 and JScript compatible. No
doubt it will gradually replace the existing mix of languages.
The Compatible Object Model
Even though most browsers these days will accept JavaScript,
the browser itself will have different capabilities. This means that the
objects you can manipulate in script will be different. For example, Internet
Explorer 4.0 introduced the all collection to allow access in
script to any element on the page. Navigator has no such object, and trying to
refer to it will create an error.
However, Navigator has a plugins collection for its navigator
object, which allows you to iterate through all the plug-ins loaded by the
browser. Internet Explorer doesn't support these plug-ins and the plugins
collection will always be empty, so your code will get no usable result.
There are also differences between objects that do appear on
both browsers: for example, the event object occurs in both Navigator
4.x and IE4/5, but has different properties in each browser. It doesn't exist
at all in earlier browsers, or browsers from other manufacturers. And, worse
than this, where two properties do have the same name, they can return
different information. The meanings are different even if the names are the
same.
There are moves at W3C to define a standard Document Object
Model (DOM). However, like most standards in our section of the
industry, the two main browser manufacturers are moving ahead so quickly that they
make even the latest proposals appear out of date. The good news is that both
Netscape and Microsoft have promised to support all the standards that appear
in new versions of their browsers. The problem is that there will still be
features they implement beyond the standards that you will want to use in your
pages.
Duplicated Script Sections
If the code in our page needs to access the object model at
the kind of depth that we've just been describing, one route you can take is to
build a page that contains duplicated sections of code. That way, depending on
the browser that loads the page, you can use the appropriate script code.
Here's a simple example that displays the user's system color depth � read from
the screen
object that has different properties in the two mainline browsers:
...
<SCRIPT
LANGUAGE="JavaScript">
<!--
� var
sorryText = 'Sorry, cannot display the color depth of your system';
� if
(navigator.appName.indexOf('Netscape') != -1)
���
if (navigator.appVersion.substr(0, 1) > 3)
�����
document.write('System color depth is ' + window.screen.pixelDepth)
���
else
�����
document.write(sorryText);
� if
(navigator.appName.indexOf('Microsoft') != -1)
���
if (navigator.appVersion.substr(0, 1) > 3)
�����
document.write('System color depth is ' + window.screen.colorDepth)
���
else
�����
document.write(sorryText);
//-->
</SCRIPT>
<NOSCRIPT>
�
Sorry, your browser doesn't support client-side scripting,
� so
it can't display the color depth of your system.
</NOSCRIPT>
...
Here are the results in Navigator 4 and Internet Explorer 4:

Inserting Duplicated Script Sections With ASP
One easy way to use duplicated script sections is to allow
ASP to insert the correct code automatically. The following example shows how
you can use ASP to decide if the browser can produce the information at all,
and, if it can, which code to use. The extra bonus here is that, because we are
positively identifying the browser, we can use script sections in VBScript for
IE4/5 and JavaScript version 1.2 for Navigator 4.x if required. In this case we
do not require the comment tags around the script to hide it from non
script-enabled browsers, because we are only going send it script-enabled ones:
...
<%
Set objBCap =
Server.CreateObject("MSWC.BrowserType")
If objBCap.Browser = "IE" And
CInt(objBCap.Version) >= 4 Then
%>
<SCRIPT LANGUAGE="VBScript">
�
'client-side script here to suit IE 4 and above
</SCRIPT>
<%
ElseIf objBCap.Browser =
"Netscape" And CInt(objBCap.Version) >= 4 Then
%>
<SCRIPT LANGUAGE="JavaScript1.2">
�
'client-side script here to suit Navigator 4 and above
</SCRIPT>
<%
ElseIf objBCap.javascript = True Then
%>
<SCRIPT
LANGUAGE="JavaScript">
�
'client-side script here to suit generic JavaScript enabled browsers
</SCRIPT>
<%
Else
%>
<P>This page requires a script enabled
browser to work properly ... etc.</P>
<%
End If
%>
...
An alternative, to make the page easier to maintain and
update, is to use SSI to insert the appropriate <SCRIPT>
code or 'sorry' message. This is also useful if you need to use the same code
in several pages:
...
<%
Set objBCap =
Server.CreateObject("MSWC.BrowserType")
If objBCap.Browser = "IE" And
CInt(objBCap.Version) >= 4 Then
%>
<!-- #include
file="ie4_code.inc" -->
<%
ElseIf objBCap.Browser = "Netscape"
And CInt(objBCap.Version) >= 4 Then
%>
<!-- #include
file="nav4_code.inc" -->
<%
ElseIf objBCap.javascript = True Then
%>
<!-- #include
file="generic_code.inc" -->
<%
Else
%>
<!-- #include
file="no_code.inc" -->
<%
End If
%>
...
You might be tempted to try something like this
instead:
'Note: this doesn't work
If objBCap.Browser = "IE" And
CInt(objBCap.Version) >= 4 Then
�
strInclude = "ie4_code.inc"
ElseIf objBCap.Browser =
"Netscape" And CInt(objBCap.Version) >= 4 Then
�
strInclude = "nav4_code.inc"
Else
...
<!-- #include file="<% =
strInclude %>" -->
This won't work, because the 'include' file is
inserted into the page before the ASP code interpreter gets to see it. You'll
just get an error to say it can't find the include file.