CSS Variables Are The Future

or: “Reports of the Harm Caused By CSS Variables Are Greatly Exaggerated”

To say that CSS is abominable isn’t controversial. The implementations are leading the spec in some places, and we’re getting real progress there. Firefox’s rounded corners and WebKit’s drop-shadows, declarative animations, background tiling, and CSS variables are all hugely important and liberating. But where the spec is in-front of the important implementations…well, I’ve ranted before on the topic. CSS sucks, and the editor of the spec has now written at length of his intent to keep it that way (via Simon). His arguments are flim-flam, but just saying so isn’t enough to convince any one. Making the case requires answering long-hand and showing our work.

By The Numbers

Lets look first at the numbers presented in the sidebar here. Remember that the survey numbers come from documents on the W3C website. The article would have us believe that this sample set bears some relationship to the rest of the web such that we can extrapolate a case against CSS variables out of them. The relationship is tenuous enough that this disclaimer is included:

The authors who write on this Web site site are probably more careful about the structure and re-usability (and download speed) of their documents than the average Web author and there are indications that the average size of style sheets on the Web is two or three times higher. That is still small for computer code, though. Although it doesn’t fit in one window, like the average W3C style sheet, it doesn’t take more than scrolling once or twice either.

There’s much wrong with this leap of logic: if the real web is at least 2x more complicated, how can we dismiss the clamors of real web developers for more powerful tools? Further more, what’s to say that what is or isn’t being encoded in CSS is due to to complexity? There are lots of things which we’d like to put in CSS but don’t because CSS just can’t do many of the things we should expect of it. Real-world CSS is likely to get longer, not shorter, as CSS evolves toward its manifest destiny and allows us to declare property bindings, animations, and all manner of complex layouts for which we currently turn to table elements and layout systems like the Dojo BorderContainer and ExpandoPane widgets. This isn’t a foot-note, it’s an out-and-out refutation of the proffered case.

We can also do much better than the chosen sample set. A quick wget of the front pages of the top 20 Alexa sites (to stop short of the porn) reveals a world which the article’s sample set bears no resemblance to. Remember, these are only the front pages, as well. Internal pages can be significantly more complex as they trend toward applications and away from relatively static views of data. Here’s what I ran to get data to work with:

media:css_stats alex$ ls
./		../		out/		sites.txt
media:css_stats alex$ cat sites.txt 

http://yahoo.com/


http://google.com/


http://youtube.com/


http://live.com/


http://msn.com/


http://myspace.com/


http://facebook.com/


http://blogger.com/


http://orkut.com/


http://rapidshare.com/


http://microsoft.com/


http://google.co.in/


http://ebay.com/


http://hi5.com/


http://aol.com/


http://google.co.uk/


http://photobucket.com/


http://amazon.com/


http://imdb.com/


http://imageshack.us/

media:css_stats alex$ wget --user-agent="..." -P out -l1 -p -H -i sites.txt 
--15:05:15--  http://yahoo.com/
           => `out/yahoo.com/index.html'
Resolving yahoo.com... 68.180.206.184, 206.190.60.37
Connecting to yahoo.com|68.180.206.184|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.yahoo.com/ [following]
...

Of these 20 pages, there are only 28 referenced external style sheets (per wget), likely to speed rendering time. Most of the pages that do specify external style sheets also host them on “static” servers to increase download parallelism and resource usage on front-end boxes. We can already say something about the use of CSS is large, commercially successful websites:

Site authors are going to enormous lengths to ensure that pages load as fast. Therefore, techniques which reduce redundancy and therefore result in smaller style sheets will have significant value to content authors.

Recall that one of the primary drivers behind CSS inheritance, macros, and variables is to reduce the size of style sheets. Just looking at the behavior of real-world page authors at least makes a strong case for techniques to create terse style sheets if not for these specific solutions.

These external style sheets have a median line count of 280, seemingly validating the essay’s assertion that the “real world” is 2x to 3x more complicated. But something tells me that’s also misleading. Indeed:

media:css_stats alex$ cd out
media:out alex$ find . | grep "\.css" > css_files.out
media:out alex$ cat `cat css_files.out` | wc -l
    7866
media:out alex$ CSS_FILES=`cat css_files.out`
media:out alex$ for f in $CSS_FILES; do wc -l $f; done
      92 ./i.media-imdb.com/images/SF389ed063874f275ab16e1fef86e6462a/css2/consumerhome.css
     419 ./i.media-imdb.com/images/SFf399dbc3948ab005b0ed6e733d294c7c/css2/consumersite.css
      59 ./imageshack.us/css/styles.css
     138 ./imageshack.us/img/style-def.css
      32 ./imageshack.us/img/tooltips.css
     122 ./include.ebaystatic.com/v4css/en_US/e573/GlobalNavVjoOpt23_Ebay_e5736892865_en_US.css
     128 ./include.ebaystatic.com/v4css/en_US/e577/CCHP_HomepageV4_SLDR_e5777009417_en_US.css
     310 ./rapidshare.com/img2/styles.css
      86 ./static.ak.fbcdn.net/rsrc.php/102900/css/typeaheadpro.css
      58 ./static.ak.fbcdn.net/rsrc.php/104778/css/dialogpro.css
     332 ./static.ak.fbcdn.net/rsrc.php/108104/css/ubersearch.css
     150 ./static.ak.fbcdn.net/rsrc.php/98481/css/welcome.css
      10 ./static.ak.fbcdn.net/rsrc.php/99258/css/webkit.css
    2081 ./static.ak.fbcdn.net/rsrc.php/pkg/77/113750/css/common.css.pkg.php
       0 ./static.hi5.com/friend/styles/global_1215662072.css
       0 ./static.hi5.com/friend/styles/headernav_1214604328.css
       0 ./static.hi5.com/friend/styles/homepage_anon_1203011808.css
       0 ./static.photobucket.com/include/css/pkgs/homepage_v14.2.4.css
       0 ./static.photobucket.com/include/css/pkgs/photobucket_v14.2.4.css
       0 ./stc.msn.com/br/hp/en-us/css/54/bluso.css
     377 ./x.myspacecdn.com/modules/common/static/css/global017.css
     346 ./x.myspacecdn.com/modules/common/static/css/header/siteheader004.css
     192 ./x.myspacecdn.com/modules/common/static/css/master.css
     853 ./x.myspacecdn.com/modules/splash/static/css/splashv2007.css
     386 ./z-ecx.images-amazon.com/images/G/01/nav2/gamma/n2CoreLibs/n2CoreLibs-n2v1-43122._V252271770_.css
    1428 ./z-ecx.images-amazon.com/images/G/01/nav2/gamma/navbarCSS/navbarCSS-navbar-53059._V252284495_.css
     256 ./z-ecx.images-amazon.com/images/G/01/nav2/gamma/topproductideasCSS/topproductideasCSS-topproductideasCSS-50166._V13960170_.css
      11 ./z-ecx.images-amazon.com/images/G/01/s9-campaigns/popover._V255266624_.css

But what about those 0-line files? ls says there’s more there:

 8.8K  ./static.hi5.com/friend/styles/global_1215662072.css
 4.4K  ./static.hi5.com/friend/styles/headernav_1214604328.css
 2.3K  ./static.hi5.com/friend/styles/homepage_anon_1203011808.css
 8.8K  ./static.photobucket.com/include/css/pkgs/homepage_v14.2.4.css
  34K  ./static.photobucket.com/include/css/pkgs/photobucket_v14.2.4.css
 1.6K  ./stc.msn.com/br/hp/en-us/css/54/bluso.css

Indeed, they’re all 1-line long and missing a trailing newline char due to the whitespace removal that’s been applied to them. The shortest of the files, when expanded for readability, is longer than 100 lines. Clearly counting lines doesn’t actually tell us much about the complexity of production-quality CSS – at least not without some normalization. Since most production-level CSS is embedded in the served document then, we should probably have a look at it too and figure out ways to normalize the whole shooting match to determine some sort of “style complexity factor” since it’s very much the case that the impact of CSS is not often isolated to individual elements. Indeed, some of the hardest to maintain issues with CSS come from the overall difficulty of knowing what’s affecting which element and those rules can come from anywhere. So getting an accurate view of the amount of style that a developer or designer needs to keep in their head at once (the central argument of the original piece) is usually some factor of the total number and applicability of the rules in the page to the elements currently being styled. Therefore, to get a sense of the complexity of the style being applied to a page, it would be far better to know the number of normalized lines of CSS on the page plus a count of the total number of rules applied to the document.

I put together a small python script to do just this. Quickly summarized, it sweeps through documents looking for external stylesheet links, @import statements, or <style> tags, parsing the contents of each into a normalized, pretty-printed form. Here’s the summary output:

Totals:
----------------------------------------
	files examined: 17
	total # of CSS rules: 9462
	normalized lines of CSS: 39999
	average # of CSS lines per file: 2352 (mean) 1428 (median)
	average # of CSS rules per file: 556 (mean) 308 (median)
	average # of CSS style sheets per file: 4 (mean) 3 (median)

(full output here)

This output comes after removing items from the list which don’t have valid index pages (e.g. microsoft.com got wise to my faked user agent) and which included some manually fetched external CSS files that wget initially missed. Also, it’s worth noting that the Google home-page pulls the averages down significantly since they only include 111 lines of normalized CSS per and the home pages for google.com, google.co.in, and google.co.uk are seemingly identical from this perspective and all occur in the top 20.

Never the less, the results are still astounding when compared with the results from the original article. CSS authors who maintain the world’s most popular landing pages are contending with thousands of lines of CSS per page and hundreds of rules. This is orders of magnitude more complexity than the initially presented numbers, hopefully dispelling any notion that we could rely on those numbers as the basis for asserting anything but that those in the employ of the W3C and the volunteers which join them are not typical content authors and do not attempt the feats of CSS which are meerly work-a-day constructions for commercially successful websites. Granted, the home-pages of the most successful websites on the internet are also not “normal” (by definition), but they are significantly more representative of where the web is heading and the standards that content authors likely aspire to.

The article’s numbers may indeed present a compelling case for not adding CSS variables for the sake of the W3C’s content authors, but no such case holds in the “real world” of deployed content.

Upon Further Inspection…

One argument made in the article is that the ability to understand what you see in a style sheet is bolstered by a lack of indirection. This argument is simplistic insofar as CSS is already rife with indirections. From cascades to the order of precedence in style application to the !important rules to media queries, CSS currently provides many facilities for content authors to create difficult situations in determining where a particular rule is coming from or what the impact of a rule will be. Inspectability and what-you-see-is-what-you-get were properties of an earlier, simpler web which the article harkens back to. But the WYSIWYG principle has already been lost as HTML and CSS have failed to keep pace with the tasks being demanded of them. When a pile of non-semantic div or table elements are employed to create the canonical 3-column layout for which the CSS is a mind-bending combination of art and science, no novice can be expected to follow along at home. I whole-heartedly agree that the ability to “View Source” on the web and have that mean something is a powerful evolutionary advantage to the Open Web, but it is one which is being under-cut most forcefully by the lack of evolution in HTML and CSS, not by the addition of features to them. While HTML and CSS lack semantics for simple construction of common visual and structural idioms, we should continue to expect the contorted, complex sets of rules and markup. Visual and interaction designers aren’t demanding less of the user experience simply because CSS isn’t up to the task. Instead, they’re turning to JavaScript toolkits like Dojo which can and do deliver the goods. Hardly a better position for the platform to compete from.

On this point the essay also contains a rhetorical bait-and-switch which I find distasteful: it dismisses variables because they don’t inherently do anything to reduce the lengths of pages (true!) and then argues against macros and inheritance because they create levels of indirection which can be confusing. Inheritance and macro definitions can play a key role in drastically reducing the length of style sheets. In this way, they promote understanding through exactly the same “memory effect” mechanism that is cited as a liability when discussing variables.

Variables, on the other hand, provide an effective and over-due mechanism for consolidating the definition of shared values across style sheets which may be defined in distributed places (say, via a CMS’s default template which is later customized by users). For the very-lengthy, real-world styles which occur frequently on the public internet, this ability to cleanly separate the definition of common values into a single style sheet would prove a huge boon to the development and maintenance of sites for which large teams must cooperate on the generation of what ends up being a single page. Style sheets are already long, and the proponents of variables assume this to be true. That variables do not shorten style sheets is not a valid argument against the considerable good that they can do in ensuring that style sheets are maintainable.

The essay dismisses the idea that variable names are (and should be) self-documenting. The argument that a comment would somehow “be better” ignores the reality of todays large style sheets. There isn’t a way for rules to effect similar visual appearance on different properties without repetition today, leading to tremendous maintenance headaches.

Modern style sheets are already well beyond the complexity levels which allow us to fit them all in a single screen, and re-using values today requires the exact same looking-in-multiple-places-burden that the essay deems unacceptable in a future with macros. The results for this extra effort today, however, aren’t consistent and maintainable rules which can be changed with relatively few updates. Instead we’re left with a mish-mash of hard-coded values which are copied here and there, often across multiple style sheets. Adding multiple classes to a single node is also no panacea as it quickly devolves into tens or hundreds of small rules to define what are essentially parameterized constants for a single set of layout, color, or typography decision combinations. These decisions cannot be conveyed through a simple selector but must instead by applied in the right combinations throughout a document directly to elements which required them. Ugg. Even if the original article were to make a cogent case against the need for variables, that can’t be extended to a case against inheritance or macro capabilities. Composition is far too difficult and authors are already awash in complexity. Denying them effective, optional tools to deal with this complexity is simply to deny the truth of the web which has evolved.

Cobbling It Together

Perhaps the most disingenuous argument fielded is that the addition of variables in CSS places an onerous burden on the developers of user agents. User agent developers are best suited to know the difficulties and pitfalls in implementing CSS variables and at least one team has decided that not only is it workable, they have authored the spec now under discussion and have implemented several different syntaxes for the feature in parallel in order to figure out what will work best. Were there hue-and-cry from other implementers, I’d be much more sympathetic to this point. However, given the general lack of objection amongst implementers, the long-standing ambiguities in the CSS specifications, the inscrutable choices of box models, and the weirdisms of the CSS in general it seems that we’re very far down the path in terms of the complexity required of any implementor. It is probably the case today that authoring a new HTML and CSS rendering engine that will consume the real web isn’t a realistic prospect save but for the most well-heeled and motivated of teams today. Adding or not adding CSS variables and/or macros doesn’t change that reality.

The arguments against variables and macros/inheritance get weakest when they are taken as a whole. Variables are likely just the first step to a CSS that allows both simple parameterization (variables) and composition (inheritance, macros, etc.). One without the other is weak sauce, and the essay tacitly acknowledges as much by arguing against them in turn (but not in together). A CSS dialect which includes inheritance will allow the specialization of “parent” rules without relying on extra nodes or multiple classes added directly to nodes. CSS with variables will allow for much simpler maintenance and “templating” of complex visual identities. Taken together, these techniques allow for sophisticated CSS authors to stop repeating themselves and get a handle on the thousands of lines of code which they’re managing to construct pages today.

Arguing that they are too hard or too confusing simply ignores the deeply painful experience of today’s content authoring process. The time has long passed when we can delay progress or claim it “harmful” without proof. Once again, it’s time to let the implementations lead and time for the standards bodies to stand aside and cheer them on.

14 Comments

  1. Posted August 11, 2008 at 8:16 am | Permalink

    Thanks for writing this. Someone needs to be arguing coherently about this, and I’m glad you are. The argument against variables felt flimsy to me, but I wasn’t able to verbalize why.

  2. Posted August 11, 2008 at 8:31 am | Permalink

    I for one am getting sick and tired, not to mention feeling more and more insulted, by the idea thrown around by the W3C, that CSS _should be simple_, the extent to which that idea is applied seems to imply that the W3C thinks most web developers are morons.

    No, it should not be simple at the cost of function. It should be _as simple as possible whilst doing what we want_ – it should not be lobotomised simply to keep it easy to learn.

    The fact is that it needs to control presentation, and what CSS can do right now is, frankly, not good enough. It’s like trying to paint a masterpiece whilst wearing boxing gloves.

    CSS Constants (they are not variables) are simple concepts to get, with huge benefits. There is NO valid argument against them. For me, I’d like to see real Variables in CSS. Not to mention calculations and mixed units.

    I’m not interested in fancy-pants shadows and (pathetic) ASCII-art layout techniques (for serious?) whilst we are still fighting with CSS to do the absolute basics like getting widths correct in liquid layouts!

    Roll on the day I can do this:

    #login { width : (100%-30px); position : absolute(#container); top : 10px; }

  3. Posted August 11, 2008 at 8:34 am | Permalink

    Let me be double clear: CSS’s implementations of control concepts should be simple. CSS’s abilities should be limitless.

  4. Posted August 11, 2008 at 9:22 am | Permalink

    I agree with Matt. The suggestion that CSS should be “simple,” as in “anyone ought to be able to write it,” is silly. CSS is used by web developers. It’s not used by Moms and Pops. If web developers have to do a bit of learning, fine — that’s their job.

    This is a terrific piece, Alex. Well-done.

  5. Posted August 11, 2008 at 10:46 am | Permalink

    #login { width : (100%-30px); position : absolute(#container); top : 10px; }

    I love that idea. That plus constants would make it really really simple to work with CSS.

    And as far as my personal experience is concerned, even static sites have CSS files several 100 lines long. Larger sites, the total CSS lines easily crosses several thousand lines. And it is really tough keeping track of colors & shades.

    If I could just define a particular color with a set of shades, I could use those constants everywhere without having to keep copying the color code. How is remembering color codes easier than remembering names like: deep_blue, medium_blue, light_blue etc. Constants are used to simlify the code, they don’t make it more complex.

  6. Posted August 11, 2008 at 12:29 pm | Permalink

    Thank you for taking the time to write that. I’m really happy that you countered those “arguments” with solid facts and research.
    I found it shocking that he would suggest search and replace as an easier way to achieve that. Also, suggesting that I should spend server cycles to patch inabilities of the client is idiotic. But the argument that CSS should be simple was just the last straw: they would have to rewrite it from the ground up to achieve that anyway.
    And what’s with the atrocious design of this guy’s web site? I almost went blind reading it.

  7. Posted August 11, 2008 at 1:54 pm | Permalink

    It did bug me how Bos argues that it’s “not necessary” to add constants to CSS simply because there’s a different, Rube Goldberg–esque solution (for one platform) that involves running all your CSS files through a preprocessor.

    Problems are always “easier” to solve on a part of the stack that’s not yours, right?

  8. Posted August 11, 2008 at 4:21 pm | Permalink

    > it should not be lobotomised simply to keep it easy to learn.

    I’d argue CSS is NOT easy to learn now.

    If CSS wants to be simple, then it has a way to go – why does a page designer need to understand box models, ‘float’, and ‘clear’ in order to make a basic functioning two or three column layout with a header and footer? In practice, they go to Google, search for “3 column CSS” and copy-and-paste the CSS & HTML structure from the first result. That doesn’t lead to understanding. Higher-level rules (which are effectively macros) would be a solution to keeping it simple and lead to incremental improvements in understanding. If they were actually serious about making it simple.

    But as Matt said, there’s no need to lobotomise the advanced practitioners along the way. In the same way a new C/C++ developer can work without macros, they provide flexible and extensible tools for advanced workflows and techniques, and allow developers to build useful functionality ahead of the standards track.

  9. Posted August 12, 2008 at 5:27 am | Permalink

    @Robert

    It’s also not very hard to learn at the moment either. The difficulty today comes from cross browser issues, and those are rapidly becoming a thing of the past.

    As for “why does a page designer need to understand box models..” – well for the same reason that the same designer needs to understand the layout grid, basic typography, or any other basic tool of their trade. If people want to be a good designer in any field then they have to understand a lot of surrounding issues and details. I don’t think the box model or floats are really any more complex than knowing about good UI principles, or the nuances of good typography, for example.

    CSS is simple. It’s built out of behavioural blocks that you put together to make something more complex. Think of it like LEGO. Once you understand how the blocks fit together then you can go out and build a replica 14th century town house out of it if you like.

    No one expects to be an expert UI designer in a day (or a month, or a year), so why do they expect to be an expert CSS author in a day?

  10. cs44
    Posted August 12, 2008 at 10:21 am | Permalink

    Definitely a fan of “let the implementations lead” – this is long overdue. Thanks Alex.

  11. Posted August 12, 2008 at 11:25 am | Permalink

    The fact that CSS even needs something like “!important” is prima fascia evidence that it is poorly thought out.

    I’ve been writing code for over thirty years now, starting with assembly language. But even the simplest assemblers had macros which permitted symbolic representation of constant values. This lack of the most rudimentary facilities in CSS continues to baffle me. It is as if all wisdom learned in computer science was just ignored and discarded.

    For example, what do we know of modularity? Well the standards principals are that you want modules with high cohesion and low/loose coupling. CSS seems to be just the opposite. Anything that comes later can modify anything that came before in CSS. It’s goto gone wild!

    Keep in mind that layout elements have semantic meaning to the designer. Wouldn’t it be useful if our layout language let us specify our layout in semantic groupings, not just specify the style of individual elements?

    I get around some of these issues by generating some of my CSS dynamical on the server side. In other cases I have tags that get processed when I save the CSS file … kind of like mail-merge tags.

    But for the most part I avoid CSS because my small projects just can’t afford testing on every browser version out there and I’m not about to learn the foibles of each one.

    And finally, until CSS lets me format my layout in a simple grid, just like a table, without resorting to strange non-semantic markup and obscure large negative margins and other hacks, I will continue to use HTML tables to perform this function.

    Peace,

    Rob:-]

  12. Posted August 14, 2008 at 2:29 pm | Permalink

    Plenty to chew on here, and I’ll echo the thanks for the time spent researching this before publishing a response.

    I think there’s a natural tendency for developers to seek convergence in the languages they use. We see it in javascript too – people want it to be more like c/java/python/whatever, and argue passionately about why it should be so. That’s the backdrop here for me, and one reason why I’m still on the fence with this issue.

    It is certainly true that there’s no inherent simplicity in the problem of styling a document or application – particularly when you want one static stylesheet to cover the various permutation and states a page can find itself in. There is a legitimate question though in what portion of that complexity should be accomodated in CSS vs. client or even server-side (post and pre-processing) code.

    CSS in the wild is currently crippled by lack of consistent browser support. We haven’t begun to exhaust what can be done with it as-is. Something as simple as reliable multiple class (.classOne.classTow) support would revolutionize the way we write stylesheets – we would have much more modularity.

    There is a danger of circular reasoning when looking at current trends in CSS use. If people are writing “simple” css today, its likely because that’s the only kind its really practical to write. With richer semantics (and good browser support,) more difficult problems could be addressed with greater simplicity.

    I am glad to see debate on the matter either way – it is important the evolution of CSS is informed by real experience solving hard problems. If w3c.org was representative of the kind of challenge CSS needs to meet, we’d all have packed up and gone home long ago.

    I’m flip flopping for and against with every paragraph, so I’ll wrap up. Yes to constants (not variables.) I’m not yet convinced of the need for macros. I do see a need for some means of referencing property values on other elements (the only really useful bit of css expressions). I would like to see relative/proportional values like darker/lighter, thinner/thicker, hue-shifts – in line with the proportional values we have for text sizes already.

  13. Posted August 19, 2008 at 11:27 am | Permalink

    I absolutely agree with this article. I am just a beginner web designer and I am already seeing where things could be made much simpler in CSS.

    Being able to reference particular objects would be very nice especially for absolute positioning and width declarations.

    #login { width : (100%-30px); position : absolute(#container); top : 10px; }

    Statements in CSS like this would make it very, super easy for a beginner to use. I am a beginner, so I carry validity with this statement.

    Who styled the W3C site anyway? It is atrocious and hard to read.

  14. Posted October 31, 2008 at 6:24 am | Permalink

    Firstly, this is a great, well-researched and argued article.

    Secondly, the length of many CSS files (e.g. WordPress) often indicates a lack of craft and poor use of inheritance, on top of excessive and non-semantic HTML markup (div-itis).

    Thirdly, I wanted CSS constants so badly after having to plough through thousands of lines of badly-constructed CSS that I made some with good old SSI: http://ecoconsulting.co.uk/training/css_includes.shtml

    Clunky, but useful.

2 Trackbacks

  1. By Ook interessant | Scriptorama.nl on August 14, 2008 at 10:30 pm

    [...] CSS Variables are the Future – Alex Russell, mede ontwikkelaar van het Dojo javascript framework, beschrijft waarom hij de redenen die Bert Bos beschrijft onzin vindt [...]

  2. [...] Stylesheets mittels Variablen zu erleichtern und zu beschleunigen. Die Vorteile liegen auf der [...]