Integrated Web Design: Strategies for Long-Term CSS Hack Management
Date: Jun 25, 2004
Hack management? What the heck is that? Well, if you're working with CSS and you're trying to address the oddities of multiple browsers, you simply cannot achieve consistency between those browsers without employing hacks.
So, how is a hack defined? That's another issue up for debate, but for the purposes of this article, a hack occurs any time we use an element, property, or other syntax within a language for a purpose other than its intended application.
Depending upon your site needs, you might be one of the lucky few who never has to employ a CSS hack, but I doubt it (at least for now and at least if you're working with CSS and addressing numerous browser concerns). So, this article will provide you with a variety of hacks as well as offer some incredibly intelligent strategies for managing your hacks and ensuring that they quickly disappear when you don't need a given hack anymore.
After all, we really don't want to use hacks. The biggest hack of all in web design has been the use of tables for layout, and we all know what a mess that's gotten us into.
Hacking Strategies
Before you get hacking, you'll want to know a bit about how to effectively use hacksor not use them. This section will help you set up your strategy before using a hack.
General Tips
Here are some tips to ensure that you'll manage your hacks with expertise:
Don't need them? Don't use them. If you know your target audience and browsers well enough that you don't have to support especially problematic browsers, don't use hacks. A good example is if you're in an intranet situation and have total control over the browsers in use.
Know CSS and know your hacks. Although this article will go a long way toward helping you understand the how and why of hacking CSS, knowing CSS itself and how it works in various browsers will be one of your first-line defense systems in ensuring that you use only what you have to use for as long as you have to use it. So many problems arise out of copying and pasting markup and CSS it's not funny! Sure, we all do it, but for professional applications, we have to know what it is we're working with to optimize it and use it as properly as possible.
Comment, comment, comment. Although it's always a great idea to adequately comment your markup and CSS, if you're working with hacks, be sure to comment the hack. This helps co-workers as well as those surfing around swiping your CSS to understand what you're doing and why. If the hack has a specific name, make sure to name the hack in your comment, such as
/* Box Model Hack to correct Box Model implementations */
After you determine that you will require hacks and are committed to managing them effectively, you're ready for the surgical correction strategy.
Surgical Correction Strategy
This is a strategy I heard Tantek Çelik (perhaps the creator of more CSS hacks known to humankind than anyone) discuss at a recent SXSW panel on CSS. As a developer of browsers as well as a CSS expert, Çelik has had to manage browser inconsistencies with CSS for a long time. Although not a proponent of hacking by choice, Çelik realized that we need to provide options to use CSS as effectively as possible, but removing those hacks as soon as they are no longer needed will enable us to move forward without being encumbered by them.
This strategy makes your hacks easy to manage by placing the CSS syntax in unique files. Then, you can import them into your main style sheet using the @import property. By doing this, you import your hacks into the main CSS rather than actually coding them in the main CSS itself. Let's say you've got a document, hi-pass.css, in which you have the syntax for the hi-pass filter (discussed later in this article). The hack is resident in a file all its own and then imported into the main sheet:
/* importing hi-pass filter */ @import "hi-pass.css";
After you determine that the hack is no longer necessary, you simply delete this syntax from the main sheet, delete the hi-pass.css file, and you are then that much closer to a hack-free environment with very little muss and fuss.
Figure 1 illustrates the surgical connection strategy.
Figure 1 Surgical connection strategy
Hacks and Workarounds
Now that you have some good strategies for managing hacks over the long term, it's time to take a look at some popular hacks and workarounds that you may want to use to manage browser issues.
Box Model Hack
As you might know, IE for Windows has incorrect implementation of the Box Model. (The Box Model is a visual model upon which CSS relies to effectively style element boxes.) In the Box Model, each element creates a box that can then be managed using CSS to style its width, height, position, borders, margins, and padding.
Let's say you were to begin with a simple box, such as this one:
#content { border: 10px solid black; padding: 10px; width:300px; }
In browsers with proper implementation of the Box Model, this would be interpreted by adding the borders and the padding width-wise as follows (you wouldn't add the bottom or top borders and padding because you're concerned only about width in this instance):
Left border 10px + Right border 10px + Left padding 10px + Right padding 10px + Box width 300px = 340 pixels total width
However, improper box model implementations will place the border and padding inside the width of the box, resulting in those widths being subtracted:
Box width 300px - Left border 10px - Right border 10px - Left padding 10px - Right padding 10px = 260 pixels total width
No small difference! With this kind of significant discrepancy, you see that some kind of hack or filter is necessary to make sure that your visual layouts are as consistent as possible.
The Box Model hack taps into a parsing bug in those problem browsers to work around the problem. Using the voice-family property, you'll first define the true width, insert the hack, and then apply a width that gets overridden and tricks the problem browsers into using the correct width of 340 pixels:
div.content { width: 340px; voice-family: "\"}\""; voice-family: inherit; width: 260px; }
Although a feature known as DOCTYPE Switching corrects this problem in IE 6.0, earlier IE versions will misinterpret your CSS badly enough to cause significant layout discrepancies (hence, this hack and later filters that have emerged as alternatives to it). DOCTYPE Switching occurs only when documents are marked up with correct DOCTYPE declarations.
NOTE
Please see "CSS: Beyond the Retrofit" for more information on DOCTYPEs and switching technologies.
Interestingly, using the Box Model hack, CSS would routinely fail the W3C's CSS validator despite the fact that even if it is a hack (again, something being used for a purpose it was not intended) doesn't mean that the syntax has an error. Public commentary encouraged the W3C to correct the validator to support it, so now you can use this hack without worrying about invalid CSS.
Horizontal Centering Hack
Although CSS offers a perfectly acceptable means of centering elements horizontally, browser support of the correct means is inconsistent.
The correct way to horizontally center any element is to use the margin property and set left and right values to auto:
div#content { margin-left: auto; margin-right: auto; }
This works in some browsers, but not in others. Another means of centering is to use the text-align property for a given element, which in many browsers will align the element as well as the text:
div#content { text-align: center; }
Because neither the correct way nor the text-align method works in all browsers, you'll want to combine the technique:
div#content { margin-left: auto; margin-right: auto; text-align: center; }
And this creates your horizontal center hack. Of course, because you now ask that all text be aligned within the element, you'll have to be sure to create rules that overwrite that:
div#content p { text-align: left; }
This makes sure that any paragraph within the now-centered content division will align properly.
@import Workaround
If you are attempting to gracefully degrade your CSS layouts and have to support Netscape 4.x version browsers, you may want to consider using the @import workaround as a solution to ensure that your site degrades the way you want it to.
Netscape 4.x versions have partial support for CSS. Layouts are especially prone to breaking. But, Netscape 4.x version's impartial CSS support is a partial blessing because there's no support for the @import rule. This allows designers to split their CSS into two style sheets:
Site-wide styles (linked). This style sheet will contain font, color, and other CSS properties used for just about everything but layout information.
Layout styles (imported). This style sheet contains the layout information for the site.
So let's say you have a site-wide style sheet (styles.css) and a layout style sheet (layout.css), split up in the way described above. You can then link to the styles.css, but import the layout styles using @import:
<!-- begin link to design styles for screen --> <link rel="stylesheet" type="text/css" media="screen" href="styles.css" /> <!-- begin @import for layout styles --> <style type="text/css" media="screen">@import "layout.css";</style>
Because Netscape 4.x can read the linked style sheet, some style will be applied to the page. But because it cannot read the @import rule and therefore any styles associated with it, the layout style information is ignored, leaving a more gracefully degraded site.
Filtration Systems
Filters are really just hacks with a fancy name. Specifically, a filter filters out other browsers so you can create a style sheet to hack for a specific browser or browser set only.
High Pass Filter
This filter is a means of filtering CSS rules to a variety of browsers while ensuring that unwanted styles don't get maligned by those problem browsers. The high pass filter takes into account the idea that we want to move toward as hack-free an environment as possible, but still be able to deliver CSS to browsers in some controlled way.
So while we're still hacking away, we're moving those hacks out of the main HTML and CSS documents.
In the case of the high pass filter, you'll first create a linked style sheet with @import rules written to trick browsers without proper implementation:
<link rel="stylesheet" href="highpassfilter.css" />
This style sheet itself contains two rules:
@import "null?\"\{"; @import "highpass.css";
The first rule is a trick using the same technique in the Box Model Hack to throw off those browsers that can't parse the style value. The second style sheet, highpass.css, will contain your actual styles, which will then be imported into the style sheet and carried over into the compliant browser via the link, leaving the hack separate from the main HTML document and separate from the clean style sheet.
The Mid Pass Filter
This filter allows you to provide a style sheet for versions IE 5.x of Windows without including any other browser. This means you can fix the Box Model and other problems in IE5.x versions without adding those hacks directly to your main documents.
In the case of the mid pass filter, you'll trick the browser using the @media rule with a value of TTY.
Consider the following:
@media tty { i{content:"\";/*" "*/}} @import 'midpassbefore.css'; /*";} }/* */ p.test { color:green; padding:1em } strong { color:black; background:#fff; padding:0 2px; margin:-2px } @media tty { i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";} }/* */
Because of the filtration process based on bugs with the @media rule, both the first and last @media tty rules will be seen only by IE 5.x browsers for Windows and ignored by all other browsers. The style information in the middle will be interpreted by all browsers.
IE 5.0 Windows Band Pass Filter
This filter works on the same premise as the mid pass filter, but is specific to IE 5.0 for Windows only. Every other browser before or after is filtered out:
@media tty { i{content:"\";/*" "*/}}; @import 'ie50winbandpassbefore.css'; {;}/*";} }/* */ p.test { color:green; padding:1em } strong { color:black; background:#fff; padding:0 2px; margin:-2px } @media tty { i{content:"\";/*" "*/}}; @import 'ie50winbandpassafter.css'; {;}/*";} }/* */
So in this case, the styles you place in an imported style sheet using the @media tty rule and the associated syntax will be picked up by IE 5.0 only:
i{content:"\";/*" "*/}}; @import 'ie50winbandpassbefore.css'; {;}/*";} }/* */
Any other CSS in the sheet will be picked up by any browser that supports those styles.
IE 5.5 Windows Band Pass Filter
By now, you have the hang of what these filters are doing, and in this case you're filtering for IE 5.5, specifically. Anything you put into the imported style sheet using the IE 5.5 filtration syntax will be used by IE 5.5 only, with no other browsers able to access that style.
@media tty { i{content:"\";/*" "*/}}@m; @import 'ie55winbandpass.css'; /*";} }/* */
Any additional normal style information within the style sheet will be picked up by those browsers supporting the styles therein, but the styles in the ie55winbandpass.css file is be picked up only by IE 5.5.
NOTE
All the filters in this section were developed by Tantek Çelik and are distributed freely with attribution under a Creative Commons license, http://www.tantek.com/CSS/Examples/.
Hack it Up, Take It Home
If you need to hack, hack away. But doing so using good strategies such as the surgical correction strategy, using only those hacks you truly need, and staying on top of understanding the languages with which we work will make all the difference in the quality and consistency, and ultimately the portability of your CSS-designs.