5.5 Detecting the Client Operating System

NN 2 , IE 3

5.5.1 Problem

You want to apply styles or other content features tailored to a particular operating system.

5.5.2 Solution

The string returned by the navigator.userAgent property usually contains information about the basic operating system platform on which the browser is running. Unfortunately, there is no standard nomenclature that you can search the userAgent string for a particular operating system. The values are not only different with each browser brand, but have evolved over time and may be different for OEM versions of the browser.

The widest difference is in the depiction of the Windows platforms, in which Windows 98, for example, might be displayed as "Win98" or "Windows 98". A better solution is to test for the presence of strings that identify other operating systems more uniformly. For instance, all Macintosh versions have the string "Mac" somewhere in the navigator.userAgent property. By the same token, all Windows versions have the string "Win" in them, but that could be anything from Windows 3.1 to Windows XP. Furthermore, all Unix versions of Navigator have the string "X11". If you're just looking for a rough cut, the following global variable assignment statements will do the job of setting Boolean flags:

var isWin = (navigator.userAgent.indexOf("Win") != -1);
var isMac = (navigator.userAgent.indexOf("Mac") != -1);
var isUnix = (navigator.userAgent.indexOf("X11") != -1);

Browsers running under Linux include both "X11" and "Linux" in the navigator.userAgent property.

5.5.3 Discussion

As you can see, operating-system detection is a tricky business and should be used with care. While some OEM versions of a browser might have more specific information about the operating system in the navigator.userAgent property (such as the specific release number of the operating system), you are not assured of this information being there for all browsers on a given operating system. For example, Windows XP identifies itself as a version of Windows NT. On the Macintosh side, Netscape 6 and later offer sufficient detail to differentiate between users of Mac OS X and earlier versions, but IE for the Mac treats all Mac OS versions the same.

Netscape 6 and later include a new navigator object property, oscpu, that returns that portion of the userAgent value containing as much operating system and CPU information as is revealed by the browser. When running under Windows, the property conveys only the operating system information, such as "Win98" or "Windows NT 5.1." For the Mac, the property always returns the CPU class ("PPC") and the operating system for Mac OS X (as "Mac OS X").

Once you are satisfied that the global variables you set for operating system versions are doing what you need, you can use them efficiently in making operating system-dependent settings for page characteristics such as font size. For example, it is well-known by designers that a given font point size looks smaller on a Macintosh screen than on a Windows display. If you are intent on specifying font sizes in point units, you can make the content look more similar across operating systems by dynamically writing the style sheet, using the operating system global variables to set the desired font size:

<script language="JavaScript" type="text/javascript">
document.write("<style type='text/css'>");
document.write("body {font-size:" + ((isMac) ? "12" : "10") + "pt}");

Similar decision constructions can be used to apply operating system-specific element position coordinates if your design requires it. In fact, you can nest inline if constructions to get three-way switching. For example, if you need to establish a variable for a pixel offset between elements, you can set an offset for each of the three major OS categories as follows:

var elemOffset = (isMac) ? 15 : ((isWin) ? 12 : 10);

After execution, the elemOffset variable is 15 for the Mac, 12 for all Windows flavors, and 10 for all others (presumably Unix).

5.5.4 See Also

Recipe 5.1, particularly if one operating system version of a particular browser brand is giving you design headaches; Recipe 11.5 for importing operating system-specific style sheet definitions; Recipe 4.6 for conditional branching.