CSS Browser detection using jQuery instead of hacks

2 Dec 2008 | Jon Hobbs-Smith
Browser sniffing is messy. There are a million ways to do it but none of them are particularly clean and most involve conditional statements such as "<!--[if condition]> HTML <![endif]-->" for IE and various other CSS selector hacks for other browsers.

I've done a fair amount of browser sniffing with jQuery recently and it's really easy, useful for when you need to detect the browser and version number in your javascript. It occurred to me that it would be easy to detect the browser and then put something in the DOM that your CSS could use for conditional formatting. So I wrote a quick script in JavaScript/jQuery.

How it works:


All you have to do is include the JavaScript file in the head of the page and it'll attach 2 classes to your body tag to say what browser and what version is being used so you've got 2 levels of granularity. Possible values are...

.browserIE
.browserIE6
.browserIE7
.browserIE8
.browserChrome
.browserChrome1
.browserSafari
.browserSafari1
.browserSafari2
.browserSafari3
.browserMozilla
.browserFirefox
.browserFirefox1
.browserFirefox2
.browserFirefox3
.browserOpera

If you need to detect any other browsers then it would be easy to modify the script.

All that happens automatically.

Usage example:


All you have to do is write your CSS selectors to use those classes where necessary, so let's say for example that you had an input textbox which looks correct in every browser except safari (quite common in my experience) and you want to position it 2 pixels lower in safari, all you have to do is set up the following 2 styles.

#myInput {background:black;} .browserSafari #myInput{background:black; position:relative; top:2px;}
Pretty neat compared to other solutions. The script is < 1k minified and the browser detection only needs to be done once on page load, from that point on it's CSS selectors all the way.


Get the code:


download files  browserDetect.js (2k)
download files  browserDetect-min.js (0.9k)


comments

Shadowfiend @ 4 Dec 2008 5:11 AM

I would argue that conditional comments are not a hack for the web developer. They're a hack in IE, yes, but that hack is in fact a useful feature for the developer.

Arguably detecting the browser using Javascript instead of using the built-in IE feature is, in fact, an even better plan, for a variety of reasons:

* You don't load the rules that won't be applying because they're not for this browser.

* You don't depend on a technology that can be turned off independently of CSS.

* You don't depend on a technology where a syntax error could temporarily break your browser detection.

* There's no sense in wasting browser time setting the relevant class and recalculating the styles everywhere. Yes, this time is essentially unnoticeable, but from a 'dirty vs clean' stand point I think that make it dirtier.

In short, I still think conditional comments are the way to go for IE targeting. Though this could come in useful in targeting styles for browsers other than IE, in my experience it's relatively rare to have to target styles that way, and when you do, you can typically work around it by doing things a little differently rather than applying a style to just one browser. Neat technique, of course, I just personally don't think it trumps existing ones for cleanliness.

Jon @ 4 Dec 2008 11:37 AM

I see your point and I think it comes down to personal preference.

Most of our sites rely on javascript being switched on to use all of their features anyway and personally I'm not a fan of the extra markup cause by traditional methods, or keeping a totally seperate stylesheet for IE which makes it hard to just go in and edit things in a single location.

Andy Ford @ 5 Dec 2008 10:14 PM

Well done. Aside from its dependency on jQuery, are there any significant differences to CSS Browser Selector? http://rafael.adm.br/css_browser_selector/

Just curious. I've yet to use either script but am certain I will soon

Jon @ 5 Dec 2008 10:51 PM

@Andy - Nope, they look very similar. This was just an idea I came up with on a recent project. That guy's clearly had the same idea :)

Karl Swedberg @ 5 Dec 2008 11:55 PM

Although I'm not a big fan of browser sniffing, I can see how this sort of thing might come in handy from time to time. I'd suggest pulling the script out of the $(document).ready() function, though, and adding the class to the html element rather than to the body (as I wrote about here). This way you can avoid the flash of unstyled content that can occur with complex DOM structures.

keif @ 13 Feb 2009 7:07 PM

The problem with this is it needs javascript to function - instead of incorporating everything in one CSS, I'd *assume* it'd be best to do the browser detection and load the necessary CSS via JS.

Or do the browser detection serverside (but not everyone has the capability, understandably).

Adilson @ 31 Mar 2009 9:04 PM

Excelent solution! It is clean, ellegant and effective.The code is easy to change if a necessity arrises.
Congratulations.

John @ 10 Jun 2009 4:44 PM

Could this be modified to search for platform specific versions of browsers - say for instance, to differentiate between gecko versions for windows & mac?

Bhooshan @ 16 Jul 2009 1:59 PM

I am trying to do for IE8 but nothing works for me. I've called both the files in head "browserDetect.js" and "browserDetect-min.js". Named the class for IE8

Normal class (which works in IE7)
#wp_ft_footerBG {
position: fixed;
height: 30px;
margin-left: 0px;
margin-bottom: 0px;
font-size: .9em;
background-image: url(../../Resources/Images/wp_footerBG.gif);
background-repeat: repeat-x;
min-width: 700px;
bottom: 0px;
}

IE8 specific classs:
.browserIE8 #wp_ft_footerBG {
position: fixed;
height: 30px;
margin-left: 0px;
margin-bottom: 0px;
font-size: .9em;
background-image: url(../../Resources/Images/wp_footerBG.gif);
background-repeat: repeat-x;
min-width: 700px;
bottom: 0px;
width: 100%;
}

The difference between both is the width. But I don't see it solving my problem.

Bo Frederiksen @ 31 Jul 2009 3:39 PM

Line 7 could be a little neater:
$.browser.chrome = /chrome/.test(userAgent);

I wonder if this script could be done server-side. That would eliminate the need for loading two javascript files. And no flash problems to deal with. Most public websites doesn't seem to require jQuery on every page.

Max Solaris @ 1 Aug 2009 1:12 AM

Great Work -- this is really cool and further keeps me happy with jquery

Roger @ 3 Aug 2009 9:38 PM

Brilliant! I rarely need to use conditional comments, but this makes the CSS much easier. Nice work.

Brad @ 18 Sep 2009 3:15 PM

Do you plan on modifying this with the new JQuery as JQuery.browser is technically deprecated in favour of browser feature detection. I'd be interested to see if this is difficult?

Brandon Buttars @ 20 Nov 2009 4:39 PM

Awesome. This is the perfect code! Most detectors out there I've found don't detect Chrome, this snippet covers them all. I posted your code to snipplr.com too with a link back to here. I'm starting to see a bunch of differences in the way Safari and Chrome are displaying things in CSS and this code will help me target them specifically. The CSS hacks usually all end up affecting everything webkit which is kind of annoying. Jon you have become my hero for a day.

Bill @ 30 Nov 2009 8:22 PM

Not being a programmer and having my IT go move on to (what he thinks are) "Greener Pastures". I need some help.

Would I "Cut and Paste" the Browser Detector.js in to my main.css file? If so, where in that file should it go?
If not, where should it be installed?

Thanks, very much for any help.

Bill

Jamy @ 17 Dec 2009 10:51 PM

This is really cool, Thanks!
Would it be possible to detect whether it was firefox 3.0 or 3.5?

Kai @ 24 Feb 2010 2:10 AM

Neither script seems to work :-( Is there a live demo somewhere?

Harry Moore @ 24 Feb 2010 3:15 PM

Not seeing this work in Chrome which is causing me a slight issue, the class is being added in FF which looks great, IE is fine, but this is adding nothing to Chrome.

Mikael @ 2 Mar 2010 9:04 AM

It does not work for me.
I have placed two two .js files in the head of the page.



I wish to change a few lines in the following class:

body {
margin-top: 0px;
background-color: #A5A5A5;
background-attachment: scroll;
background-image: url(../styleImages/backgrounds/pageBg.jpg);
background-repeat: repeat-x;
background-position: top;
/* margin-left: 0px; */

}

.browserIE body {
margin-top: 0px;
background-color: #A5A5A5;
background-attachment: scroll;
background-image: url(../styleImages/backgrounds/pageBg.jpg);
background-repeat: repeat-x;
background-position: top;
margin-left: 300px;

}

I tested in IE v8 and Firefox 3.5 but it shows the same result.


Btw, I am using Cubecart v3.

I would be happy if someone could give me the right direction to solve this issue.
Regards,
Mikael

Ryan Sadwick @ 5 Mar 2010 1:30 AM

The jquery browser detection script works perfectly. Also, thanks to the comment by Karl Swedberg, revealing how to avoid the flash of unstyled content.


add your comment