Clean CSS with Server-Side Browser Detection (1/2)

12 May


We all know that browser detection is bad, but let us look at some situations in which it may actually make sense; consider the following use cases:

  1. A specific (old?) browser needs special CSS styles to make things look/work acceptably.
    For example, Firefox 3.0 needs a negative margin on an INPUT field, to correct a bug.
  2. Certain content should be highlighted to give a visual clue that this content appears most appropriate for the visitor’s context, like browser and OS.
    For example, on a download page, you want to highlight a download for Mac OS X 10.6, because that is what the visitor appears to use.

Alternative Solutions

Typical solutions for these problems are:

  1. Use CSS hacks.
    Downsides: Unreliable, cumbersome and very hard to maintain.
  2. Use conditional comments.
    Downside: IE-only.
  3. Use feature detection. Various client-side frameworks support this, e.g., Modernizr or jQuery’s $.support.
    Downsides: Only works when JavaScript is enabled, only on more recent, capable browsers and may impact performance negatively on less capable devices.
  4. Use client-side browser detection. This has the advantage of being able to use more than only agent string; using navigator.vendor gives more reliable results.
    Downside: Works only when JavaScript is enabled and impacts client-side performance.

The Case for a Different Path

Excluding the first one, the mentioned solutions have their applications in modern web development. However, they certainly do not cover all ground. An alternative solution for the specified use cases would be welcome if it would comply with all or most of the following requirements:

  1. Reliable, e.g. should automatically pick up new browser versions.
  2. Easy to apply.
  3. Easy to maintain, i.e., no hacks like html>/**/body {}.
  4. Generally applicable, i.e., not specific to IE.
  5. Supports Progressive Enhancement, i.e., does not require JavaScript.
  6. Supports older and less capable browsers as well as more recent and capable ones.
  7. High performance, no time lost detecting features client-side on a limited CPU.

Server-Side Detection

An alternative solution is to have a server-side algorithm add some CSS classes to an element on the HTML document. For example, an iPad agent string could result in the following BODY tag being generated:

<BODY class="Device-Tablet Browser-Safari BrowserEngine-WebKit BrowserOS-iOS">

Let’s look at what such an approach has to bring to the table in terms of requirements coverage:

  1. Reliability: Fair, but not very good, since it relies on the agent string which is easy to spoof. On the other hand, newer browser versions are typically picked up either automatically or with a small update of the detection algorithm.
  2. Easy to apply: Yes, definitely: BODY.BrowserOS-MacOS .MacDownload {border: 1px solid green;}
  3. Easy to maintain: Yes, you only deal with (readable!) CSS.
  4. Generally applicable: Yes, only limited by what user agents offer (of course) and what the algorithm detects; but the algorithm can be extended.
  5. Supports Progressive Enhancement: Yes, perfectly. Works without a single line of JavaScript.
  6. Supports older and less capable browsers: Yes, the detection is done server-side, independent of the browser.
  7. High performance: Yes, server-side algorithm should take (way) less than 10 ms.

What’s Next?

Does it sound like there is a valid use case for server-side browser detection? Let me know in the comments! In a followup article, I will give some code samples.

Leave a comment

Posted by on 12 May 2011 in Web Development


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: