Dealing with CSS Incompatibilities and Differences

A simple tip on working around CSS incompatibilities across browsers without relying on CSS parser bugs...

CSS incompatibility across browsers is an all too familiar source of annoyance and frustration for anyone doing anything significant. Over time, I've come across several pages (for example, the box model hack page), and even books not just demonstrating, but recommending leveraging known CSS parsing bugs to define browser-specific CSS rules. I've never liked them, because they're unmaintainable, and frankly unreadable (understanding such style sheets first requires intimate knowledge of parsing bugs). An even bigger reason to try and avoid them is that potentially every new version of a browser is likely to invalidate some set of hacks that worked in the past... apparently as reported here, the "* html" trick doesn't work in IE7, as reported over here.

Here is an alternative technique I came across a while back when working with the live.com folks on Atlas... I think it works fairly well, and for its most appealing aspect... it doesn't rely on parser quirks. Lets say I had the following markup:

<html>
  ...
  <div id="foo">...</div>
  ...
</html>

Now say that I wanted to fill with a different color on Firefox vs. IE vs. IE7. I use this merely as an example to illustrate the technique; obviously the point is to use it for something that really does require special casing for different browsers.

I could now define the following stylesheet in order to make the div red in most browsers, yellow in IE browsers except IE7, and finally blue in IE7.

div#foo {
  background-color: red;
}
HTML.IE div#foo {
  background-color: yellow;
}
HTML.IE7 div#foo {
  background-color: blue;
}

The trick is to programmatically set the class attribute on the HTML tag based on the browser, and you're done. This is obviously where a little bit of javascript comes into play to do detect the browser along with its version and programmatically set the class value as appropriate. Obviously its pretty straightforward to implement this pattern. In Script#, I've tried to make this even simpler by baking in the functionality... Just use the following in your markup:

<html class="$browser $browser$major">...</html>

That's it! The Script# Application class on startup looks for macros such as $browser, $major and $minor, does some browser detection, and automatically initializes the class attribute for you. So on IE7, at runtime, you end up with:

<html class="IE IE7">...</html>

This would be fairly straightforward to incorporate into Atlas... er... the Microsoft Ajax Library as well. When doing this for real, you could use this technique to do all sorts of things - for example, account for differing box models, support or lack thereof of translucent pngs across browsers... and dealing with all sorts of real nuisances one comes across when working with CSS. Theres probably a couple of downsides I can see someone claiming. First it relies on Javascript. Secondly, a designer kind of person may or may not be used to the idea of script determining final look and feel. But like any other technique, it has its pros and cons... its something to keep in mind if relying on browser implementation bugs bug you :-)

Thoughts?


[ Tags: | | | | ]
Posted on Thursday, 9/14/2006 @ 11:45 PM | #Ajax


Comments

21 comments have been posted.

jesper hauge

Posted on 9/15/2006 @ 1:47 AM
I've relied on the "conditional comment" approach, the last couple of years. I think it is way more stable since it doesn't rely on hacks OR javascript. I've allways been able to make a stylesheet that functioned well in all up level browsers besides IE6, and then included an IE stylesheet after the inclusion of the main stylesheet like this.

<link rel="stylesheet" type="text/css" href="/css/Main.css" media="screen" />
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="/css/IE.css" media="screen" />
<![endif]-->

Only trouble is that i haven't found any good ways of using this approach when using themes in ASP.NET 2.0 apps :(

argh

Posted on 9/15/2006 @ 3:02 AM
Does it not seem a bit strange that you are recommending work arounds to deal with the failings of a product built by the company that you're working for.
I mean I realise that MS is a huge business but the fact that none of these hacks (conditional comments are really still a hack) would be necessary if IE was not such a CSS retard, and yes I am still angry that the lack of position:float and png transparency and all the other things that don't work but should makes web development so much more painful than it should be.
How many hours do people who work for MS waste coming up with solutions and workarounds for IE's failings when that time would be better spent by someone else simply fixing the damned thing.

However yes I think you make a very good point about not trying to code against bugs.

Nick

Posted on 9/15/2006 @ 3:36 AM
I've never understood what the issue is or why people use hacks on a .NET site.

Just use a dynamic stylesheet which outputs different CSS code to different browsers where necessary. A stylesheet doesn't have to be a .css file, it can easily be a styles.aspx page and therefore just as dynamic as any other webpage on your site.

No hacks necessary, and very readable CSS.

Joe Brinkman

Posted on 9/15/2006 @ 7:01 AM
I think I have to agree with argh on this one. But go one step further. It is not just Microsoft with the problem, but all of the browsers. I have plenty of CSS that works on FF but not opera. Or that works in FF but not Safari. It is absolutely wrong that I have to test my stylesheets on 7 or 8 different browsers (not to mention browser versions) and use various hacks just to get things to look correct.

I have long since given up on trying to bend CSS to my will and find it to be almost a complete waste of time. Until the major browser vendors decide to fix the problem, I will continue to shun tableless designs and stick to something that works - reliably.

Nikhil Kothari

Posted on 9/15/2006 @ 9:05 AM
Jesper - yes that is a viable approach as well. Works pretty well if separating out into multiple stylesheets is an option.

Argh - I am not trying to put down a browser, or uphold any particular browser implementation (I have a position on things that isn't so religious and no things aren't all one sided... but that is orthogonal to this post). This post is what I myself might do when trying to create a page; being pragmatic about the situation, dealing with it and moving on. Like Joe mentions, the need for special casing CSS should be avoided if possible... but when there is no other alternative, its nice to know there are ways to go about doing so without using on hacks.

Marc Brooks

Posted on 9/15/2006 @ 10:36 AM
That's a great approach... I talked about it in July here: http://musingmarc.blogspot.com/2006/07/browser-specific-css-clearest-way.html when Rafael Lima posted his CSS Browser Selector here: http://rafael.adm.br/css_browser_selector/

Tom Robinson

Posted on 9/15/2006 @ 1:27 PM
Surely the fact that this approach doesn't work unless JavaScript is enabled makes this extremely limited, if not a total waste of time. I certainly wouldn't use it for anything important like layout.

Matthew Hintzen

Posted on 9/15/2006 @ 3:36 PM
Nikhil,

You mention "Just use a dynamic stylesheet..." can you point me to somewhere that walks me thru a simple helloworld example (renders and applys different CSS from the dynamic stylesheet based on Firefox vs. IE, or any two browsers) for a .NET web app?

and I would have to whole heartedly agree with Joe Brinkman, it's not IE that is the bad citizen, ALL browsers at some point or another decide to "ignore" or act incorrectly.

Even the WC3 ignores its own "suggestions" from time to time. For example the latest html 1.0 transitional spec call for deprecating <td width="35"> in favor or <td style="width:35"> but if you submit the width="35" to the tidy engine, it doesn't warn you about this error.

What's worse, Firefox doesn't render the new method <td style...> correctly so you have to live with invalid html warnings (even if tidy decides to ignore that).

Oh well

Matthew

Nikhil Kothari

Posted on 9/15/2006 @ 6:10 PM
Tom, if you're already depending on Javascript for the rest of the page's functionality, then its certainly not a waste of time. If this is the only script in page, then this may not be a choice, depending on what configurations you need to support. Like I said, everything on the web has its pros and cons... pick the right tool for the job... there are no black and white rules.

Matthew... Nick (not me) referenced the dynamic stylesheet approach. I believe he is referring to producing the css content for your stylesheet dynamically on the server depending on browser detection. Not common, but again, it might be suitable depending on what you're doing. Having plain .css files does help the overall design experience, and is more performant than serving up the content by dynamically generating it.

Eric DG

Posted on 9/16/2006 @ 2:39 PM
If every webdeveloper for once and for all stick to the WC3 rules instead to the browser rules, the browsers will eventually follow because lot of pages will not render well. You can't blame browsers if every webdeveloper accepts the browser faults and make them theirs and eventually their co-webdevelopers.
You can begin with the new browsers like IE7 and FF2. DON'T FOLLOW THEIR RULES!

Jens

Posted on 9/18/2006 @ 1:46 AM
relying on the server to figure out what version the client is does not always work, i.e. no .net server knows that BonEcho or Minefield are Firefox (betas).

The conditional comments are a much better approach because they work on the client in exactly those browser versions where they are needed (MSIEx) and there is no way for the visitor to fake that.

Steven

Posted on 9/18/2006 @ 5:50 AM
The use of class, for the HTML tag, is invalid in XHTML.

Bill Ramirez

Posted on 9/18/2006 @ 8:02 AM
That is a genius solution, thank you so much for sharing. It is simple, elegant and clean, and more importantly, very easy to convey to the html and graphics designers.

Nikhil Kothari

Posted on 9/18/2006 @ 8:32 AM
Jens - the approach does not use server side code to detect the browser... it does it on the client. Conditional comments don't work across browsers... there are cases where you might need to special case something for Safari. If a user decides to fake the user agent, they are doing so at their risk of breaking the developer's logic.

Steven - perhaps you can use the same approach on another tag ... like BODY... seriously, web developers have enough to deal with. Being pragmatic is key to success whether it comes to this particular approach, or lots of solutions to other problems. How does whether there is a class attribute on the HTML tag or not affect readability, maintainability, ability to work across browsers etc. i.e. the meaningful set of things that a standard provides for? If you had included that information along with your note about it being invalid, it might have been something to think about...

Marchu

Posted on 9/18/2006 @ 10:20 AM
[quote]If every webdeveloper for once and for all stick to the WC3 rules instead to the browser rules, the browsers will eventually follow because lot of pages will not render well. You can't blame browsers if every webdeveloper accepts the browser faults and make them theirs and eventually their co-webdevelopers.
You can begin with the new browsers like IE7 and FF2. DON'T FOLLOW THEIR RULES! [/quote]

And you think, they gonna pay me, for a website/app, that doesn't work under IE7 and FF2???
I be on bread and water then...

Steven

Posted on 9/19/2006 @ 5:45 AM
Nikhil,

Of course using the class attribute on the HTML tag doesn't affect the issues that you listed (or at least not that I know of) but just because you can use it doesn't mean that you should. And yes, the BODY tag would have been a better tag to use...

For what it's worth, I actually like the concept.

Brennan Stehling

Posted on 9/19/2006 @ 10:03 AM
CSS is not so far. I find that I can code cross-browser CSS first and then make minor tweaks for variant browser adjustments with minimal effort. But I try to avoid the complex uses of CSS which just dramatically increase the work necessary to pull it off.

cowgaR

Posted on 9/20/2006 @ 10:06 AM
I am too for conditional comments, nowadays all I care is IE and its bugs, Firefox and Opera 9 are almost "there"...

jesper hauge wrote
"Only trouble is that i haven't found any good ways of using this approach when using themes in ASP.NET 2.0 apps :("

- use a StyleSheetTheme web.config property instead of Theme property and you're fine. It will aply theme styles _before_ your conditional comments...

Greg

Posted on 10/2/2006 @ 11:26 PM
Just a quick word on the "Dynamic CSS" aproach. What I have used to a fairly high degree of success, and without annoying my "designers" was a blend between the Dynamic and Static CSS files. What I get them to do is to design the CSS files for each browser (IE, Safari, FF, & what not...) Each of these is a separate file, being produced for a specific browser. Once I have that, I use the server side script that includes the appropriate CSS.
It's kind of a nag to maintain, since any aleration has to be made on all CSS files, but, you'd have to test on them anyway, and probably most alterations would result in having to rewrite CSS for each browser, so....

This does solve some of the problems I've been reading about here, and it does not rely on things like Conditional Comments or Javascript.
Hope this helpls anybody out there....

Susan Warren

Posted on 10/20/2006 @ 9:47 AM
I've written about the approach we used for styles in WindowsMarketplace.com, which supports IE6, IE7 and FireFox 1.5+: http://vertigoblogs/swarren/archive/2006/10/20/3963.aspx. The approach Nikhil describes is fine for small projects, but IMO it's hard to maintain for a project of any size: the CSS file sizes get too big to maintain effectively. I personally favor IE conditional comments to include IE-specific stylesheets as needed to override a "standards" style sheet authored for FF (yep, I know FF is not completely standard either but it's much closer). That way you write 100% of the CSS for FireFox, with a 25-50% delta for IE6, and 5% delta for IE7. By cascading these, you can get a lot of reuse between the versions. Our team found it was more maintainable than complete versions for per browser. Best of all: it's script-free and hack-free.

If you use the cascading approach, an essential tool for is Firebug. It allows you to highlight an element in the rendered page and see the file names and line numbers of the style definitions applied to the element. https://addons.mozilla.org/firefox/1843/

/wave Nikhil :-)

~Susan

Susan Warren

Posted on 10/20/2006 @ 9:52 AM
Bah, bad link above. The public link is: http://blogs.vertigosoftware.com/swarren/archive/2006/10/20/3963.aspx. Need more coffee. :)
The discussion on this post has been closed. Please use my contact form to provide comments.