Browser Detection and the body_class() Function

Yesterday, I wrote an article introducing and unwrapping the new WordPress body class function that will be included in WordPress 2.8. Today, I want to take it a step further by giving you a practical example of how you you can use the function to make things easier for yourself.

One of the more frustrating things about coding for the web is the fact that different browsers often render the same code differently than one another. Wouldn’t it be nice if we could apply certain CSS styles to just the browsers that need it? With the new body_class() function, and a little code magic on our part, and you’ll be able to do just that.

It should be noted that this article will be a bit more involved than some of the others on this site. There will be a lot of assumptions made about your level of coding experience.

Leveraging the Tools WordPress Provides

Many people don’t know this, but WordPress provides several global variables that we can use to do browser detection. Once again, browsing around the WordPress source code pays off.

The variables WordPress provides are as follows:

  • $is_lynx
  • $is_gecko
  • $is_IE
  • $is_winIE
  • $is_macIE
  • $is_opera
  • $is_NS4
  • $is_safari
  • $is_chrome
  • $is_iphone

Each variable has a value of FALSE by default, and is switched to TRUE if the condition is true. For example, if the user loads a page using Firefox, the $is_gecko gets a value of TRUE.

This list may not be as extensive as we might like (browser versions, platforms, etc.), but it is a really good start.

Building the Browser Detection Function

Now that we know that WordPress is doing simple browser detection for us, we can use this data to add classes to the output of the body_class() function. And in order to add those classes, we’re going to use a method that I outlined yesterday — we’re going to filter the classes using the body_class filter. Here’s the final code — I’ll explain what’s going on afterwards.

<?php
add_filter('body_class','browser_body_class');
function browser_body_class($classes) {
	global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone;

	if($is_lynx) $classes[] = 'lynx';
	elseif($is_gecko) $classes[] = 'gecko';
	elseif($is_opera) $classes[] = 'opera';
	elseif($is_NS4) $classes[] = 'ns4';
	elseif($is_safari) $classes[] = 'safari';
	elseif($is_chrome) $classes[] = 'chrome';
	elseif($is_IE) $classes[] = 'ie';
	else $classes[] = 'unknown';

	if($is_iphone) $classes[] = 'iphone';
	return $classes;
}
?>

The first thing you’ll notice is that we had to globalize all the conditional variables. This is something PHP requires in order to use variables that are defined outside the function.

Once we’re able to use the variables, we use a simple IF ... ELSEIF ... ELSE statement to check if the different conditions are true. If they are true, then we add the corresponding class. If they are not true, then we move along.

You’ll also notice that I checked the value of the $is_iphone variable in a different IF statement. That is because when browsing with an iPhone, you are also using Safari. Therefore, if I had checked the $is_iphone variable in the first IF statement, either the “safari” or “iphone” class wouldn’t have gotten added to the $classes[] array.

If, for whatever reason, the server can’t detect what type of browser the user is using, it will add an “unknown” class to the $classes[] array.

Finally, we return the $classes array with the new browser classes added to it.

The Result

The final result will look something like this, if you view the source code of your page:

<body class="home blog logged-in safari">

How to Use the Browser Body Class

Now that we have the <body> tag outputting a class for the browser we’re using, we can use CSS to target particular styles to elements being viewed in certain browsers. For instance, let’s say this was my default link style:

a {
	color: blue;
	text-decoration: underline;
}

Now, let’s make the links a different color when a user views the site in FireFox:

.gecko a {
	color: red;
	text-decoration: underline;
}

Notice, all I had to do was prepend the browser class-selector to the style, and now, any time someone using FireFox visits my site, all their links will be red, instead of blue.

One of the most useful applications I’ve discovered is the ability to target Internet Explorer with certain styles. It’s great to be able to just apply slightly different styles to certain elements in order to account for the many bugs in Internet Explorer.

So there you go! You can now use the new WordPress body class function, and the built-in browser detection in WordPress to add new CSS classes to your <body>.

Further Reading

Here are some other resources that you might find useful when trying to do browser detection, if you want to make your function even more thorough:

Comments

  1. kyle says

    My only problem with using this for css, is if you’ve got cache implemented on your wordpress site as well – won’t the cached copy be relegated to the browser used when making the cached copy?

    1. says

      Yes. If you’re using a cacheing program, then the browser body class ceases to be dynamic. So, if you build this into a public theme, be sure to do a funcion/class check for something in the caching plugins.

  2. says

    I didn’t even know about the browser detection, thanks for the info.

    However, I would recommend using switch instead of if..else.
    It performs better, especially if you have more than 3-4 cases.

  3. says

    Please, please do not encourage people to do something like this. Browser sniffing in general is a very brittle technique that will fail in a significant number of cases, and WordPress’s browser sniffing is particularly naive. It’s a hack that should probably be removed in the future.

    If you need to target styling to certain browsers, use more reliable, established methods such as using IE’s conditional comments:

    <!--[if IE 6]>
    [ IE-specific stuff here ]
    <![endif]-->
    
    1. says

      @Austin,
      Normally, I do use conditional comments to target IE, and I probably still will, even though I hate having to do so. But there are occasions where IE stylesheets aren’t enough. For instance, I recently ran into a bug in FireFox 2. It was fixed in FF3. So I used server side browser detection to fix it.

      Rules and exceptions.

  4. says

    But there are occasions where IE stylesheets aren’t enough. For instance, I recently ran into a bug in FireFox 2. It was fixed in FF3. So I used server side browser detection to fix it.

    IE conditional comments was an example of a more robust approach.

    Without knowing what bug you’re referring to, I can’t say whether browser sniffing is required. But WordPress’s naive browser sniffing wouldn’t help. It just sets $is_gecko to true, not distinguishing between versions. And even if you use your own sniffing to check for a “2,” you’ll miss Flock, which in version 1.x uses the same engine as Firefox 2.

    Besides, my main concern is that you don’t have any caveats in your post. You’re a respected theme designer in the WordPress community, and when people see that Nathan Rice says that this works, they’ll take it at face value.

  5. says

    Great post Nathan,

    Have you ever checked out the thematic_body_class function that’s included with the Thematic framework? It has a few additions added to it that provide better flags for browser versions.