by Kyle Weems 21.January 2008 09:12
As further proof that web designers may need a tad less caffeine in our diet, things got a bit interesting last month when Håkon Wium Lie (no, I don't know how to pronounce it either), the CTO of Opera Software and "father of CSS" posted an open letter regarding Opera filing a complaint against Microsoft with the European Commission to coerce MS to use open Web Standards in their browser. Andy Clarke, among others, decried this action as contributing even further to unstablizing what he terms the CSS 'Un'working Group and its glacial progress in getting anything done with CSS3. As is the case when a popular figure drops a big rock in a pond, there were waves. Some, like Daniel Glazman, pretty much unloaded both barrels at Andy (for the record, I think he needs to rethink the term 'deep sense of politeness' in context to what he wrote). Others were more measured and thoughtful in their responses. Mr. Clarke seems to be of the overall opinion that big changes need to happen to make further progress with CSS happen at a pace that'll impact our lifetime. I'm inclined to side with him on this one. There's some really exciting properties in the CSS3 spec that, if implemented across all browsers, would be wonderful tools in cutting down the development time on many projects I work on.
I'm not, however, holding my breath. Even IF CSS3 properties got greenlit faster (and it's a vague process that I don't really understand anyhow), I doubt Microsoft is going to be any better at implementing them faster than CSS2, which as of IE7 still doesn't work correctly without various workarounds on their browser (although the news that IE8 won't have the dreaded 'hasLayout' structure makes me at least hopeful).
However, that doesn't mean we need to wait until 2054 to make use of at least some CSS3. Browsers like Firefox and Safari have already implemented some of the properties (albeit with proprietary names), and some impatient people have come up with Javascript solutions that can be applied to IE, the hunched over juggernaut that crouches on the world of web development like a giant buzzkill.
In particular, the CSS3 properties I find the most interesting are those related to the multi-column module. A List Apart, waaaay back in 2005, had a nice article that introduced the wonders these properties would bring us. This also linked to a nifty javascript technique that you could use to support multi-column properties on any browser in the interim until they were officially implemented.
Interim is a really nice word for it. Three years later, only Firefox and Safari have introduced support for the feature, and even then with their own proprietary prefixes on the property names. Which means, once again, 80% of the web's users can't see such a feature without some javascript.
Well, I for one am tired of waiting. There's plenty of reasons from a readability standpoint that narrow columns are so bloody useful, and webpages aren't getting any thinner, so we need an easy way to get that text to wrap vertically in certain layouts, and we need it this century. Rather than inventing some torturous routine or tons of excess markup, using the CSS3 properties like "column-count" and "column-gap" seem like the perfect solution to me.
Now if only all the browsers were doing this.
However, they aren't. So what I'd like to do is slightly (ever so slightly) update the aforementioned Javascript technique for multi-column support (created by Cédric Savarese), changing it to take into account Safari and Firefox's abilities in the area. I don't like using Javascript for presentation unless I have to, I'm going to use Mr. Savarese's javascript, but with a slight modification so that when the visitor is using Safari or Firefox (of the appropriate versions), the CSS handles the layout, but if that's not the case, then the script wields its scapel and forces the columns into place itself.
On my example page (with its hideous red background) you can see the results of my tinkering. I've tested it on IE7, IE6, Firefox 2, Safari 3, and Opera 9, but it should work for most modern browsers. I'm not making any promises for handheld browsers or ancient Netscape versions, mind you. How this whole thing works is as follows.
1. The CSS - Savarese's script accepts four of the CSS3 multi-column properties: column-count, column-gap, column-width, and column-rule. There are some limitations in how you can use the styles (take a look at the link I provided to his page up above), but overall they work like presented in the CSS3 specs. Firefox and Safari support these, but with '-moz-' and '-webkit-' prefaces, respectively. So I'll need to include all three versions of the styles in my sheet. As support increases, and the two browsers drop their specific prefaces, we can just drop their versions of the properties in the file, leaving the official CSS names.
2. The HTML - Because of some limitations in the Javascript, we're going to have some issues keeping any styles OTHER than the column styles applied on an element that's being parsed by the script to support the columns (it breaks the element in the HTML into multiple elements, often resulting in the selectors no longer applying). So we'll need to do a teensy bit of extra markup and make sure that there's a seperate element wrapped around our text that'll hold just the column styles, and and all the other styles apply to a parent of that element. THat's why, when you examine the source code, you'll see the div with the class "columns" wrapped around our paragraphs, instead of the div marked "content" getting the column styles.
3. The Javascript - This is straight from here, with only a small modification to add the support for Firefox and Safari's implementations of the styles. The changes are as follows:
On the page, the following line at the very bottom of the script:
var css3MC = new CSS3MultiColumn();
This is used to create and run the object that'll parse the CSS sheets (note, only sheets linked in your HTML above the link to the script, and inline styles don't work with this) and then cut the HTML up as needed to create the column effects. Because we don't want to run this on Safari and Firefox, I've replaced that with the following.
function runScriptIfNeeded()
{
var runScript = true;
// Check for Firefox 1.5 or greater
if(navigator.userAgent.indexOf("Firefox")!=-1)
{
var versionindex = navigator.userAgent.indexOf("Firefox") + 8
if (parseFloat(navigator.userAgent.substring(versionindex, versionindex+3))>=1.5)
{
runScript = false;
}
}
// Check for Safari 3 or greater
if(navigator.userAgent.indexOf("Safari") != -1)
{
var versionindex = navigator.userAgent.indexOf("Version") + 8;
if(parseFloat(navigator.userAgent.substring(versionindex,versionindex+3)) >= 3)
{
runScript = false;
}
}
// run script if needed
if(runScript)
{
var css3MC = new CSS3MultiColumn();
}
}
runScriptIfNeeded();
This uses browser 'sniffing', which is a technique most of the time you want to avoid. The premise is that you don't want to rely on browser sniffing to work, since in the future it may fail to detect a specific browser that doesn't use the same nomenclature with the javascript 'navigator.userAgent' code, and thus things could break. In this case, it's less of a concern. It's only trying to find certain version numbers (or higher) of Safari or Firefox, and if they exist, it won't run the script. So if a future browser comes out (say, of Firefox or Safari) that it fails on the detection with, then it'll just run the script, which will at least render the site as we desire (even if it's unnessecary). But it's fair to warn that this is a technique you don't want to use too often.
What the runScriptIfNeeded function does is as follows.
First, it uses navigator.userAgent to see if it's being ran in either Firefox or Safari. If so, then it parses the navigator.userAgent string to determine the version number (depending on the browser, the position of this number in the string can vary, hence the substrings that are looking in different spots). If in either case the version is high enough to support the column styles, then it sets the variable runScript to false. If, at the end, the runScript variable is still true, the script runs, parsing the CSS and forcing the HTML to comply to the columns itself.
Do we need to make sites with multiple columns for our text? There's a lot of debate on that fact, with quite a few people saying no. But studies do show that there's an optimal width that people read comfortably at, beyond which eye strain or a lack of interest kicks in. With monitors getting larger and larger, columns will be a key technique in keeping the pages readable for our visitors. CSS3's multi-column properties will be a huge aid in accomplishing that. I don't think that every design needs or even desires multiple columns. But there's definitely a place for them, and as web designers we'll want this tool in our box for when the need arises. But until CSS3 actually becomes a widespread reality, we're going to have to rely on our own solutions in the interim.
Here's hoping that the interim isn't much longer.