This article originally appeared in the Design & Usability Tactics newsletter.
CSS hacks are clever snippets of code that take advantage of an idiosyncrasy in the way certain browsers parse CSS code to selectively deliver different styles to different browsers. Invariably, designers employ these hacks to compensate for inconsistencies in browser rendering by delivering slightly different size and position attributes to the problem browser.
CSS hacks are also a response to the unfortunate reality of dealing with browsers that have flawed or incomplete support for CSS. Hacks can be effective tools for combating browser inconsistencies, but using them exacts a price in the form of cluttered and bloated CSS code, which can be hard to read and harder to maintain.
My own approach to hacks (and the approach that I recommend to anyone who will listen) is to avoid using them if possible. That may sound like an obvious strategy, but it's not always easy to follow. Hacks provide well-documented solutions to common browser-compatibility issues, so it's often tempting to apply the quick fix instead of searching for other solutions to the problem.
I have several reasons for preferring to shun hacks; some of them are theoretical and others are practical. First of all, every hack that I see in CSS code is an irritating reminder of the browser deficiencies that we have to deal with. It's also an admission that I couldn't find a more elegant cross-browser solution and had to resort to code trickery to single out a specific browser for special treatment. The practical reasons include objections to the added code required to implement the hacks and the time and effort that it takes to apply, test, and maintain them. The practical advantages of clean, uncluttered code are enough to justify searching for alternatives to using hacks.
I go to great lengths to avoid needing hacks, and I'm successful much of the time. That doesn't happen because of good luck or wishful thinking; it's the result of a deliberate effort and planning. Here are some things you can do to minimize the need for hacks:
- Avoid pixel-precise design: Develop a page design that has the flexibility to look good despite rendering differences in various browsers. You won't need to use hacks if your design can absorb browser inconsistencies and still have the desired effect.
- Adjust your design during coding: Often, the best hack is to redesign the page element so that you don't need to use a hack. This requires thinking of design and coding as parts of the same process and being willing to go through multiple iterations of the process to refine your design. It doesn't work if you approach coding as the task of precisely implementing a preconceived design.
- Work with what you have: Design within the limitations set by the scope of CSS tools that can work consistently and reliably in all major browsers. Avoid using selectors and attributes that aren't well supported by all major browsers. This approach limits your design options significantly, but there's a lot you can do within those limits. Embrace the challenge. It's a lot like a painter who deliberately chooses to work with a limited palette.
Selecting a hack
Despite your best efforts to avoid needing hacks, there may be times when there is no other way to achieve an acceptable result in today's major browsers. So, if you must use a CSS hack, your next challenge is how to minimize its undesirable impact on your code.
There may be more than one hack that can do the job. So, you need to select the one that is the simplest and most effective to use. The best hack is one that targets a problem browser precisely, and does so with the minimum of extra CSS code. A good hack is also one that you can live with over time as you return to your CSS code for future edits. (That last point is important because you're going to have to deal with the hack every time you edit your CSS code.)
I find that it's usually harder to use the hacks that rely on comment characters (and other similar character strings) embedded in a style. I have trouble remembering the precise syntax of the hack, and they often interact badly with regular comments. In contrast, other Web builders like hacks such as the IE5 Backslash Hack because it requires relatively few added characters, and it can target a specific browser precisely.
Personally, I prefer the Star HTML hack (using the * html selector to target Internet Explorer) and other hacks that rely on CSS selectors that certain browsers recognize or ignore. Somehow, it seems easier for me to remember that certain selectors work with certain browsers than it is to memorize arcane character sequences. I also like the fact that selector-based hacks are naturally compartmentalized, which makes them easy to identify, edit, and comment out for testing.
Your mileage may vary. The important thing is to be comfortable with the hacks you use because you're going to be working with them repeatedly.
Another consideration when selecting a hack is whether the resulting code will validate. As a general rule, you should avoid nonvalidating hacks because they prevent your CSS from validating successfully, and because you can't be sure how future browsers will respond to the code.
Hacks clutter your code, making it hard to read and maintain. The only way to avoid that problem completely is not to use hacks. However, you can fight back with good comments that document the hack and its purpose in your code.
When documenting hacks in your code, it's important to mark the start and end of the hack. You might also want to add a comment to mark any normal code that is related to the hack. All of this makes it easier to maintain the code and the hack. The comments also make it easier to find and remove the hack if it's no longer needed.
In a perfect world, all browsers would consistently support current CSS standards. In such a world, there'd be no need for hacks and we'd be free to write clean, uncluttered CSS code that would work reliably in all browsers. Unfortunately, we don't live in a perfect world, and hacks are one of the ways we have for dealing with the imperfections.