About Client Capabilities

Web developers are constantly searching for ways to design and implement sites that deliver the best user experience possible. One way to enhance user experience is to customize content based on capabilities that the client browser supports. By making this information available on the client, pages can be cached, server roundtrips minimized, server resources freed up as content generation shifts back to the client, and overall performance improved. For example, when a client-side script detects a low-bandwidth modem connection to the server, it may choose to request low-resolution images from the server to minimize bandwidth consumption.

Client capabilities consists of information about the browsing environment, such as screen resolution, screen dimensions, color depth, CPU, or connection speed. Microsoft Internet Explorer 4.0 exposed client capabilities as properties through the Dynamic HTML (DHTML) Object Model. Internet Explorer 5 enhanced this further to include a means to install browser components on demand. Beginning with Internet Explorer 5, all this information was encapsulated into DHTML behaviors and made available as one of the browser's default behaviors.

This article outlines the benefits introduced by a client-side solution and discusses the details involved in obtaining client capabilities information from the client. Realizing that a client-side solution is not suited for every Web site or Web application, a solution for server-side developers is also provided.

  • Benefits of a Client-Side Solution
  • Obtaining Client Capabilities
  • The Blended Client-Server Approach
  • Related Topics

Benefits of a Client-Side Solution

Before the release of Internet Explorer 4.0, the only means of obtaining client capability information was through cookies. Microsoft Internet Information Server (IIS) provided another mechanism through the Browser Capabilities component. However, these two methods have inherent limitations. By exposing client capabilities on the client side, Internet Explorer 4.0 provides a solution that attempts to overcome these limitations.

Using Cookies

The following diagram illustrates what occurs when the user types in the URL of a site that requires client capabilities.

Client Capabilities Illustration

1) The client sends a request to the server. 1) The client sends a request to the server.
2) The server sends back a script to obtain the information. 2) The server sends the page, including a client-side script, to obtain the information.
3) The client executes the script and stores the information in a cookie. 3) The client executes the script and renders the page.
4) The client sends the cookie back to the server.
5) The server processes the information in the cookie and generates a custom page.
6) The server sends the custom page back and the client renders it.

The following table outlines the limitations to the server-side approach that uses cookies, and explains how these problems are addressed by a client-side solution that uses client capabilities.

Server-side limitation Client-side solution
Every time new client capability information is sent in a cookie as part of the client's request, the server spends precious cycles generating content for that client request. By providing client capabilities on the client side, no cookies have to be passed back and forth. All the processing takes place on the client computer, none takes place on the server. This provides the server with more time to service other clients' requests.
Because the server generates a custom page for every client request, the page cannot be cached. Client capabilities provides a way to shift the content generation process from the server back to the client. Because the server sends the same page for every client request for the same URL, the page is cached. Every subsequent client request for the same URL, therefore, can be serviced directly by the cache, rather than by an expensive roundtrip back to the server.
In a multiuser environment, where Internet requests are routed through a proxy server, the limitation is even more apparent. Consider the same scenario with 1,000 users. If every one of those users request the same page at least two times, the server has to respond 2,000 times to service each of those requests, because the page uses cookies and therefore cannot be cached on the proxy. Because the client-side solution allows the page to be cached, the only time the proxy hits the server is the very first time a user requests the page. Every subsequent request for the same page is serviced directly by the proxy's cache, instead of the server. Consider the same environment of 1,000 users. This means one request instead of 2,000 requests. This represents a significant reduction in the number of server hits and results in increased performance on both the client and the server.

Using the Browser Capabilities Component

The server-side Browser Capabilities component in IIS provides information about the capabilities supported by the browser by comparing the user-agent HTTP Header with the entries in the Browscap.ini file, which maps the Understanding User-Agent Strings to a list of features known to be supported by that version of the browser. Server-side scripts are then able to deliver customized content based on this information.

Each of the entries in the Browscap.ini file is available as a property of the Browser Capabilities component. The following example demonstrates how to detect if Microsoft ActiveX controls are supported.

<% Set objBC = Server.CreateObject("MSWC.BrowserType") 
   If objBC.ActiveXControls Then %>

   <!-- HTML that implements the ActiveX control. -->

<% Else %>

   <!-- HTML that uses an alternate presentation. -->

<% End If %> 

This approach poses limitations as well. The following table outlines how the server-side component compares to a client-side solution.

Server-side limitation Client-side solution
The component relies on a file called Browscap.ini, which contains a static list of client capabilities based on the version of the browser. Due to the static nature of this file, it is updated every time a new version of the browser becomes available. Exposing client capabilities on the browser works around this by making the same information available dynamically as part of the object model and accessible through script.
The static list maintained in Browscap.ini fails to account for options that the client can turn on or off on demand, nor does it provide version-independent information, such as whether certain components currently are installed on the client's system. Among the types of information client capabilities provides are screen resolution, screen dimensions, available bandwidth, cookies or Java support, color depth, language, as well as components currently installed on the client.

Obtaining Client Capabilities

As highlighted in the preceding section, the ideal way to obtain client capability information is from a client-side script. This method minimizes server round trips, frees up server resources, and, consequently, boosts performance. It also provides information about browser settings and user preferences that cannot be obtained in any other way.

Internet Explorer 4.0 introduced this type of information as a set of enhancements to the DHTML Object Model, making it easily accessible to client-side scripts. In most cases, this information has been exposed as properties of the navigator object, which contains information about the browser. In other cases, the information is available as properties of the screen object.

The following table outlines the client capabilities exposed since Internet Explorer 4.0.

Client capability Description
availHeight Retrieves the height of the working area of the system's screen, excluding the Microsoft Windows taskbar.
availWidth Retrieves the width of the working area of the system's screen, excluding the Windows taskbar.
bufferDepth Sets or retrieves the number of bits per pixel used for colors in the off-screen bitmap buffer.
colorDepth Retrieves the number of bits per pixel used for colors on the destination device or buffer.
cookieEnabled Retrieves whether client-side cookies are enabled in the browser.
cpuClass Retrieves a string denoting the CPU class.
height Retrieves the vertical resolution of the screen.
javaEnabled Returns whether Java is enabled.
platform Retrieves the name of the user's operating system.
systemLanguage Retrieves the default language used by the system.
userLanguage Retrieves the current user language.
width Retrieves the horizontal resolution of the screen.

Additional implementation details can be found in the following example.

Sample Code

The following example downloads the appropriate image based on the number of colors supported by the client screen. If it detects fewer than 256 colors (or 8 bits per pixel), it displays an image of 16 colors; otherwise, it displays a higher resolution image. As a result, the colors are more suited to the client screen, and overall user experience is improved.

<img id="myImage" src="16color.bmp" width=200 height=200>

<script>
if (window.screen.colorDepth >= 8)
    myImage.src = "256color.bmp";
</script> 

As of Internet Explorer 5, client capabilities information has been available as one of the browser's default behaviors. Encapsulated in this behavior are all the properties exposed in Internet Explorer 4.0, plus a set of new properties and methods that enable Web applications to install browser components on demand. For a complete list of properties and methods, see the clientCaps behavior reference.

The following example shows how to use the clientCaps behavior to obtain some of the available client capabilities information. For more information about behaviors and using behaviors on a page, see Related Topics.

The Blended Client-Server Approach

Note  This approach requires Microsoft Internet Information Services (IIS) 5.0 and uses client-side cookies.

Although the benefits are clear, a purely client-side solution might not be viable for every Web application. In some cases, a Web developer might prefer to use a server-side solution, and feels that the disadvantage of using cookies is negligible. For those cases, Internet Explorer 5 and IIS 5.0 introduce a way to access client capability information from Active Server Pages (ASP), using a combination of cookies and the server-side Browser Capabilities component. As of IIS 5.0, the Browser Capabilities component has been extended to include client-side capability information as properties of the component.

To collect user-specific information, the browser will return the requested information in a cookie named BrowsCap, which the ASP interpreter requests when the page is first executed. The name/value pairs from the cookie are added as properties to the Browser Capabilities component, where they are accessible to server-side script.

Implementation Details

Here are the steps required to obtain client capability information from a server-side script.

First, create a file that contains the client-side script used to retrieve the client capability information on the server's behalf.

  1. Cut and paste the following code to your file. Note that you will need to optimize and modify the script to handle the types of browsers that you expect to encounter.

    <html xmlns:IE>
    <head>
    <style>
     IE\:clientcaps {behavior:url(#default#clientcaps)}
    </style>
    </head>
    <body onload="createCookie();">
    <IE:clientcaps ID="oClientCaps" />
    <script language="JavaScript"><!--
    function createCookie() {
        // Internet Explorer 5 and later
        strCookie = 'width=' + oClientCaps.width
               + '&height=' + oClientCaps.height
               + '&availWidth=' + oClientCaps.availWidth
               + '&availHeight=' + oClientCaps.availHeight
               + '&bufferDepth=' + oClientCaps.bufferDepth
               + '&colorDepth=' + oClientCaps.colorDepth
               + '&cookies=' + oClientCaps.cookieEnabled
               + '&javaapplets=' + oClientCaps.javaEnabled
               + '&connectionType=' + oClientCaps.connectionType
               + '&cpuClass=' + oClientCaps.cpuClass
               + '&platform=' + oClientCaps.platform
               + '&systemLanguage=' + oClientCaps.systemLanguage
               + '&userLanguage=' + oClientCaps.userLanguage;
        // Set the cookie
        document.cookie = "BrowsCaps=" + strCookie;
    }
    --></script>
    </body>
    </html> 
    

    The property names and their corresponding values are constructed as an ampersand-delimited list of name/value pairs. Persisting information as "name=value" is characteristic of cookies. For more information, see cookie.

  2. Add as many name/value pairs as you need. The property names specified on the left side of the equal sign do not need to match the names of the actual property in the DHTML Object Model. The name you specify will be used when the property is accessed from the server-side script.

  3. Set the BrowsCap cookie to the resulting string of all the name/value pairs. The cookie is passed back to the server.

Next, create a new Active Server Pages (ASP) file or modify an existing one.

  1. Insert the following METADATA tag as the first line in your ASP file. Make sure you set the SRC attribute to the name of the file you created above.

    <!--metadata type="Cookie" name="BrowsCap" src="InsertNameHere.htm"-->
    
  2. Create an instance of the Browser Capabilities component.

    There are two ways to do this. One way is to insert this object tag into your page.

    <object id=myBrowsCap progid="MSWC.BrowserType" runat="Server"></object>
    

    Another way is to call the Server.CreateObject method in ASP, and assign it to the variable myBrowsCap.

    <% Set myBrowsCap = Server.CreateObject("MSWC.BrowserType") %>
    
  3. Once the Browser Capabilities component is created, it parses the cookie string to find the values of individual properties. These values are then accessible to the server-side script as properties of the component.

    <%
       Response.write("width= "         +myBrowsCap.width          + "<br>") 
       Response.write("height= "        +myBrowsCap.height         + "<br>") 
       Response.write("availWidth= "    +myBrowsCap.availWidth     + "<br>") 
       Response.write("availHeight= "   +myBrowsCap.availHeight    + "<br>") 
       Response.write("bufferDepth= "   +myBrowsCap.bufferDepth    + "<br>") 
       Response.write("colorDepth= "    +myBrowsCap.colorDepth     + "<br>") 
       Response.write("cookies= "       +myBrowsCap.cookies        + "<br>") 
       Response.write("javaapplets= "   +myBrowsCap.javaapplets    + "<br>") 
       Response.write("cpuClass= "      +myBrowsCap.cpuClass       + "<br>")
       Response.write("platform= "      +myBrowsCap.platform       + "<br>")
       Response.write("systemLanguage= "+myBrowsCap.systemLanguage + "<br>")
       Response.write("userLanguage= "  +myBrowsCap.userLanguage   + "<br>")
    %>