My (current) take on CSS Preprocessors

CSS preprocessors (Sass, Less, et al) have come up repeatedly in the last few weeks.  I have some existing views on the topic that seem to take a lot of preprocessor advocates by surprise.  One even suggested I write a blog post about it, so I sat down to do just that, starting off with some research, as I like to do.

Lo! The blog post I was about to write has already been written — several times, in fact:

Those are just the first few I found; I’m sure there are many, many more.  Plus, the above posts have much more lively and interesting discussions in the comments than would probably happen on my outpost of a blog.

Many of the anti-preprocessor arguments overlap, but they broadly go like this:

  • The layer of abstraction a preprocessor adds is not worth the cost of integrating it into an existing workflow (e.g. setting up a development environment, adding team members, maintenance, bug fixing, et al)
  • Preprocessors solve problems that could easily be solved with better CSS (e.g. variables and mixins are just classes by another name)
  • The CSS output of a preprocessor is less smart than the CSS output of a human

I more or less agree with all of that.  Like many of the authors above, I think being able to perform functions and set variables inside of CSS could be very useful; so why not make CSS4 do so?  Then we have a single, open standard that browsers already know how to parse and that developers already know how to code.

What’s troubled me since the first time I heard about preprocessors was why on Earth anyone would think to make one.  I’ve always found CSS’s syntax both logical and flexible.  My complaints with it are few and minor.  But then, I do not have a computer science degree.

What I eventually came to realize is that computer programmers do not like CSS because it is not a programming language (see also the relationship of Haml to HTML, which is also not a programming language).  Some found that fact so irritating that they resolved to write a CSS-generating programming language with a syntax that made more sense to them.  Other programmers were overjoyed to at last be freed from the tyranny of CSS; the rest of us were surprised to find that, unbeknownst to us, one of our favorite tools had actually been terrorizing many people (many smart people, it turns out, which made me wonder if I’m just a moron…).

Ultimately, there may come a day when I find that the utility of preprocessors outweigh their associated costs; enough people — and enough people whom I respect — use them that from a statistical perspective I have to assume this will happen eventually.  It just hasn’t happened yet.

16 Responses to My (current) take on CSS Preprocessors

  1. garann says:

    “The CSS output of a preprocessor is less smart than the CSS output of a human” ++

    Excellent post and summary, thank you for writing it. I have a CS degree, but I also learned CSS at roughly the same time I was coding interfaces for things like Java applets and Visual Basic desktop programs. The programmatic way of styling elements was painful and brittle, whereas CSS was elegant and flexible, so I was very happy to embrace the latter. My personal feeling is that people – developers OR designers – who want to return to what we did before CSS are off their collective rockers.

  2. Jordyn Bonds says:

    Interesting! Can you go into more detail about programmatic styling vs CSS? You’re the only CS person I’ve talked to to prefer the latter.

  3. garann says:

    I guess it’s not disimilar to writing CSS with JavaScript. And I think most people agree that’s pretty tedious, and difficult to maintain. And with Java, at least, I remember there being additional overhead with having to specify default styling for containers for things. You couldn’t just leverage the defaults of a platform like a browser.

    CSS just feels very clean. You only specify what you need, it’s grouped by element or element class, not logical branch, so you’re not finding things getting set in some deep-down for loop somewhere. And there’s a clear and very simple system of inheritance and overrides, instead of having to create – literally – an object definition in order to reuse functionality. It’s very well suited to its task. Even if the syntax feels unfamiliar, I’d think CS people should be able to appreciate that.

  4. Jesse says:

    I have long suspected that most CS folks don’t like it because most CS folks don’t like declarative programming languages, and therefore write abstractions for things like SQL and CSS to fit their existing concept of how stuff should be.

  5. My thoughts on main points:

    >The layer of abstraction a preprocessor adds is not worth the cost of integrating it into an existing workflow (e.g. setting up a development environment, adding team members, maintenance, bug fixing, et al)
    –Build preprocessor compilation into the site and you don’t need to worry about team-members setting up their environments. They just need to find something to make syntax highlighting better in their text editor. If anything, maintenance is easier with LESS/SASS files – everything nested with relationships obvious and easy to follow.

    >Preprocessors solve problems that could easily be solved with better CSS (e.g. variables and mixins are just classes by another name)
    – Having lots of classes takes time to plan and maintain. DRY doesn’t help much in CSS with a typical small-medium website. Variables and mixins save huge amounts of time in implementation and maintenance.

    >The CSS output of a preprocessor is less smart than the CSS output of a human
    –How is it ‘less smart’? You make it sound like a CSS processor is like a heavily abstracted framework, where the user writes some simple code, and the framework turns that into hundreds of lines of code (which the user isn’t very familiar with) which produces a feature.
    A preprocessor just extends the functionality of CSS. You could use it to build a framework and abstract things from the user, but it’s just a tool to help you do that.

    Even Andy Clarke changed his mind on CSS preprocessors.

  6. Tom says:

    Pre processing will let you extract all your CSS out into lots of different folders and files, then generate a single file for you to include. This is really useful for a responsive site with loads of coders.

    It also allows you to create a massive load of CSS source files with a single generated include where no-one knows WTF is going on.

    Pre-processors help, but if its a simple site you don’t need it really.

  7. Jordyn Bonds says:

    @Phil:

    Having lots of classes takes time to plan and maintain

    Indeed it does, but I usually find that time very well spent — just as you find the extra time you invest in a preprocessor to be well worth it.

    everything nested with relationships obvious and easy to follow

    The issues with preprocessor nesting have been detailed elsewhere, but over-specificity seems to be a frequent hazard.

    Regarding preprocessors not being “heavily abstracted frameworks”, etc.: Many ardent fans of preprocessors I’ve spoken to admit this is actually the case. If planned unthoughtfully, the framework does indeed turn some simple code into an overly bloated stylesheet.

    For me, that is the rub: Both CSS and CSS preprocessors can be nightmarish when executed poorly; my (again, current) assessment is to keep focusing on executing CSS better and better rather than starting from zero with a new language.

  8. Pingback: SKYBONDSOR » P.S. on frameworks, libraries, toolkits, et al.

  9. James McKay says:

    The reason why programmers have more problems with CSS than designers is not that CSS isn’t a “proper” programming language, but that as developers, we have to consider factors that designers do not.

    The main factor is change management. Designers usually create the original stylesheet and HTML, then hand it over to the developers, and once it’s done, it’s done. On the other hand, developers have to consider how to deal with requests for change after the fact. A developer will consider a stylesheet to be badly designed if a single change requires a cascade of other changes right through to other parts of the codebase, or presents a high risk that a change to one part of the code will break something unrelated. That’s why we have best practices such as DRY, avoiding magic constants, and loose coupling.

    The other factor is how the CSS and HTML integrates into the rest of the application. Some web frameworks such as ASP.NET impose constraints on the kind of HTML you can use, e.g. specific ID or class attributes, or specific HTML markup for elements such as validation messages. JavaScript components will also impose constraints of their own, and don’t get me started on content management systems. With this in mind, seemingly innocuous changes to a badly designed stylesheet can have repercussions right through your codebase far beyond your HTML and CSS.

    It is these factors that CSS preprocessors are designed to tackle. I am yet to come across an anti-preprocessor argument that addresses them convincingly.

  10. Jordyn Bonds says:

    @James:

    It has almost never been my experience as a CSS writer that I hand off my original stylesheet to developers who cover the changes from there. If there are style changes to be made, someone with a comprehensive understanding of the structure of those styles should be the one to handle them.

    seemingly innocuous changes to a badly designed stylesheet can have repercussions right through your codebase far beyond your HTML and CSS

    I 1000% agree! But again, this is if the stylesheet has been designed (or maintained) badly. Why not focus on writing better, smarter CSS? Creating a whole new language/syntax to try to prevent bad CSS opens the door to even MORE layers of bad code.

  11. James McKay says:

    So what specific design patterns and practices do you recommend to keep your CSS (and HTML, and the rest of your codebase) well-organised and robust in the face of change? How do you avoid magic numbers and DRY violations, and ensure that, for instance, your colours and element widths are specified once and only once, especially on a more complex stylesheet? How do you organise your stylesheets so that changes to one element won’t have repercussions in unrelated parts of the site?

    I’ve looked at Object Oriented CSS (OOCSS) for example, but I’m not entirely convinced: it may reduce repetition in your CSS itself, but it seems to do so at the expense of requiring you to add extra class declarations right through your HTML. In particular, it looks like it could be tricky to retro-fit it to an existing website, especially one where a lot of JavaScript and jQuery selectors are involved.

  12. Jordyn Bonds says:

    @James:

    So what specific design patterns and practices do you recommend to keep your CSS (and HTML, and the rest of your codebase) well-organised and robust in the face of change?

    Whenever I start to add something to a stylesheet or html file, I take a few minutes to think about where it fits in overall, and whether I can leverage any existing structures to cope with its integration.

    Occasionally, whatever I’m adding requires that I rethink something fundamental to the site structure. On my better days, I am courageous about doing whatever massive re-org or overhaul needs to be done to the existing code to keep things clean; on my worse days, I add an ID to it, add a bunch of overly specific styles, and then promise myself I’ll revisit it later (maybe on one of those “better days” I just mentioned).

    How do you avoid magic numbers and DRY violations, and ensure that, for instance, your colours and element widths are specified once and only once, especially on a more complex stylesheet?

    The short answer is, I don’t! Sometimes, for the sake of maintability and readability, repeating some styles here and there is a good idea. For example, I might style two different types of buttons the same color by chance; if they are semantically unrelated in function, I might go back and change one type of button to a different color. When that happens, I’ll be happy I declared its color separately!

    The long answer is that variables would be an excellent addition to CSS and thus I will advocate for it to the W3C whenever I can. But creating an entirely separate syntax and process — basically, an entirely separate language — seems like overkill when the combination of developer tools, line numbers, and CTRL-F works just fine.

    How do you organise your stylesheets so that changes to one element won’t have repercussions in unrelated parts of the site?

    This question puzzles me because it seems to miss the “cascading” benefits of CSS. The reason CSS is so helpful is precisely BECAUSE the effects of changes cascade. I guess I avoid unwanted repercussions by, again, being thoughtful about my code.

    Ultimately, my sense is that the disagreement here is mostly aesthetic; I find CSS really readable and exceptionally maintainable. Everything is in one file. On occasion, the sections of a site are different in appearance in a way that requires separate stylesheets; all the better! I know that if I’m editing a module in the “Widgets” section, I should look in widgets.css to make the change.

    I usually format my CSS in single-lines, so scanning the left side of the document is very readable to me. If I have a number of selectors listed before a particular set of styles, or if there’s anything unintuitive going on, I might insert a comment giving my future self (or some unlucky non-me CSS author) some clue as to my thinking.

    Again, I reiterate that there may come a day when I see the utility in preprocessors, but no argument has made much sense to me so far. If I join a team that’s using one, I will happily learn about it and keep my mind open to its benefits. It just hasn’t happened yet.

  13. Pingback: Sass (stylesheet language): What reasons would one have to not use Sass? - Quora

  14. Pingback: Nested CSS Grid Hello World!T. C. Mits | T. C. Mits

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>