<?xml version="1.0" encoding="Shift_JIS" ?>

<!-- article-1.00.xml template -->



<?xml-stylesheet type="text/xsl" href="http://devedge.netscape.com/lib/xsl/devedge-1.00/article_ja.xsl"?>



<nde:article 

  url="http://devedge.netscape.com/viewsource/2002/browser-detection/"

  xmlns="http://www.w3.org/1999/xhtml"

  xmlns:nde="http://devedge.netscape.com/2002/de"

  xmlns:ent="http://devedge.netscape.com/2003/ent"

  xml:lang="ja">



  <nde:header>

  <nde:title>

ブラウザ判別とクロス・ブラウザサポートについて

  </nde:title>



  <nde:category>

    記事

  </nde:category>



  <nde:authlist>

    <nde:author>

      <nde:authname>著者：Bob Clary  (翻訳：桃井勝彦)</nde:authname>

      <nde:authaffil>

        Netscape Communications

      </nde:authaffil>

    </nde:author>


  </nde:authlist>



  <nde:pubdate year="2002" month="07" day="17"/>



  <nde:channels>

   <nde:channel id="viewsource"/>

    <nde:channel id="gecko"/>

  </nde:channels>
   <nde:translations>
      <nde:trans url="http://devedge.netscape.com/viewsource/2002/browser-detection/index_en.html" title="English translation of this article">English version</nde:trans>
    </nde:translations>

  <nde:summary>

      適正でないブラウザ判別法を使うとウェブページ維持にいろいろな支障を来たす悪夢の元となります。効率よく維持できて多くのブラウザで綺麗に見れるクロス・ブラウザの条件を満たすサイトを作るにはいつ、どのようにuser agent判別を使用すべきかの根本を見直すことが必要です。

  </nde:summary>

  <nde:abstract>

  </nde:abstract>

</nde:header>

  <nde:head>

    <style type="text/css">

      dl dt { font-weight: bold; }

      ins { color: green; }

      del { color: red; }

    </style>

  </nde:head>

  <nde:content>

    <p>
      適正でないブラウザ判別法を使うとウェブページ維持にいろいろな支障を来たす悪夢の元となります。効率よく維持できて多くのブラウザで綺麗に見れるクロス・ブラウザの条件を満たすサイトを作るにはいつ、どのようにuser agent判別を使用すべきかの根本を見直すことが必要です。この記事ではブラウザ判別法の幾つかの方法を取り上げ吟味し、それらの判別法を状況によって上手に使い分ける方法を打ち出す。

    </p>
    <p>

      When reporting browser statistics, you should aggregate traffic

      for all Gecko based browsers. Please see 

      <a href="http://devedge.netscape.com/viewsource/2002/browser-statistics/">Browser Statistics</a>

      for more information on how to accurately report Gecko based

      users.

    </p>



    <p>

      Visit <a href="http://devedge.netscape.com/central/gecko/">Gecko Central</a> for

      more specific information on supporting Gecko based browsers.

      Visit 

      <a href="http://devedge.netscape.com/central/css/">CSS Central</a> and

      <a href="http://devedge.netscape.com/central/dom/">DOM Central</a> for more 

      information regarding cross browser web development.

    </p>



    <h2 id="intro">Introduction</h2>



    <p>

      In an <em>ideal</em> world, we could author 

      HTML, XML, CSS and JavaScript and only worry about the W3C and ECMA standards. 

      However, we don't quite live in such a world yet.

      Due to bugs, incomplete implementations of the standards and

      legacy browsers, web developers must be able to determine

      which browser a visitor is using and provide the appropriate

      content and scripting code path.  

    </p>



    <p>

      Although browser detection is perhaps the most common scripting 

      task that every web developer faces, it seems that the variety 

      of different strategies in use for detecting browsers is unlimited.

      As a member of the Netscape Evangelism team who has spent over a year

      investigating existing web content, I can say without a doubt that most

      compatibility problems found on the web today are due to a lack of

      understanding of the standards combined with inadequate and

      inappropriate browser detection strategies.

    </p>



    <p>

      This article is intended to provide an overview of browser detection 

      strategies and best practices. For more specific Netscape Gecko 

      <sup style="font-size: x-small;">TM</sup> recommendations, please see the

      <a href="http://devedge.netscape.com/viewsource/2002/gecko-compatibility/">Netscape Gecko Compatibility Handbook</a>.

    </p>



    <p><a href="#top">top</a></p>



    <h2 id="introgecko">Netscape Gecko</h2>



    <p>

      Although many web developers are aware of Netscape 6 and Netscape 7, 

      far fewer are aware that Netscape 6 and 7 are members of an entire 

      family of user agents based upon 

      <a href="http://devedge.netscape.com/central/gecko/">Netscape Gecko</a> that 

      includes the commercial browser 

      <a href="http://www.compuserve.com/">CompuServe 7</a>,

      and open source browsers such as 

      <a href="http://www.mozilla.org/">Mozilla</a>, 

      <a href="http://galeon.sourceforge.net">Galeon</a>, and 

      <a href="">Kmeleon</a>. 

    </p>



    <p>

      Netscape Gecko was designed from the ground up to be compliant

      with the W3C HTML, W3C CSS, W3C XML, W3C DOM, and ECMAScript (JavaScript) 

      standards. It also includes compatibility features which allow

      it to reasonably handle <em>legacy</em> content which was developed

      for earlier generations of browsers such as Netscape Navigator 4

      as well as features which provide compatibility with Internet Explorer 5

      and 6. Unlike other browsers, Netscape Gecko is truly a cross platform

      browser and provides identical support on all operating systems where

      it is supported.

    </p>



    <p>

      The easiest way to support Netscape Gecko is to create content which

      <strong>only</strong> uses the standards. Unfortunately, no other browser

      supports the standards as completely as Netscape Gecko which means that

      web developers and authors are forced to continue to provide support

      for other browsers which do not support the standards as fully. Fortunately,

      other browsers such as Internet Explorer 5 and 6 for Windows, to a lesser

      extent Internet Explorer 5 for Macintosh and Opera 6 also support 

      the standards to a degree. These other browsers also appear to be moving

      towards more complete and rigorous support for the standards and there is

      hope that in the future web developers and authors will be able to

      dispense with browser detection at least with regard to features 

      governed by standards.

    </p>



    <p>

      We are still faced with the question of how to develop standards 

      based content while supporting the differing implementations of 

      modern browsers while at the same time supporting (to a lesser degree) 

      older and less capable browsers. Browser detection is key to

      accomplishing this task.

    </p>



    <p><a href="#top">top</a></p>



    <h2 id="detectionhistory">Browser Detection History primer</h2>



    <p>

      To understand why many common browser detection strategies are

      inappropriate, we must first look back on how these strategies

      came into being.

    </p>



    <p>

      In the earliest days of the web, <a href="http://www.w3.org/MarkUp/">HTML</a> 

      was very simple, not standardized and did not include any support for client

      side scripting.  HTML itself was not standardized until

      HTML 2.0 was introduced in late 1995 and it did not even include tables.

      Browser vendors such as Netscape and Microsoft competed to add compelling 

      <em>features</em> to the HTML they supported

      in their browsers in order to provide the richest most compelling content to 

      their users and to entice web authors to support them. The abilities of 

      browsers to support the latest and greatest content changed on an almost

      daily basis.

    </p>



    <p>

      Web authors were faced from the beginning with a variety of browsers, some of

      which supported the latest and greatest version HTML and some which did not. The 

      solution was either to provide the lowest-common denominator of HTML or to 

      use browser detection techniques on the web server to send customized content

      to each browser depending on what level of support the browser provided. 

      server side browser detection using user agent strings was born.

    </p>



    <blockquote>

      User agent strings are defined in the HTTP protocol and are available to web

      servers (see 

      <a href="http://www.faqs.org/rfcs/rfc1945.html">RFC 1945 - Hypertext

        Transfer Protocol -- HTTP 1.0</a> and

      <a href="http://www.faqs.org/rfcs/rfc2068.html">RFC 2068 - 

        Hypertext Transfer Protocol -- HTTP 1.1</a>). 

    </blockquote>



    <p>

      The most common approach at this time was to distinguish user agents by <em>vendor</em>

      and <em>version</em> using the reported user agent string. 

      Although this approach was considered reasonable at the time, 

      this approach caused problems for browser vendors right from the beginning.

      The original Netscape browsers used a user agent string which began with 

      the code name for the Netscape browser followed by it's version number, e.g. 

      <code>Mozilla/version</code> followed by a comment token which gave additional

      information regarding the operating system being used, etc.

      Since the earliest browser detection techniques were based upon looking for

      a Netscape based browser and only provided customized content to browsers

      which used the <code>Mozilla/version</code> user agent string, other browser 

      vendors standardized on using <code>Mozilla/version</code> to signal that

      they were compatible with a particular Netscape version. Since other browsers

      <em>pretended</em> to be Netscape browsers and encoded their version information

      in a non-standard fashion in the user agent comment area, the task of 

      determining which browser was being used became more complicated than it should 

      have been.

    </p>



    <p>

      Netscape Navigator 2 introduced the ability to run JavaScript in web browsers.

      As browser evolution continued, 

      differences in the implementation of scripting and the objects supported by 

      browsers appeared. Web authors were no longer limited to detecting browsers 

      on their web servers, but could now execute scripts client side (in the browser itself) 

      which could be used to distinguish browsers.

      One of the earliest approaches to client side browser detection involved testing whether

      the browser supported particular <em>objects</em>. An example of this approach involved

      testing for the existence of the <code>document.images</code> object.

    </p>



    <p>

      While <em>object based detection</em> was used in some circumstances, 

      many web authors continued to use the <em>vendor/version</em> approach to

      distinguishing web browsers in their client side scripts.

      Since the user agent string was exposed as a property of the <code>navigator</code> object 

      (e.g. <code>navigator.userAgent</code>), many web authors used the same

      logic in their client side scripts as they had used earlier in their server side

      browser detection.  In addition to <code>navigator.userAgent</code>

      other properties such as <code>appName</code> and <code>appVersion</code>

      were available in the <code>navigator</code> object which could be 

      used in browser <em>vendor/version</em> detection strategies. 

    </p>



    <p>

      The classic example of this <em>vendor/version</em> client side detection

      strategy can be found in the 

      <a href="http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html">Ultimate Browser Sniffer</a>.

      This script and variants of it can be found today on many web sites where it

      is a common source of detection problems.

    </p>



    <p>

      Netscape Navigator 4 and Internet Explorer 4 

      introduced the ability to manipulate HTML content in a browser

      (Dynamic HTML or DHTML) rather than on the web server and 

      began the introduction of support for CSS to style content.

      This generation of browser, in addition to sharing 

      several features which were not available in earlier versions, 

      each implemented their own (incompatible) competing abilities to 

      manipulate content in a web page.

    </p>



    <p>

      Since each vendor's browser implemented different objects to perform DHTML,

      web authors began to use <em>object detection</em> to distinguish 

      <em>vendor/version</em> through the existence of particular JavaScript objects.

      The existence of <code>document.layers</code> was sufficient to

      be sure that the browser was Netscape Navigator 4 while the 

      existence of <code>document.all</code> was sufficient to be

      sure that the browser was Microsoft Internet Explorer 4.

      An implicit assumption by many web authors around this time was the there

      were only two types of browser available... Netscape Navigator and 

      Microsoft Internet Explorer. 

    </p>



    <p>

      These strategies of classifying browsers by <em>vendor/version</em>, 

      assuming that the only browsers being used where either Netscape Navigator 4

      or Internet Explorer 4 <strong>failed</strong> when alternative browsers

      such as those based upon Netscape Gecko were introduced. Many of the 

      problems reported in the press regarding Gecko's inability to display 

      content were directly related to inadequate, inappropriate browser detection

      strategies.

    </p>



    <p>

      A final note on <em>vendor/version</em> strategies. A web developer who 

      fully utilizes the browser detection and distinctions in the 

      <a href="http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html">Ultimate Browser Sniffer</a>

      will produce code which uses code forks for many browsers and versions. Imagine

      attempting to maintain a web site which uses many of the browser variables available

      from the Ultimate Browser Sniffer.

    </p>

    <table>

      <tr>

        <td>browser vendor</td>

        <td>

          is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV

        </td>

      </tr>

      <tr>

        <td>browser version number</td>

        <td>

          is_major (integer indicating major version number: 2, 3, 4 ...)

          is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)

        </td>

      </tr>

      <tr>

        <td>browser vendor AND major version number</td>

        <td>

           is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,

           is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,

           is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up

         </td>

      </tr>

      <tr>

        <td>JavaScript version number</td>

        <td>

          is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)

        </td>

      </tr>

      <tr>

        <td>OS platform and version</td>

        <td>

          is_win, is_win16, is_win32, is_win31, is_win95, 

          is_winnt, is_win98, is_winme, is_win2k,

          is_os2, is_mac, is_mac68k, is_macppc, 

          is_unix, is_sun, is_sun4, is_sun5, is_suni86,

          is_irix, is_irix5, is_irix6,

          is_hpux, is_hpux9, is_hpux10,

          is_aix, is_aix1, is_aix2, is_aix3, is_aix4,

          is_linux, is_sco, is_unixware, is_mpras, is_reliant,

          is_dec, is_sinix, is_freebsd, is_bsd,

          is_vms

        </td>

     </tr>

   </table>



   <p>

     <strong>Detecting browsers using this level of detail is unworkable, unmaintainable

       and violates the basic principles of web authoring!</strong> I strongly advise everyone

     to avoid this trap.

   </p>





    <p><a href="#top">top</a></p>



    <h2 id="problems">Problems caused by inappropriate Browser Detection</h2>



    <h3><a name="probunknown">Excluding Unknown Browsers</a></h3>

    <p>

      If you only provide tests for specific browsers in your detection logic,

      your site will not be usable if a visitor uses a different browser. Consider

      the following example:

    </p>



    <blockquote>

      <pre><![CDATA[

// WRONG APPROACH - do not use!

if (document.all)

{

  // Internet Explorer 4+

  document.write('<link rel="stylesheet" type="text/css" src="style-ie.css">');

}

else if (document.layers)

{

  // Navigator 4

  document.write('<link rel="stylesheet" type="text/css" src="style-nn.css">');

}

]]></pre>

    </blockquote>



    <p>

      Note how the above example only provided stylesheets for Internet Explorer

      and Navigator 4 and even then only if the visitor has JavaScript support

      turned on in their browser. Users of Netscape 6, Netscape 7, CompuServe 7,

      Mozilla, Opera will not be able to view the site properly.

    </p>



    <h3><a name="probmisidentify">Misidentifying Browsers</a></h3>

    <p>

      A common mistake web authors make is to assume that if a browser is not

      Netscape Navigator 4, it must be Internet Explorer and vice versa. For example:

    </p>



    <blockquote>

      <pre><![CDATA[

// WRONG APPROACH - do not use!

if (document.all)

{

  // Internet Explorer 4+

  elm = document.all['menu'];

}

else

{

  // Assume Navigator 4

  elm = document.layers['menu'];

}

]]></pre>

    </blockquote>



    <p>

      Note how the above example assumed that any browser that was not

      Internet Explorer was Navigator 4 and attempted to use <em>Layers</em>.

      This is a common source of problems when using browsers based upon 

      Netscape Gecko as well as Opera. A similar error can be seen in the 

      following example:

    </p>



    <blockquote>

      <pre><![CDATA[

// WRONG APPROACH - do not use!

if (document.layers)

{

  // Navigator 4

  elm = document.layers['menu'];

}

else

{

  // Assume Internet Explorer 4+

  elm = document.all['menu'];

}

]]></pre>

    </blockquote>



    <p>

      Netscape 6 was the first commercial browser released based upon

      Netscape Gecko.  Due to a lack of communication and understanding,

      many sites have created inappropriate detection strategies based upon the

      Netscape 6 user agent string. Netscape 6's user agent string follows the 

      HTTP standards for specifying the version of the user agent. 

      (see <a href="http://www.mozilla.org/build/revised-user-agent-strings.html">Mozilla user-agent strings</a>

      and <a href="http://devedge.netscape.com/viewsource/2002/gecko-useragent-strings/">Netscape Gecko User Agent Strings</a>)

    </p>



    <blockquote>

    <pre>

Mozilla/5.0 (...) Gecko/20001108 Netscape6/6.0</pre>

    </blockquote>



    <p>

      The first vendor/version (<code>Mozilla/5.0</code>)

      indicates that Netscape 6 is a <em>fifth</em> generation browser

      and is not identical to earlier browsers. All Gecko based browsers

      currently report <code>Mozilla/5.0</code> as their primary version

      although no other browser does so at the moment. Hopefully when

      other browser vendors achieve the same level of standards support 

      as Gecko and begin to drop support for legacy browsers, they too

      will begin to report version 5. Assuming that only Netscape Gecko

      will use <code>Mozilla/5.0</code> will cause your browser detection

      logic to fail as soon as another browser vendor releases a 

      browser which reports <code>Mozilla/5.0</code>.

    </p>



    <p>

      The second vendor/version (<code>Gecko/20001108</code>) identifies

      Netscape 6 as a particular release of Netscape Gecko which was

      built on November 8, 2000. If you must detect Gecko using the 

      user agent string, <code>Gecko/version</code> is the most appropriate

      string to search for.

    </p>



    <p>

      The third vendor/version (<code>Netscape6/6.0</code>) identifies

      this particular instance of a Gecko browser as Netscape 6.0.  

      Many sites keyed off of the existence of the string

      <code>Netscape6</code> in the user agent and used tests similar

      to:

    </p>



    <blockquote>

    <pre><![CDATA[

if (navigator.userAgent.indexOf('Netscape6') != -1)     

{

  // Netscape 6 code

}

      ]]></pre>

  </blockquote>



  <p>

    Note how this type of detection misses any other Gecko based

    browser. Unfortunately, the Netscape 6 user agent string was

    not sufficiently generalizable due to it's use of the string

    <code>Netscape6</code> as a description of the <em>vendor</em>.

    Netscape 7 corrects this error and introduces another chance 

    for user agent string based detection to fail.

  </p>



    <blockquote>

    <pre>

Mozilla/5.0 (...) Gecko/200207XX Netscape/7.0</pre>

    </blockquote>



    <p>

      Note how Netscape 7 no longer uses the string <code>Netscape6</code>

      as the Vendor. Any user agent string detection strategy for Gecko

      based upon the existence of the string <code>Netscape6</code> will

      fail to detect Netscape 7.

    </p>



    <h3><a name="probobjectvendorversion">Using JavaScript Objects to determine <em>vendor/version</em></a></h3>



    <p>

      As we already discussed, a common approach in the past was to use

      objects to classify browsers by <em>vendor/version</em>. A common 

      type of detection which originally was written to support only 

      Netscape Navigator 4 and Internet Explorer 4 might look like:

    </p>

    <blockquote>

      <pre><![CDATA[

// WRONG APPROACH - do not use!

if (document.all)

{

  // IE4

  height = document.body.offsetHeight;

}

else if (document.layers)

{

  // NN4

  height = window.innerHeight;

}

else

{

  // other

  height = 0;

}

      ]]></pre>

    </blockquote>



      <p>

        With the introduction of the W3C DOM, the standard method 

        <code>document.getElementById</code> became available in 

        Internet Explorer 5 and later in Netscape 6 (Gecko). Many 

        web authors decided that the easiest way to add support 

        for Netscape Gecko was to add another code fork as follows:

      </p>

    <blockquote>

      <pre><![CDATA[

// WRONG APPROACH - do not use!

if (document.all)

{

  // IE4

  height = document.body.offsetHeight;

}

else if (document.layers)

{

  // NN4

  height = window.innerHeight;

}

else if (document.getElementById)

{

  // They think this is Netscape Gecko

  // but could be wrong!

  height = window.innerHeight;

}

else

{

  // other

  height = 0;

}

      ]]></pre>

    </blockquote>



    <p>

      The approach is incorrect since it assumes that the only other browser

      besides Internet Explorer 5+ that implements <code>document.getElementById</code>

      is Netscape Gecko. This is not true today and will become even less true 

      as more browsers which support the W3C DOM Standards are introduced in the future.

    </p>



    <p><a href="#top">top</a></p>



    <h2 id="recommendations">Recommendations</h2>



    <h3><a name="recstandards">Target the standards and not particular browsers</a></h3>



    <p>

      While the period from 1994-2000 was dominated by incompatible

      non-standard browsers from Netscape and Microsoft, today the

      dominating factor in web development are the standards proposed

      by the World Wide Web Consortium (<a href="http://www.w3.org/">W3C</a>).

      Standards are important for web developers due to the increased flexibility,

      power of presentation, support for users with disabilities to name 

      just a few reasons.

    </p>



    <p>

      Targeting your web content to particular vendors 

      ignores the possibility that other browsers which support 

      the same standards may be introduced in the future. A common problem 

      on the web today is the assumption that the only browsers in the world

      are Netscape Navigator and Microsoft Internet Explorer. This ignores

      the existence of <a href="http://www.opera.com/">Opera</a> as well as

      the newer handheld devices which are being used to access the web today

      and in the future.

    </p>



    <p>

      Today, both Netscape (Netscape 6 and above) and Microsoft (Internet Explorer 5.5

      and above) provide browsers which due to their support for the standards

      are more similar than they are different. This similarity will only increase

      as each browser implements more and more of the standards.

    </p>



    <p>

      <a href="http://www.mozilla.org/docs/web-developer/quirks/">Netscape 6 and above</a>, 

      <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp">Internet Explorer 6</a>

      on Windows, and Internet Explorer 5 for Macintosh 

      all support <em>DOCTYPE switching</em>. This is a technique where these

      browsers can be switched from <em>Quirks</em> mode (which emulates buggy implementations

      in earlier generation browsers) to <em>Standards</em> mode (which more strictly 

      adhers to the Standards). For new content, we recommend that you use a DOCTYPE

      which will invoke Standards mode in Netscape Gecko and Internet Explorer 6.

      This will ensure that your designs work similarly in these browsers as well

      as in any other browsers which support the Standards.

    </p>



    <h3><a name="recunknown">Provide support for unknown browsers</a></h3>



    <p>

      Always provide content and code paths for unknown browsers. The recommended

      approach is to assume that any unknown browser supports the basic standards

      of HTML and CSS and to a certain extent JavaScript and the W3C DOM.

      This will guarantee that your content will be supported today and in the 

      future by <strong>any</strong> browser which supports the standards.

    </p>



    <h3><a name="recproprietary">Limit the use of <em>vendor/version</em> specific features</a></h3>



    <p>

      Authoring content which is standards compliant is the easiest way to

      support the widest range of user agents and to decrease your maintenance

      costs. While it is not always possible to avoid <em>vendor/version</em>

      specific differences between browsers, the use of such features and 

      the distinction between browsers based on <em>vendor/version</em> should

      be strictly limited to those areas where it is still required.

    </p>



    <h3><a name="reclimitua">Limit the use of User Agent String based Detection</a></h3>



    <p>

      Server side browser detection requires the use of user agent strings.

      We recommend that the use of user agent string based detection be

      limited to server side situations and except in those circumstances 

      where it is absolutely required such as when details of the Netscape

      Gecko branch are required. 

    </p>



    <p>

      There are <strong>legitimate</strong> reasons to use the user

      agent string (or the 

      <code><a href="http://devedge.netscape.com/library/xref/2002/client-data/property-data-navigator.html">navigator</a></code>

      object) to determine 

      exactly what vendor, version or operating system is being used. Many

      financial sites (banks, online stock trading firms, etc) have very 

      strict policies with respect to what browsers they support. This is

      due to the history of security exploits that have been discovered in

      older browsers. If you have the need to only allow specific versions

      of browsers to use your secure site, then the user agent string and

      the related information from the <code>navigator</code> object can

      be very useful.

    </p>



    <p>

      You can also use detailed information regarding a browser's version

      to work around bugs in specific releases of a browser. However, this

      can quickly become a maintenance nightmare if you are not careful. I 

      recommend that you only provide work arounds for bugs on a temporary basis

      and as soon as bugs are corrected in newer releases of the browser that

      you require your visitors to upgrade their browser.

    </p>



    <h3><a name="recdownlevel">Provide <em>downlevel</em> pages for older browsers</a></h3>



    <p>

      No commercial web site today makes complete support for Netscape Navigator versions

      1, 2 or 3 or Microsoft Internet Explorer 3 a requirement. The reasons are 

      that the capabilities of such browsers are far too limited compared to

      more modern browsers, the added development and quality assurance

      requirements add too much to the development cost of web sites and 

      the market share of such browsers does not justify the expense of supporting

      them.

    </p>



    <p>

      One of the most important decisions you can make in order to improve

      the quality of your site and decrease development, maintenance and quality

      assurance costs is to provide only limited support for older browsers

      such as Netscape Navigator 4 and Internet Explorer 4. One of the more 

      common approaches in major web sites is to provide a <em>downlevel</em>

      version of a web page to older browsers while providing a richer page

      which uses advanced CSS and JavaScript to more modern browsers. This can 

      be accomplished through server side browser detection either as part of

      a scripted solution or as part of the web server's native ability to 

      serve different content to different user agents. This approach does

      not necessarily require you to author separate pages for downlevel 

      and modern browsers. A common solution is to author content in a neutral

      format such as XML and use XSLT transformations to generate the necessary

      HTML for each class of browser.

    </p>



    <p>

      Whether a particular browser should be provided with <em>downlevel</em>

      content depends to an extent on what features of CSS or JavaScript are

      being used in the <em>advanced</em> content. Netscape Navigator 4 and

      Internet Explorer 4 should both be considered <em>downlevel</em> browsers

      for most pages due to their limited support for CSS and the more recent

      DOM based standards. If your pages make use of advanced JavaScript 

      which manipulates or creates new content using the W3C DOM Core, then

      Opera 5 and 6 should be considered downlevel as well due to their limited

      support for the W3C DOM. 

    </p>



    <p>

      The future belongs to developers and browsers which support standards. If you

      fail to take advantage of the coming change in browsers, your competitors

      will <em>eat your lunch</em>. Once that happens, the only place your web site

      will be found is on the <a href="http://web.archive.org/">web archive</a>.

    </p>



    <h3><a name="recnonscript">Use non-script based detection methods where possible</a></h3>



    <p>

      Older browsers have many limitations which result in their ignoring

      more advanced features. By judiciously using these limitations in 

      older browsers you can include modern content while at the same time

      supporting older browsers.

    </p>



    <p>

      HTML provides several methods of detecting support for various 

      features such as support for scripting and FRAMES. Use these 

      natural abilities of HTML to extend the range of browsers your

      content supports.

    </p>



    <h4>Using NOFRAMES to support NON-FRAMES capable browsers</h4>



      <pre><![CDATA[

<HTML>

  <HEAD>

    <TITLE>FRAMES</TITLE>

  </HEAD>

  <FRAMESET ROWS="30,*">

    <FRAME SRC="foo.html">

    <FRAME SRC="bar.html">

    <NOFRAMES>

      <BODY>

        <P>

          This page requires frames. See <a href="noframes.html">sitemap</a>.

        </P>

      </BODY>

    </NOFRAMES>

  </FRAMESET>

</HTML>

]]></pre>



      <h4>Using NOSCRIPT to support non-scriptable browsers</h4>



      <p>

        Some browsers may not support scripting while some users may have

        scripting support turned off in their browser. Use the NOSCRIPT

        tag to provide these users with alternative unscripted versions of

        your pages or to at least notify them of the need to use scripting

        in order to view your content properly.

      </p>



      <p>

        Since browsers such as Netscape Navigator 4 and Internet 

        Explorer 4 do not support some of the most recent additions

        to the JavaScript (ECMAScript) standard, it is often necessary

        to limit the use of advanced JavaScript features such as <em>exception</em>

        processing. One approach is to require that users of browsers

        which do not support the level of JavaScript used in your content

        to <strong>turn off</strong> JavaScript in order to be able to use 

        your content. You can do this by providing an error message for

        users of older browsers as well as alternative content contained

        in NOSCRIPT tags.

      </p>



      <pre><![CDATA[

<HTML>

  <HEAD>

    <TITLE>NOSCRIPT</TITLE>

  </HEAD>

  <BODY>

    <SCRIPT LANGUAGE="JavaScript">

      window.onerror = function () 

      {

        // redirect user to a page describing the limitations

        // of their browser and requesting that they turn off

        // JavaScript in order to view your site.

      }



      // Netscape Navigator 4 will throw an error

      // on any JavaScript which attempts to use

      // try ... catch exception processing.

      try

      {

        // Code to implement fancy Menu

      }

      catch (errors)

      {

        // handle Exceptions

      }

    </SCRIPT>

    <NOSCRIPT>

      <!-- 

      if javascript is not enabled, then the browser

      will display the contents of the NOSCRIPT tag

      which in this case is a simple MENU implemented

      as an unordered list.

      -->

      <UL>

        <LI><A HREF="choice1.html">Choice1</A></LI>

        <LI><A HREF="choice2.html">Choice2</A></LI>

      </UL>

    </NOSCRIPT>

  </BODY>

</HTML>

]]></pre>

      <h4>Using SCRIPT LANGUAGE to choose the browser where it will be executed</h4>



      <p>

        The choice of scripting language is determined by the 

        LANGUAGE attribute of the script tag.

        Internet Explorer 4 and above can support a variety of script 

        languages. The most common are <em>VBSCRIPT</em> and <em>JavaScript</em>.

        Internet Explorer also uses <em>JSCRIPT</em> as a synonym for 

        JavaScript. Since other browsers do not support the language

        attribute <em>VBSCRIPT</em> or <em>JSCRIPT</em> you can use

        these languages when you wish certain scripts to only be 

        executed by Internet Explorer 4 and above.

      </p>



      <pre><![CDATA[

<HTML>

  <HEAD>

    <TITLE>SCRIPT Languages</TITLE>

  </HEAD>

  <BODY>

    <SCRIPT LANGUAGE="JavaScript">

      // JavaScript Code to implement fancy Menu

      // Visible to all JavaScript capable browsers

    </SCRIPT>

    <SCRIPT LANGUAGE="JScript">

      // JavaScript Code that uses proprietary 

      // Internet Explorer features not available in

      // other browsers.

    </SCRIPT>

    <SCRIPT LANGUAGE="VBScript">

      // VBScript Code that uses proprietary 

      // Internet Explorer features not available in

      // other browsers.

    </SCRIPT>

  </BODY>

</HTML>

]]></pre>



      <h4>Using Netscape Navigator 4's CSS limitations</h4>



      <p>

        It is possible to use Netscape Navigator 4's limitations for CSS support

        to automatically exclude certain CSS rules from ever being seen by 

        Navigator 4.

      </p>



      <p>

        For example, Navigator 4 does not understand the @import

        directive in CSS and will not load any external CSS Style sheets specified

        via @import. This technique can be used to provide basic common CSS rules

        for all browsers (including Navigator 4) while providing more advanced 

        rules in a external CSS file for more modern CSS compliant browsers.

      </p>



      <blockquote>

        <pre><![CDATA[

<STYLE type="text/css">

/* Navigator 4 CSS rules */

</STYLE>



<STYLE type="text/css">

/* Advanced CSS rules ignored by Navigator 4 */

@import "advanced.css";

</STYLE>

]]></pre>

      </blockquote>



      <p>

        A similar technique is available for hiding CSS rules from

        Navigator 4 using the fact that Navigator 4 will ignore CSS

        rules after an occurence of <code>/*/*/</code> in a stylesheet.

      </p>



      <blockquote>

        <pre><![CDATA[

<STYLE type="text/css">

/* Navigator 4 CSS rules */



/*/*/

/* Advanced CSS rules ignored by Navigator 4 */

</STYLE>

]]></pre>

      </blockquote>



      <p>

        DevEdge uses this technique to hide advanced CSS from

        Navigator 4.

      </p>





      <h3><a name="recfeatureobject">Use feature oriented object detection</a></h3>



      <p>

        Object detection is a powerful method of providing cross browser 

        support in your web content. Although you can use object detection as 

        just another means of distinguishing between <em>vendor/version</em> 

        the technique shows it's true power when used to detect features 

        rather than browsers. 

      </p>



      <p>

        Feature oriented object detection is the testing

        for the existence of specific objects before attempting 

        to use them in a script. The classic example is:

      </p>



      <blockquote>

        <pre><![CDATA[

if (document.images)

{

  // code which processes the images 

}

]]></pre>

      </blockquote>



      <p>

        The advantage to feature detection is that it will work

        regardless of the <em>vendor/version</em>. We can rewrite

        the earlier example which illustrated problems with 

        using objects to determine <em>vendor/version</em> to 

        use feature detection instead.

      </p>



    <blockquote>

      <pre><![CDATA[

if (document.body && typeof(document.body.offsetHeight) == 'number')

{

  height = document.body.offsetHeight;

}

else if (typeof(window.innerHeight) == 'number')

{

  height = window.innerHeight;

}

else

{

  height = 0;

}

]]></pre>

    </blockquote>



      <p>

        Note how the previous example does not make assumptions about

        which browser is being used. Instead, it only tests for the

        objects which it wishes to use. Since the numeric values

        could potentially be zero, the script tests the type of the 

        objects to make sure they are numbers instead.

      </p>

        

    <h2 id="geckonn4">Gecko and Navigator 4</h2>



    <p>

      Gecko is the replacement for Navigator 4 and as such retains many features

      from Navigator 4. The basic differences between Navigator 4 and Gecko

      can be easily summarized by:

    </p>



    <h4>Differences between Gecko and Navigator 4</h4>

    <dl>

      <dt>Gecko is standards conformant</dt>

      <dd>

        <p>

          Gecko supports many more standards than Navigator 4 and 

          implements them correctly unlike Navigator 4.

        </p>

      </dd>



      <dt>Gecko does not support Layers</dt>

      <dd>

        <p>

          Navigator 4 introduced the Layer API which it used to

          manipulate content and which formed the basis of DHTML

          in Navigator 4.

        </p>



        <p>

          Layers however were not accepted by the W3C either in HTML

          or in the DOM. Since Gecko's mission was to be the most 

          standards conformant browser possible, Layers were not

          supported. This lack of backwards compatibility has been

          the cause of many problems for web authors, but can easily

          be overcome through proper authoring and browser detection

          strategies. As the use of Navigator 4 decreases and more authors

          use the standards in their content, Layers and the problems

          they cause will disappear.

        </p>



      </dd>

    </dl>



    <p><a href="#top">top</a></p>



    <h2 id="geckoie">Gecko and Internet Explorer</h2>



    <p>

      Gecko implements a number of Internet Explorer only proprietary

      features especially with respect to their 

      <a href="http://msdn.microsoft.com/...">DHTML object model</a>. 

      Gecko's support for a number of IE's features has steadily increased

      since the introduction of Netscape 6 in November 2000. The best

      approach to take advantage of these IE compatibility features 

      in Gecko is to use object based feature detection. This will automatically

      use any such features in Gecko if they are available in the version of

      Gecko being used.

      See the <a href="http://devedge.netscape.com/library/xref/2002/client-data/">Client Object Cross Reference</a>

      for more details on which Internet Explorer's objects and

      properties are supported by which version of Gecko.

    </p>



    <p>

      A number of Internet Explorer features <strong>are not supported by Gecko</strong>.

      These include the <code>window.event</code> object, behaviors,

      filters, transitions, and ActiveX.

    </p>



    <p><a href="#top">top</a></p>



    <h2 id="geckonavigator">How (and when) to use the <code>navigator</code> object when detecting Gecko</h2>



    <p>

      Unless you specifically need to detect if Gecko is being used, do not use

      these methods. These methods should only be used in circumstances which

      can not be handled by using <em>object feature detection</em> such as when

      specific versions of Gecko must be excluded for security reasons. 

    </p>



    <p>

      <strong>Note:</strong> For client side detection, we recommend using the 

      <code>navigator</code> object and it's properties. All of the information 

      reported in the <code>navigator</code> is also available in the user agent

      string which can be used in server side situations.

    </p>



    <h3><a name="geckonavigatorproduct">Product</a></h3>

    <p>

      <code>navigator.product</code> is specific to Gecko browsers and will 

      always return <code>'Gecko'</code>. The is a quick and simple means of

      determining that a browser is based upon Netscape Gecko.

    </p>



    <h3><a name="geckonavigatorbranch">CVS Branch Tag</a></h3>

    <p>

      Beginning in Gecko 0.9.0 (Netscape 6.1 in Gecko 0.9.2), 

      <code>navigator.userAgent</code> 

      contains the CVS branch tag of the source which was used to 

      create the version of Gecko being used in the browser. 

      The branch tag is contained in the comment 

      area of the user agent string and follows the string 

      <code>'rv:'</code>. In the following example, the branch tag is 

      <code>a.b.c</code>.

    </p>



    <pre>

      Mozilla/5.0 (...; rv:a.b.c) Gecko/CCYYMMDD Vendor/version

    </pre>



    <p>

      Gecko browsers which are built from the same branch share the same basic version of

      Netscape Gecko and can be treated similarly when dealing with HTML, CSS, JavaScript,

      etc. For example, Netscape 6.2, 6.2.1, 6.2.2, 6.2.3 and CompuServe 7 are all built

      from the <code>0.9.4</code> branch and therefore share similar behavior 

      in many ways.

    </p>



    <table border="1">

      <caption>Gecko Branch Tags</caption>

      <tr><th>Browser</th><th>Branch Tag</th></tr>

      <tr><td>Netscape 6.0</td><td>contained M18 rather than the rv value</td></tr>

      <tr><td>Netscape 6.1</td><td>0.9.2</td></tr>

      <tr><td>Netscape 6.2</td><td>0.9.4</td></tr>

      <tr><td>Netscape 6.2.1</td><td>0.9.4</td></tr>

      <tr><td>Netscape 6.2.2</td><td>0.9.4.1</td></tr>

      <tr><td>Netscape 6.2.3</td><td>0.9.4.1</td></tr>

      <tr><td>CompuServe 7</td><td>0.9.4.2</td></tr>

      <tr><td>Netscape 7</td><td>1.0.1</td></tr>

    </table>



    <p>

      As you can see, all versions of Netscape 6.2 and CompuServe 7

      were created from the <code>0.9.4</code> branch. The distinction

      between <code>0.9.4</code>, <code>0.9.4.1</code>, <code>0.9.4.2</code>

      is minor.

    </p>



    <p>

      <strong>Note:</strong> The branch tag is a string and can contain

      more than single digits in any particular level. For example,

      it is conceivable that someday there will exist branch tags

      similar to <code>2.2.0</code> and <code>2.12.36</code>. Since

      these values are strings, it is not possible to use relative string

      comparisons to determine which branch tag came later. In our 

      example, branch <code>2.2.0</code> was created before <code>2.12.36</code>

      however comparing these values as strings shows <code>'2.2.0' > '2.12.36'</code>.

      The JavaScript function 

      <a href="/xbProjects-docs-srce/geckoGetRv/"><code>geckoGetRv()</code></a>

      provides one solution to this problem by converting the branch tag 

      in the user agent string into a floating point number where each 

      level of the branch tag is considered as a number from 0-99.

    </p>



    <table border="1">

      <caption>geckoGetRv() Examples</caption>

      <tr><th>Branch Tag</th><th>geckoGetRv()</th></tr>

      <tr><td>0.9.2</td><td>0.0902</td></tr>

      <tr><td>0.9.4</td><td>0.0904</td></tr>

      <tr><td>0.9.4.1</td><td>0.090401</td></tr>

      <tr><td>0.9.4.2</td><td>0.090402</td></tr>

      <tr><td>1.0.1</td><td>1.0001</td></tr>

      <tr><td>2.2.0</td><td>2.02</td></tr>

      <tr><td>2.12.36</td><td>2.1236</td></tr>

    </table>



    <p>

      <code>geckoGetRv()</code> returns values which can be compared using

      greater than, less than, etc. <code>geckoGetRv()</code> is not an official

      part of Netscape Gecko however is provided as an example of approaches 

      you can take to compare the different branch tags today and in the future.

    </p>



    <h3><a name="geckonavigatorbuild">Build Date</a></h3>

    <p>

      <code>navigator.productSub</code> is specific to Gecko browsers and will

      return a string containing the date the browser was built in the format

      CCYYMMDD (e.g. '20020801' for August 1, 2002). 

      If you are concerned about a specific security

      issue in Gecko and know for example that all Gecko browsers

      contain a fix for the issue after a certain date, you can check that the 

      <code>navigator.productSub</code> value is after that date.

    </p>



    <p>

      You can also distinquish between <em>point releases</em> using a combination

      of the branch tag and the build date. For example, Netscape 6.2.2 and Netscape 6.2.3

      both have branch tags <code>0.9.4.1</code>, but Netscape 6.2.2 has 

      <code>navigator.productSub == '20020314'</code> while Netscape 6.2.3 has

      <code>navigator.productSub == '20020508'</code>.

    </p>



    <h3><a name="geckonavigatorvendor">vendor/version</a></h3>

    <p>

      All Gecko browsers report the vendor and vendor's version both in

      the <code>navigator</code> object and the user agent string.

      The vendor and version information is not as useful as the 

      branch tag and the build date however and we do not recommend their

      use. However, if you wish, you can distinguish the different 

      types of Gecko browser using these values. As we saw earlier,

      the vendor/version appear in the user agent string following

      the Gecko version.

    </p>



    <pre>

      Mozilla/5.0 (...; rv:a.b.c) Gecko/CCYYMMDD Vendor/version

    </pre>



    <p>

      The vendor is available in the <code>navigator</code>

      object as <code>navigator.vendor</code> while the vendor's 

      version is available as <code>navigator.vendorSub</code>.

    </p>



    <table border="1">

      <caption>Gecko vendor/version values</caption>

      <tr><th>Browser</th><th>Vendor</th><th>version</th></tr>

      <tr><td>Netscape 6.0</td><td>Netscape6</td><td>6.0</td></tr>

      <tr><td>Netscape 6.01</td><td>Netscape6</td><td>6.01</td></tr>

      <tr><td>Netscape 6.1</td><td>Netscape6</td><td>6.1</td></tr>

      <tr><td>Netscape 6.2</td><td>Netscape6</td><td>6.2</td></tr>

      <tr><td>Netscape 6.2.1</td><td>Netscape6</td><td>6.2.1</td></tr>

      <tr><td>Netscape 6.2.2</td><td>Netscape6</td><td>6.2.2</td></tr>

      <tr><td>Netscape 6.2.3</td><td>Netscape6</td><td>6.2.3</td></tr>

      <tr><td>CompuServe 7.0</td><td>CS 2000 7.0</td><td>7.0</td></tr>

      <tr><td>Netscape 7 Preview Release 1</td><td>Netscape</td><td>7.0b1</td></tr>

      <tr><td>Netscape 7</td><td>Netscape</td><td>7.0</td></tr>

    </table>



    <p><a href="#top">top</a></p>



    <h2 id="examples">Examples</h2>



    <p>

      If you are like me, you learn best from examples. Studying how

      other authors use browser detection and cross browser coding 

      techniques in the <strong>best</strong> way to learn.

    </p>



    <h3>Example 1 - object based feature detection</h3>

    <p>

      This example illustrates the use of <em>feature detection</em>. Note that

      Gecko 1.0 (Netscape 7) and later implement the proprietary Internet Explorer feature

      <code>clientWidth</code> while Netscape 6 did not. In this example, Netscape 7

      and Internet Explorer 5+

      will automatically use <code>clientWidth</code> while Netscape Navigator 4,

      Netscape 6, CompuServe 7 <em>and Opera</em> will use <code>innerWidth</code>.

    </p>



    <p>

      Compare how you would have had to code this using <em>vendor/version</em>

      based detection approaches.

    </p>



    <blockquote>

      <pre><![CDATA[

if (windowRef.document.body && typeof(windowRef.document.body.clientWidth) == 'number')

{

  // Gecko 1.0 (Netscape 7) and Internet Explorer 5+

  width = windowRef.document.body.clientWidth;  

}

else if (typeof(windowRef.innerWidth) == 'number')

{

  // Navigator 4.x, Netscape 6.x, CompuServe 7 and Opera

  width = windowRef.innerWidth;

}]]></pre>

    </blockquote>



    <h3>Example 2 - object based feature detection</h3>



    <h4>Cross Browser Support</h4>

    <p>

      This example also illustrates the use of <em>feature detection</em>

      and shows the complications that can arise from the non standard

      implementations in other browsers.

    </p>



    <blockquote>

      <pre><![CDATA[

function moveElement(id, x, y)

{

  // move the element with id to x,y

  // where x,y are the horizontal

  // and vertical position in pixels



  var elm = null;

  if (document.getElementById)

  {

    // browser implements part of W3C DOM HTML

    // Gecko, Internet Explorer 5+, Opera 5+

    elm = document.getElementById(id);

  }

  else if (document.all)

  {

    // Internet Explorer 4 or Opera with IE user agent

    elm = document.all[id];

  }

  else if (document.layers)

  {

    // Navigator 4

    elm = document.layers[id];

  }



  if (!elm)

  {

    // browser not supported or element not found

  }

  else if (elm.style)

  {

    // browser implements part of W3C DOM Style

    // Gecko, Internet Explorer 4+, Opera 5+



    if (typeof(elm.style.left) == 'number')

    {

      // Opera 5/6 do not implement the standard correctly

      // and assume that elm.style.left and similar properties

      // are numbers.

      elm.style.left = x;

      elm.style.top  = y;

    }

    else

    {

      // Gecko/Internet Explorer 4+

      // W3C DOM Style states that elm.style.left is a string

      // containing the length followed by the unit. e.g. 10px

      // Gecko will allow you to omit the unit only in Quirks 

      // mode. 

      // Gecko REQUIRES the unit when operating in Standards

      // mode.

      elm.style.left = x + 'px';

      elm.style.top  = y + 'px';

    }

  }

  else if (typeof(elm.left) == 'number')

  {

    // Navigator 4

    elm.left = x;

    elm.top  = y;

  }

}]]></pre>

    </blockquote>



    <h4>Standards only</h4>

    <p>

      Consider how simple this function is if you 

      code it according to the W3C standards. 

    </p>



    <blockquote>

      <pre><![CDATA[

function moveElement(id, x, y)

{

  // move the element with id to x,y

  // where x,y are the horizontal

  // and vertical position in pixels



  var elm = document.getElementById(id);



  if (elm)

  {

    elm.style.left = x + 'px';

    elm.style.top  = y + 'px';

  }

}]]></pre>

    </blockquote>



    <p>

      Ask yourself this: "Is supporting <em>non-standard</em> 

      browsers worth the development and maintenance costs?"

    </p>



    <h3>Example 3 - Detecting specific Netscape Gecko branches</h3>



    <blockquote>

      <pre><![CDATA[

// return the rv value of a Gecko user agent

// as a floating point number. 

// returns -1 for non-gecko browsers, 

//          0 for pre Netscape 6.1/Gecko 0.9.1 browsers

//          number > 0 where each portion of 

//          the rv value delimited by . 

//          will be treated as value out of 100.

//          e.g. for rv: 3.12.42, 

//          getGeckoRv() returns 3.1242

//          

function geckoGetRv()

{

  if (navigator.product != 'Gecko')

  {

    return -1;

  }

  var rvValue = 0;

  var ua      = navigator.userAgent.toLowerCase();

  var rvStart = ua.indexOf('rv:');

  var rvEnd   = ua.indexOf(')', rvStart);

  var rv      = ua.substring(rvStart+3, rvEnd);

  var rvParts = rv.split('.');

  var exp     = 1;



  for (var i = 0; i < rvParts.length; i++)

  {

    var val = parseInt(rvParts[i]);

    rvValue += val / exp;

    exp *= 100;

  }



  return rvValue;

}





// determine if the browser is any Netscape Gecko

// branch >= 1.0.1 or Netscape 6.2.x/CompuServe 7 

// built after August 1, 2002



var rv    = geckoGetRv();

var found = false;



if (rv >= 0)

{

  // Gecko browser

  if (navigator.productSub > '20020801')

  {

    if (rv >= 1.0001)

    {

      found = true;

    }

    else if (rv >= 0.0904 && rv < 0.0905)

    {

      if (navigator.vendor == 'Netscape6' || navigator.vendor == 'CS 2000 7.0')

      {

        found = true;

      }

    }

  }

}

]]></pre>

    </blockquote>



    <h3>Example 4 - <a href="http://www.iht.com/">The International Herald-Tribune</a></h3>

    <p>

      This <a href="http://www.iht.com/">site</a>

      illustrates many of the techniques described in this article.

      They use <em>downlevel</em>

      pages for less capable browsers combined with <em>object based feature</em>

      detection to produce a compelling and interesting site.

    </p>



    <h3>Examples From DevEdge</h3>

    <ul>

      <li><a href="/xbProjects-docs-srce/xbDOM/">xbDOM</a></li>

      <li><a href="/xbProjects-docs-srce/xbMarquee/">xbMarquee</a></li>

      <li><a href="/xbProjects-docs-srce/xbPositionableElement/">xbPositionableElement</a></li>

      <li><a href="/xbProjects-docs-srce/xbAnimatedElement/">xbAnimatedElement</a></li>

    </ul>



    <p><a href="#top">top</a></p>



    <h2 id="conclusion">Conclusion</h2>



    <p>

      As we have seen in this article, the browser detection story is still quite 

      complicated due to differences between the modern browsers such as 

      Netscape Gecko/Internet Explorer 6 and the older or non-standard browsers 

      such as Netscape Navigator 4. 

      You may say to yourself "If only all browsers were as good as Netscape Gecko 

      and Internet Explorer 6, then my job would be so much easier!". 

    </p>

    <p>

      I would like to leave you with this thought. In the past, users did not have

      the choice of picking a browser which implemented the standards however today

      they do have a choice. There is no compelling reason 

      for anyone in the world to continue to use a browser which does not support 

      the standards. However, as long as web developers continue to code work arounds

      for these older browsers, users will not have a compelling reason to 

      upgrade. By ceasing to support older browsers, you can provide a reason for users

      to upgrade. This will benefit not only them, but yourself as well. Supporting

      <strong>only standards based browsers</strong> can reduce development and maintanance

      costs as well as increase the <em>dynamic and compelling content</em> which will

      attract visitors and increase your revenue. The choice is yours... <strong>Decide to 

        support the standards today!</strong>

    </p>



    <p><a href="#top">top</a></p>



    <h2 id="links">Links</h2>



    <ul>

      <li><a href="http://devedge.netscape.com/viewsource/2002/gecko-compatibility/">Netscape Gecko Compatibility Handbook</a></li>

      <li><a href="http://www.mozilla.org/build/revised-user-agent-strings.html">Mozilla user-agent strings</a></li>

      <li><a href="http://devedge.netscape.com/library/xref/2002/client-data/property-data-navigator.html">Object Cross Reference - <code>navigator</code></a></li>

      <li><a href="http://devedge.netscape.com/viewsource/2002/gecko-useragent-strings/">Netscape Gecko User Agent Strings</a></li>

      <li><a href="http://www.faqs.org/rfcs/rfc1945.html">RFC 1945 - Hypertext Transfer Protocol -- HTTP 1.0</a></li>

      <li><a href="http://www.faqs.org/rfcs/rfc2068.html">RFC 2068 - Hypertext Transfer Protocol -- HTTP 1.1</a></li>

      <li><a href="http://devedge.netscape.com/library/xref/2002/client-data/"> Client Object Cross References </a></li>

      <li><a href="http://www.mozilla.org/docs/web-developer/quirks/">Quirks Mode in Mozilla</a></li>

      <li><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp">CSS Enhancements in Internet Explorer 6</a></li>

      <li><a href="http://www.w3.org/">W3C</a>

        <ul>

          <li><a href="http://www.w3.org/MarkUp/">W3C Markup</a></li>

          <li><a href="http://www.w3.org/TR/">W3C Technical Recommendations</a>

              <ul>

                <li><a href="http://www.w3.org/TR/html401/">W3C HTML 4.01</a></li>

                <li><a href="http://www.w3.org/TR/REC-CSS1/">W3C CSS 1</a></li>

                <li><a href="http://www.w3.org/TR/REC-CSS2/">W3C CSS 2</a></li>

                <li><a href="http://www.w3.org/TR/DOM-Level-2-Core/">W3C DOM Core 2</a></li>

                <li><a href="http://www.w3.org/TR/DOM-Level-2-HTML/">W3C DOM HTML 2</a></li>

                <li><a href="http://www.w3.org/TR/DOM-Level-2-Style/">W3C DOM Style 2</a></li>

              </ul>

          </li>

        </ul>

      </li>

    </ul>

  </nde:content>



</nde:article>

