Thursday, February 05, 2009

CSS: the last word (I hope)

The flood of comments on my CSS versus tables rant has finally died down to a trickle. The final tally (as of 9 AM PST) was 146 on Hacker News, 198 on Rondam Ramblings, and a whopping 716 on Reddit (plus 921 karma points for Nicou). That smashed my previous record by a factor of four! There were also ~250 comments on my followup piece. Yowza! I wish I could say that I read every comment, but I didn't. After a while they started to get a little repetitive, and the ad hominem attacks in particular started to get annoying. But despite the fact that I didn't respond much because of the overwhelming volume, I did read a lot of them. And I wanted to thank everyone who commented, even the ones who attacked me. Notwithstanding accusations to the contrary, I did not write the piece as a publicity stunt. You will notice there are no ads on my blog, nor on my personal web page. [UPDATE: I've added a TipJoy button just to see what happens. Any money I make will be donated to charity.] I wrote it because I thought the CSS versus tables controversy could benefit from the injection of some actual data, and because I wanted to take a stand against what I saw as faulty arguments in favor of CSS. Nonetheless, as a writer it's always good to know that someone out there is paying attention, even if that attention is negative. So thanks to all of you.

I did want to take time to respond to some of the common themes that kept repeating themselves over and over in the comments. I doubt this will stop any of these memes from reproducing in the future, but everyone else is getting their two cents in so I figure I'm entitled.

Theme #1: CSS is hard, and you have no business expressing an opinion until you've paid your dues and spent five years learning all of the ins-and-outs.

I already addressed this point in a previous post but this theme kept showing up even in the comments to that post so apparently I was still being a little too subtle. I utterly reject this view, and not just when it comes to CSS, but in all aspects of life. This idea that only the experts have opinions worth considering is not merely wrong, it's corrosive. It is -- to cite but one example -- what got us into this economic mess. The idea that the crisis "could not have been foreseen" is absurd on its face. Not only could it have been forseen, it was foreseen. It was predicted at least as far back as 1992 and probably earlier than that. You don't have to be a rocket scientist nor an economist to see that if you spend more than you make, sooner or later you will wind up in trouble.

Likewise, you don't have to be a CSS expert to see 1) a lot of broken CSS on the web, 2) a lot of people tying themselves into knots trying to do conceptually simple things. You don't have to be an expert to know that if text is spilling out beyond div boundaries everywhere you look, and people are proving their CSS studliness by doing something as simple as a liquid three-column layout, something is wrong.

Now, tables are not perfect. Much of the criticism leveled at them is valid. But it is unsound reasoning to conclude that because tables have problems you should therefore use CSS. CSS has problems too. That makes the choice between tables and CSS a valid engineering tradeoff. My personal quality metric is that all else being equal the simpler solution wins. The situation could change as the technology landscape shifts, but right now, that calculus comes down on the side of tables. Reasonable people could disagree.

(BTW, if you are a fan of arguments from authority, you should keep in mind that just because someone chooses not to wield their credentials doesn't mean they don't have any.)

Theme #2: CSS does not really have the problems you think it has, you just need to study it more.

I anticipated this argument as well, but again people didn't seem to notice. I knew people would say this, which is why I used someone else's code to make my point. People still didn't get it. They attacked the code anyway and said that those people didn't know what they were talking about. Here's the thing: on that criterion, no one knows what they are talking about. There is not a single CSS-based solution to the "holy grail" problem that does not have some deficiency or other. The mere fact that people even talk about the "holy grail" in connection with CSS ought to tell you something.

I don't have anywhere near the time to deconstruct every putative solution to the three-column layout problem, so I'll pick just a few of my favorite examples. The first is ChristianZ, who I am choosing to pick on because his comments were particularly vituperative. He held out his website as an example of three-column layout in CSS. I must confess, I think his website is looks outstanding. Trick is, it's not done in CSS. Turn off Javascript and suddenly it doesn't look so hot.

The second is Matthew James Taylor's oft-cited solution. Once again I have to doff my hat to what is truly a heroic effort to rescue a hopeless situation. As a thought experiment you might want to ask yourself why it is that Taylor's solution (nor YUI grids, nor anything else) has not emerged as the definitive solution to the problem. If you can't come up with an answer, try this: take Taylor's "holy grail" solution and modify is so that the left and right columns are not always butted right up against the edges of the screen. (BTW, even Taylor's solution suffers from the ubiquitous CSS malady that text will spill out beyond the div boundaries if it's too wide to fit.)

Theme #3: CSS is not meant for dynamic content

This one I did not anticipate. It was not a common theme so it could be that the commenter was simply wrong. But I list it here just an case anyone else has something to say about it.

That's pretty much all I have to say on this. Thanks again to everyone who commented.


Unknown said...

Great writing, but I suspect you'll get flamed as usual :)

Anonymous said...
This comment has been removed by a blog administrator.
Ron said...

Not flamed, but spammed.

Robert said...

I've been struggling with CSS for years, learning the quirks of it.

I agree that CSS for some layout work is a steaming pile of poo.

It's really easy if you need a box in the bottom right corner or in some other location.

What's tough is exactly what you focused on which is the multi-column fluid/dynamic layouts.

Most of the time sites I develop don't have such layouts, but if I ever needed to do one, I'd try it first with CSS, but I wouldn't hesitate to use tables to make my life easier and to save a crap ton of time.

Still though, I'd only use it for that particular problem, and I'd still use CSS to position almost everything else there is.

By the way, I've now subscribed to your blog and your blog joins 75 other 'Coder' blogs that I follow with Google reader.

Mitch074 said...

Point #3 is bogus: CSS can deal with fluid content without any problem (however, how it is supported by the browser is another thing: IE 7, not 6 nor 8, will have CPU spikes and eventually crash in some cases).

now, the 'text will spill over if there's not enough room' thingy you assert is bogus too.

That's what the 'overflow' property is for. By default, text will spill over the box if it's not big enough. You can set it to 'scroll' to add scroll bars all the time, 'auto' to automatically add scrollbars if content happens to be too large (and the not-yet-standard-but-supported, set-for-CSS3, overflow-x and overflow-y give you more granular control).

No, the biggest problem with CSS is that the majority browser can't make head nor tails of it: IE 6 (and 7) have TERRIBLE CSS support: it's incomplete, what is there is buggy, and rife with proprietary options that other browsers don't often support, or that step upon the way it's declared in the standard.

This situation will be somewhat reduced with IE 8, which has very good CSS 2.1 support - in 'edge' mode.

Ron said...

> IE 7, not 6 nor 8, will have CPU spikes and eventually crash in some cases

That doesn't sound like "without any problem" to me.

> the 'text will spill over if there's not enough room' thingy you assert is bogus too. That's what the 'overflow' property is for.

What should I set the "overflow" property to so that I get a div whose width by default is a certain percentage if its container's width, but will grow if its content is too wide to fit?

> No, the biggest problem with CSS is that the majority browser can't make head nor tails of it

That's a pretty big problem. A show-stopper, in fact. (I actually don't think things are quite *that* bad. You *can* make CSS behave semi-reasonably, it just takes an awful lot of work at the moment.)

Unknown said...

Ron, I applaud both your arguments and your stoicism in the face of much bigoted abuse.

I am not sure that "CSS Wars" existed before your original post, but they certainly do now! This is actually all to the good, because you have brought out into the open some fundamental issues that _everyone_ has been glossing over for some time in almost evangelical zeal about the real capabilities of CSS.

I only hope that this debate reaches the ears of the apparently zombified W3C, because I am a firm believer in both the potential merits and the actual current flaws of CSS. CSS3 anyone?


Mitch074 said...


Point 1.
The IE 7 bug has a workaround and is, actually, difficult to hit: it requires an off-rendering window dynamic-sized element to not have a set height of any kind. I suspect it is actually an hasLayout bug introduced in IE 7, as it is gone in IE 8 Standard mode and isn't present in IE 6 (which doesn't deal with dynamic sized elements outside of Jscript).
This kind of behavior can't be done with a table, so it can't actually be used to recommend table-based layout. Or more interestingly, it can ALSO be triggered in a table-based layout.

Point 2.
For relative adaptive sizing, look up 'min-width' and 'max-width' - don't use 'width' here. Note: IE 6 will require 'width', since IE6's 'width' works like min-width, which isn't supported (!). This is a documented deviation from standards, specific to IE5/6, solved in IE 7. But, as said by many CSS programmers, IE 6 (and 7 in a lesser measure) need to be dealt with independently, be it in CSS, but also in HTML and ECMAscript.

For example, if you want a child container to have a minimum width of 60% of its parent's width, set its css as being min-width:60%; Just don't forget to give its parent a dimension, otherwise it will size relative to its grandparent etc.
Then, in order to fix IE 5/6, add a conditional comment pointing to a style sheet (either local or external) saying:
[!--[if IE lte 6]]
.myelement {width:60%}

The former is the recommended-by-MS, least intrusive method to fix IE bugs in a forward-looking manner - something that using tables can't guarantee. See later.

Point 3.
It's not a show-stopper: said majority browser is fixing itself, in fact, and working NOW to have a working 'pure' CSS version, with an extra 'fixes' stylesheet, will ensure that your layout won't need to be rewritten in 3 years.

If, for example, all browsers do decide that a table is a block element, not an inline-block element... Currently, that causes 'boom' in IE8, Firefox, Opera and Webkit in Standard mode (and whoever tries to program in Quirks mode must have masochistic tendencies).

So, your current tables-based layout is susceptible to go boom when browsers decide to implement tables and table elements as per the standard.

I'll take the following example: you create a 3 columns layout using a table, with the leftish column cell being set to 150px wide. During design stage, a 180px wide image is added to it, and contrary to what is expected, the column stretches to accommodate the image; then, text and menus are added, making use of the remaining space.

Unfortunately, browsers finally decide that table cells should behave like any other block element, and follow the CSS specs: by default, the content is shown but the container doesn't stretch to accommodate it: the image spills on the center column. Text above and under it, being inline, wraps - and gets all wonky, since it was typed for a 180px width and ends up inside a 150px wide parent.
The only practical solution in that case is to set a width to the column that matches its largest child's, and keep it current if said child changes (say, to an image that is 175 px wide...)
Or, you define your left column as having a min-width of 175px, overflow:hidden, a max-width of 30% (just to be thorough), and float it to the left. If you decide to not set its height, you can also make your main content text-wrap around it (something a table can't allow).

Currently, the only thing I really miss in CSS is the ability to set a size with a mix of units (in fact, the MS-proposed expression() 'value') or relative to siblings, without relying upon table-like markup. This, however, can be largely offset with some creative margin and padding use.

CSS3's "column"-related properties try to solve a problem that neither tables nor CSS2 address: how to set up the flow of elements in a single container (be it a table cell or a div) without having to 'hard-wire' column changes and page changes.
Look at it this way: what happens if you try to display your carefully set-up three-column-formatted text (one column is a table cell) with a font that has a very different font spacing, kerning and hinting? Say, you formatted your text so that column 1 and 2 ended on the same line count and with proper last line justification, in Arial, with subpixel-grid hinting.
Then, you show this page to someone using a Mac that defaults to Helvetica, with font hinting being done to a paper-like rendering (yup, Apple does printing).
Your layout is toast.