Cross-Browser Development Tips: Part 1 - CSS

Did you know people still use Internet Explorer 8 (IE8)? As part of Tinfoil’s recent major redesign, which required a complete front-end rewrite, we had to make a firm decision about which browsers, and which versions of those browsers, to support. Two of the main goals with the rewrite were to replace as many images as possible with CSS and HTML (buttons, arrows, etc.) and move most of the interactions and navigations from full-page refreshes to dynamic pages with AJAX. According to our analytics, 2% of our traffic comes from IE8 and above. The rest of our traffic comes from browsers that auto-update to their latest version and are modern enough to support all of the features that we want.

Visits by browser

In a perfect world, we would code to the standards set by the World Wide Web Consortium (W3C) and call it a day, resting assured that every browser would render our application identically. In practice, however, standards can take years to become standard, and old browsers will always have missing or broken features. Yet, we as front-end developers have to take care to ensure that our application works for all of our users. Given this, and the fact that people still use IE8 and above to use our application, we made the executive decision to support every browser back to Internet Explorer 8.

With our redesign now out in the wild, I’d like to take this opportunity to share the most important lessons we have learned about the wild world of cross-browser front-end development, and what it’s like to write code that works on a browser that was released in 2009 and last updated over three years ago.

Test, test, and test again in IE8

Initially, I thought I could take the lazy route. I’ve tried many browser emulation tools and IE8 compatibility testing frameworks in an effort to fulfill my goal of cross-browser testing without having to install Windows XP (or worse, Vista). These all have their advantages (convenience, cost, etc.), but nothing beats the real thing. Even IE9’s Compatibility Mode renders pages slightly differently than pure IE8. Get a virtual machine or a real PC, install Windows XP, and make sure that you do not upgrade IE past version 8. Whenever you test any new piece of interface functionality, fire up your Windows XP machine and test it in IE8, and incorporate this process into your normal workflow. The initial cost of setting up this kind of environment may be high, or not, but overall it is a real time-saver.

Start your CSS with a browser reset stylesheet

All browsers have sensible style and layout defaults. However, not all rendering engines have the same defaults. One browser might decree that the body tag shall have a 8px margin (the current de facto standard), another might insist on 10px. Fun fact: IE7 actually uses a 15px top/bottom margin and a 10px left/right margin on the body element by default.

Although you, as a web developer, have no control over which browser the user chooses, it is your job to ensure that your site layout is consistent across all of them. That’s where a browser reset stylesheet comes in handy. The idea behind a browser reset stylesheet is to put you in control of the default style of all elements. Instead of relying on an 8px body margin on most browsers, you can rest assured that all body tags will have a 0px margin, or whatever you decide. A really minimal starting point for a reset script may look like this.

* {
  margin: 0;
  padding: 0;
  border: 0;

Having this snippet of CSS run before all other stylesheets enables you to override any element properties you desire, knowing that anything you don’t override will at least be look consistent on all browsers.

Use vendor prefixes and fallbacks for CSS3 properties

Want to use a sleek CSS3 gradient? How about some rounded rectangles? Since W3C standards are constantly evolving, it is important that you ensure that your styles have sensible fallbacks for when a browser doesn’t support a CSS property. Older browsers will understand those fallbacks and skip the code it cannot understand, while newer browsers will understand both the fallbacks and the newer properties. For this to work, the fallbacks must appear immediately before the new properties in your CSS so that newer browsers prefer the newer properties.

It’s also just as important to use the various vendor prefixes for browsers that have their own, work-in-progress version of the standard. The correct way to use a CSS3 gradient is to list all of the vendor prefixes first, and lastly end with the W3C standard gradient property. Older browsers that only support their own vendor prefixes will use those, and those browsers that have implemented the standard will prefer that, since it is listed last. The following is a table of vendor prefixes for each of the popular browsers.

Safari, Chrome -webkit-
Firefox -moz-
Internet Explorer -ms-
Opera -o-

The following code may look ugly, but it is both backward- and forward-compatible. With pure CSS, this is how we define our blue gradients on our website.

/* IE8 fallback */
background-color: #2c99ce;

/* Vendor prefixes */
background: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #2c99ce), color-stop(76%, #459dcf), color-stop(95%, #74b9e0), color-stop(100%, #abe1fa));
background: -webkit-linear-gradient(bottom, #2c99ce, #459dcf 76%, #74b9e0 95%, #abe1fa);
background: -moz-linear-gradient(bottom, #2c99ce, #459dcf 76%, #74b9e0 95%, #abe1fa);
background: -o-linear-gradient(bottom, #2c99ce, #459dcf 76%, #74b9e0 95%, #abe1fa);

/* W3C Standard */
background: linear-gradient(bottom, #2c99ce, #459dcf 76%, #74b9e0 95%, #abe1fa);

We use a library called Compass, a Sass framework, that manages all of the vendor prefix stuff for us. All we have to do is keep the library up-to-date and the rest takes care of itself. I highly recommend it. With Compass, the above example is equivalent to the following.

/* IE8 fallback */
background-color: #2c99ce;

/* Compass mix-in */
@include background(linear-gradient(bottom, #2c99ce, #459dcf 76%, #74b9e0 95%, #abe1fa))

Target IE8 Specifically

So, you’ve tried the above techniques and you’re still having issues in IE8? You may have no choice but to use IE conditional comments. These hacks were voluntarily added by Microsoft to its browsers to help with targeting for IE’s inconsistencies. Luckily, they come in the form of HTML comments so other browsers will just ignore them.

<!--[if IE 8]>
<link href="/ie8hacks.css" rel="stylesheet" type="text/css" />

The simple ‘if’ statement above can be substituted for something more complex if you want to target all IE’s older than a particular version.

<!--[if (gt IE 5)&(lte IE 8)]>

I saved this technique for last because it should truly be your last resort. Most CSS inconsistency problems can be solved by using proper fallbacks and ordering your styles intelligently. The less code paths you have to support, the easier it is to keep your code stable.

Part 2 is going to be all about JavaScript, so stay tuned for that. For a preview of what we've built, fire up IE8, sign up, and play around.

Angel Irizarry

Angel Irizarry is the Software Samurai of Tinfoil Security, and a self-proclaimed software purist. All he needs to do his best work is a plain Linux machine with Git and Emacs installed. He loves everything about front-end development, like making pages interactive and super fast, even if that means digging in and optimizing some SQL. When he's not writing code, which isn't very often, you'll find him on his iPad scouring his RSS feeds for news and rumors of cool new gadgets.

Tinfoil Security Blog

Tinfoil Security provides the simplest security solution. With Tinfoil Security, your site is routinely monitored and checked for vulnerabilities using a scanner that's constantly updated. Using the same techniques as malicious hackers, we systematically test all the access points, instantly notifying you when there's a threat and giving you step-by-step instructions, tailored to your software stack, to eliminate it. You have a lot to manage; let us manage your website's security.