picture of Tim Perdue
Whoever said CSS would solve all your cross-platform browser display issues needs to lay off the pipe a little. I have yet to get CSS to work perfectly across all browsers / platforms, but I have gotten it to work "good enough" to get by.
I did it by using some fairly simplistic browser detection, as in recycling a library I wrote for SourceForge (which was recycled from a library on GotoCity.com).
Here are some of the things I discovered while setting up CSS on a handful of sites:
  1. If you don't set a font at all, users will complain because their browser defaults are either too big or too small - as if it's your fault.
  2. Using the CSS1 font-size: tag with a specific point size like 12pt breaks some browsers on some platforms (Netscape on Wintel).
  3. Even if that weren't the case, point sizes are different on different platforms (Macs display fonts smaller than Windows).
  4. And even if they rendered the same across all platforms, it's a really bad idea to hard-code sizes, as there are many people with impaired vision. When you hard-code a point-size, they can't override the size with their browser, and thus can't see your site. One of the worst sites on the internet is CNN.com, which hard-codes very small fonts into their CSS sheet.
  5. Because of this, you should stick with scaling percentages or the size syntax (small, medium, x-small, etc).
With those hard-learned lessons in mind, you can design a browser-smart CSS sheet and generate it with PHP. I won't go into details on CSS here. You can view the spec and examples at http://www.w3.org/Style/CSS/Test/19981002/.
Most of that spec was completely ignored by the geniuses at Netscape and Microsoft, which is why it has become such a headache for developers.
At any rate, here's my browser detection library. Just require() it at the top of your page and you'll be able to call the slick functions to generate browser-specific HTML.

<?php
//
// SourceForge: Breaking Down the Barriers to Open Source Development
// Copyright 1999-2000 (c) The SourceForge Crew
// http://sourceforge.net
//
// $Id: tim20000821.php3,v 1.2 2001/05/22 19:22:47 tim Exp $


unset ($BROWSER_AGENT);
unset (
$BROWSER_VER);
unset (
$BROWSER_PLATFORM);

function 
browser_get_agent () {
    global 
$BROWSER_AGENT;
    return 
$BROWSER_AGENT;
}

function 
browser_get_version() {
    global 
$BROWSER_VER;
    return 
$BROWSER_VER;
}

function 
browser_get_platform() {
    global 
$BROWSER_PLATFORM;
    return 
$BROWSER_PLATFORM;
}

function 
browser_is_mac() {
    if (
browser_get_platform()=='Mac') {
        return 
true;
    } else {
        return 
false;
    }
}

function 
browser_is_windows() {
    if (
browser_get_platform()=='Win') {
        return 
true;
    } else {
        return 
false;
    }
}

function 
browser_is_ie() {
    if (
browser_get_agent()=='IE') {
        return 
true;
    } else {
        return 
false;
    }
}

function 
browser_is_netscape() {
    if (
browser_get_agent()=='MOZILLA') {
        return 
true;
    } else {
        return 
false;
    }
}


/*
    Determine browser and version
*/


if (ereg'MSIE ([0-9].[0-9]{1,2})',$HTTP_USER_AGENT,$log_version)) {
    
$BROWSER_VER=$log_version[1];
    
$BROWSER_AGENT='IE';
} elseif (
ereg'Opera ([0-9].[0-9]{1,2})',$HTTP_USER_AGENT,$log_version)) {
    
$BROWSER_VER=$log_version[1];
    
$BROWSER_AGENT='OPERA';
} elseif (
ereg'Mozilla/([0-9].[0-9]{1,2})',$HTTP_USER_AGENT,$log_version)) {
    
$BROWSER_VER=$log_version[1];
    
$BROWSER_AGENT='MOZILLA';
} else {
    
$BROWSER_VER=0;
    
$BROWSER_AGENT='OTHER';
}

/*
    Determine platform
*/

if (strstr($HTTP_USER_AGENT,'Win')) {
    
$BROWSER_PLATFORM='Win';
} else if (
strstr($HTTP_USER_AGENT,'Mac')) {
    
$BROWSER_PLATFORM='Mac';
} else if (
strstr($HTTP_USER_AGENT,'Linux')) {
    
$BROWSER_PLATFORM='Linux';
} else if (
strstr($HTTP_USER_AGENT,'Unix')) {
    
$BROWSER_PLATFORM='Unix';
} else {
    
$BROWSER_PLATFORM='Other';
}

/*
//debug code
echo "\n\nAgent: $HTTP_USER_AGENT";
echo "\nIE: ".browser_is_ie();
echo "\nMac: ".browser_is_mac();
echo "\nWindows: ".browser_is_windows();
echo "\nPlatform: ".browser_get_platform();
echo "\nVersion: ".browser_get_version();
echo "\nAgent: ".browser_get_agent();
*/

?>
There, now we can start using that library to determine font sizes.
Internet Explorer on Wintel has the biggest default font by a long shot. If you don't specify a font size, Wintel users will get huge fonts and they'll yell to no end, even though it's caused by their own browser settings.
Beyond IE on Windows, other browsers like Netscape also have big fonts. Macs for some reason buck this trend and render fonts very small, so you need to set the font up a couple steps or they'll be angry.
The "other" platforms, like linux, unix, etc, come last. I generally set the fonts about the same as I do for Netscape on Windows and I haven't seen too many complaints.
Here's the library. Notice that the CSS sheet itself is generic, but the font-size: on that sheet is a variable which is set at the top of the code.

<?php 

function css_site() {

    
//determine font for this platform
    
if (browser_is_windows() && browser_is_ie()) {

        
//ie needs smaller fonts than anyone else
        
$font_size='x-small';
        
$font_smaller='xx-small';
        
$font_smallest='7pt';

    } else if (
browser_is_windows()) {

        
//netscape or "other" on wintel
        
$font_size='small';
               
$font_smaller='x-small';
        
$font_smallest='x-small';

    } else if (
browser_is_mac()){

        
//mac users need bigger fonts
        
$font_size='medium';
        
$font_smaller='small';
        
$font_smallest='x-small';

    } else {

        
//linux and other users
        
$font_size='small';
        
$font_smaller='x-small';
        
$font_smallest='x-small';

    }

    
$site_fonts='verdana, arial, helvetica, sans-serif';

    
?>
    <style type="text/css">
    <!--
    BODY, TH, TD, OL, UL, LI { font-family: verdana, arial, helvetica, sans-serif; font-size: <?php echo $font_size?>; }
    H1 { font-size: 175%; font-family: <?php echo $site_fonts?>; }
    H2 { font-size: 150%; font-family: <?php echo $site_fonts?>; } 
    H3 { font-size: 125%; font-family: <?php echo $site_fonts?>; }
    H4 { font-size: 100%; font-family: <?php echo $site_fonts?>; } 
    H5 { font-size: 75%; font-family: <?php echo $site_fonts?>; }
    H6 { font-size: 50%; font-family: <?php echo $site_fonts?>; }
    PRE, TT, CODE { font-family: courier, sans-serif; font-size: <?php echo $font_size?>; }
    A:hover { text-decoration: none; color: #FF6666; font-size: <?php echo $font_size?>; }
    A.menus { color: #FF6666; text-decoration: none; font-size: <?php echo $font_smaller?>; }
    A.menus:visited { color: #FF6666; text-decoration: none; font-size: <?php echo $font_smaller?>; }
    A.menus:hover { text-decoration: none; color: #FF6666; background: #ffa; font-size: <?php echo $font_smaller?>; }
    A.menussel { color: #FF6666; text-decoration: none; background: #ffa; font-size: <?php echo $font_smaller?>; }
    A.menussel:visited { color: #FF6666; text-decoration: none; background: #ffa; font-size: <?php echo $font_smaller?>; }
    A.menussel:hover { text-decoration: none; color: #FF6666; background: #ffa; font-size: <?php echo $font_smaller?>; }
    A.menusxxs { color: #FF6666; text-decoration: none; font-size: <?php echo $font_smallest?>; }
    A.menusxxs:visited { color: #FF6666; text-decoration: none; font-size: <?php echo $font_smallest?>; }
    A.menusxxs:hover { text-decoration: none; color: #FF6666; background: #ffa; font-size: <?php echo $font_smallest?>; }
    -->
    </style>
    <?php
}

?>
And that's it. You've got the building blocks now to do browser detection in your code, and, if desired, generate a custom CSS style sheet for each user that visits your site. My hope is that the need for this will go away when Mozilla arrives, but I'm not holding my breath on either its arrival or its wide acceptance.
Until then, have fun with the detection code and let me know if you use it for anything interesting.
--Tim