July 5 2009
Everyone thinks that the major problems of CSS are mostly due to incompatible browser implementations but that's not quite the full story. It can be hard to see how cascading style sheets are not necessarily a good fit for the problems they are supposed to solve, perhaps in part because it's been such a long hard road for web developers to get to where we are now with web standards. But with more experience working on large and complex layouts, many designers do start to question whether CSS is right for the job.
The major source of problems is that CSS lacks structure - it is just a syntax for applying rules to arbitrary DOM elements. Everything exists in the global space, there is no inbuilt notion of modularity. CSS is supposed to be declarative, yet the order in which things are declared can have a significant effect. The solution is usually to break stylesheets into multiple files as a de-facto form of modularity. But visual logic is not something that can be easily captured by declarative rules. What really bites CSS coders is the tension between general and specific application - redundancy vs dependency. When you take a general approach to writing CSS code, a whole bunch of exceptional cases will pop up that usually require messy special cases and a lot of duplicated information to accomplish. When you take a specific approach, it is usually too specific, and you end up with massive long selector lists that are brittle and inflexible when new HTML elements need to share the styles. Either way, the vast majority of CSS code that I have seen (and believe me, I have seen a lot) is bloated, imprecise, and nearly impossible to understand without reference to the various possible combinations of HTML that it is expected to apply to. Reuse is not a concept that works in CSS.
There are ways of writing well structured and modular stylesheets but it's uber difficult, and with many visual designs, the basic rules of the format lead directly to situations where it is simply not possible to develop code that follows a clean and maintainable pattern. In most programming languages, you could look at clumps of duplicated code and immediately see how they could be simplified: for instance, using indirection to wrap common operations in separately defined functions. With most uses of CSS, there is no way you can look at the code and see what it is doing.
The goal of CSS is to separate content from presentation which is of course one of the most important aspects of modern web development. But that seems to be all that CSS does. There are no abstractions to help coders deal with eliminating repetition, no affordance for the requirements of graphic designers (such as common grid systems or height based column patterns) and no readily available tools or utilities that allow coders to optimize redundancy and fold repeating information into atomic units. All of these problems can easily collide, turning what should be a straightforward and logical visual structure into a monolithic mangle of unstructured madness. Even stylesheets for relatively simple layouts can stretch into thousands of lines of code. And this is not just talking in the abstract. I've seen it happen in the real world. Over and over and over again.
I'm not saying that flexibility is a negative thing - CSS is extraordinarily malleable and powerful, and is a great asset to have at one's disposal. I'm simply saying that the structure of CSS itself is one of the major things that prevents us from being able to easily develop clean and maintainable websites. It's not a problem with browsers, it's a problem with the format itself.