Grow your CSS skills. Land your dream job.

About Variables in CSS and Abstractions in Web Languages

Published by Chris Coyier

Variables are coming to CSS. They already have implementations, so there is no stopping it now. Firefox has them in version 29 and Chrome has them unprefixed in 29+ if you have the "Enable experimental Web Platform features" flag turned on.

To be clear, no amount of arguing on whether this is good or bad is going to change things at this point. But I still think it's interesting, so let's talk about it anyway.

The Abstraction Backstory

I've been giving a talk recently about abstraction in computing. Looking back at the history of programming, there are several clear points where we stepped up abstraction to a new level. From the "1's and 0's" of machine code, to assembler languages, to compilers, and the abstractions of those giving us languages like C++.

Browsers are comprised of parts, like a rendering engine and a JavaScript engine. Those parts are written in C++. So when we write things like HTML, CSS, and JavaScript, we're yet another step up the abstraction ladder. HTML, CSS, and JavaScript don't replace the languages below them, they sit on top of them. They depend on the layers below to do the things they do best. HTML, CSS, and JavaScript are languages we invented in order to build the kind of things we wanted to build on the web: interactive documents.

As time goes on, we want/expect/need the web platform to do more. Capabilities are only ever added to browsers, never removed. We gobble up those new capabilities and use them to their limits. That makes building for the web more complex. We don't like complexity. It makes work harder and less efficient.

This has been going on long enough that we're taking that next step up the abstraction ladder. Abstraction is the natural combatant to complexity, so we employ abstraction to lower the complexity of the code we write.

The abstraction we most needed on the web was for HTML. It would be ridiculous to work on a website where every page was stored as a complete HTML document, from <!DOCTYPE html> to </html> that you edited directly. No one works that way anymore. Complete HTML documents are pieced together through templates and chunks of content.

Abstraction in JavaScript is inherent. The tools of abstraction are already there. Variables, loops, functions, etc.

The last web language to get the abstraction treatment is CSS, and that has come in the form of preprocessors. CSS is enormously repetitive and offers almost no abstraction tools. Preprocessors offer those things that we need so desperately and save the day.

Popularity

Another thing at work here is the popularity of the web platform. It is the most successful platform ever in computers. More people build for it and use the things built from it than any other. In other words, HTML, CSS, and JavaScript are pretty damn successful. Largely due to the work of the efforts of web standards advocates, but that's a story for another day.

Why is a language like CSS so damn successful? Because it is so easy. Selectors and key/value pairs. That's it. Yes, there are lots of little gotchas as nuances. Yes, it takes a long time to really master. But the root language is very simple. In ten seconds you can show someone a block of code and explain how it works in such a way they completly get it.

h1 {
  color: red;
}

I'm convinced CSS is as successful as it is because of how easy the syntax is to understand, learn, and teach. There is plenty to bitch about in CSS, but I think correct language choices were made early on.

Complicating the Core Language

As languages do, CSS has evolved over time. Like everything in the web platform, it added new capabilities. Jeremey Keith pointed out that @keyframes represent a significant shift in CSS. For the first time, you could write CSS that had no meaning and wouldn't work at all if not for another block of CSS elsewhere in the code.

/* This means nothing... */
.animate {
  animation: my-animation 0.2s;
}

/* ...if not for this, which could be anywhere or nowhere */
@keyframes my-animation {
  to { color: red; }
}

As Jeremy says:

So CSS variables (or custom properties) aren't the first crack in the wall of the design principles behind CSS. To mix my metaphors, the slippery slope began with @keyframes (and maybe @font-face too).

A given chunk of CSS is no longer guaranteed to have meaning.

CSS (the core language) is heading down the path of being fully programmatic. If variables are useful, surely loops are as well, right? We can start to imagine a version of CSS that has so many powerful programming capabilities that it no longer feels like that simple, easy, understandable language it came from. That simplicity that made it successful to begin with.

The Abstraction Layer

I'm absolutely not anti-variables or anti-any-programming-concept. I love these things. They empower me as an author, making my job easier and enabling me to do more. That's what all (good) abstraction layers do. So why not leave these concepts in the abstraction layer rather than alter the core principles of the language?

Again as Jeremy says:

Thanks to preprocessors like Sass, we can have our cake and eat it too.

Not All Abstractions Are Great

In the spirit of back-and-forth blogging, allow me to respond to Jeremy again.

...not all abstractions are good abstractions.

He goes on to compare Sass and Haml, declaring Sass good and Haml bad. I'm largely in agreement there. I've worked with Haml a little and have never extracted much value from it, while I extract loads of value every day from Sass. I have two points to make here.

Chris made the case for abstractions being inherently A Good Thing.

The context here needs to be "over time". When these points in history come along where we step up the abstraction ladder, there are always languages that compete for that place in history. Developers duke it out (as we're seeing now with the CSS preprocessor market) and as the years go by a "winner" emerges with the vast majority of "market share" if such a term applies here.

The winners are A Good Thing as they have proven themselves. The losers were (probably) the less-good abstractions.

My second point is that I believe there is a such thing as a primary abstraction and secondary abstractions. Perhaps those aren't excellent terms, but what I mean is that there is an abstraction that provides the most important and valuable things authors need (the primary abstraction) then there are abstractions that provide little niceties (secondary abstractions).

As mentioned above, the primary abstraction of HTML is templates and content stored in data-stores. Haml is a secondary abstraction providing a more comfortable syntax for developers of certain flavors. CoffeeScript is also a secondary abstraction to JavaScript's inherent tools of abstraction.

Sass (or whatever the winner turns out to be over time) is the primary abstraction for CSS.

Comments

  1. Marcel
    Permalink to comment#

    Who says that browsers have to be written in C++?

    • Owen
      Permalink to comment#

      Well, no one, but a browser would a least need to be written in a semi-low/low level language in order to manage memory well enough to create comparable performance to the existing offerings.

      Browsers currently have advanced features like runtime compilers for JS, memory managers and garbage collection algos that, although they could be implemented in something else, it’d be difficult to maintain good control of the system and still produce a quick browser. So C++, C or something of a similar integration with the system is needed.

    • Permalink to comment#

      C/C++ is the most appropriate language to write browsers in. Why would you go write it in another language. It needs to run cross platform. Any app that needs to run on many different operating systems and requires a port to get there will be written in c/c++.

  2. Capabilities are only ever added to browsers, never removed.

    Remember <blink>? http://boingboing.net/2013/08/07/firefox-nukes-the-blink-tag.html Chrome also disabled <frameset> which is a shame because I had a perfect use case in mind for it.

    I’m all for abstractions. Until the abstractions get in my way and prevent me from doing something I need to get done. At that point you’ve got an abstraction distraction on your hands.

    • Josh Young
      Permalink to comment#

      was the first thing to come to my mind when I read this statement, as well.

    • René
      Permalink to comment#

      Chrome also disabled <frameset>
      Do you have a source for that? It still works in chrome 31.

      And I can’t think of something you can do with frameset but cannot do without (at least in modern browsers)

      Your point is still valid though. Several HTML tags, attributes and JavaScript functions have been removed or significantly changed. From browsers and from specs.

  3. Permalink to comment#

    I understand your point but keyframes and variables are there but optional, css will still be easy to learn.

    css variables are not variables like in Sass and are very useful in my opinion

    I’ve tested variables in Firefox nightly and they seem very useful in RWD.

    I’ve defined font & margin bottom (for vertical rhythm) & gutter width in :root and then another time in :root but inside a media query for bigger screen

    It’s great and we won’t need to overwrite a lot of properties in MQ and keep those settings at the top.
    The stylesheet is lighter and DRY

    Some people don’t get block formatting context or display table, table-layout… but they can write & learn HTML

    I don’t know how to use promises in JavaScript or use a node server. But I can use the small part of JavaScript I know to do some DOM manipulation
    It will be the same with css in my opinion.

    Wait & see
    & welcome variables ;)

  4. Michael Cook
    Permalink to comment#

    I’m convinced CSS is as successful as it is because of how easy the syntax is to understand, learn, and teach. There is plenty to bitch about in CSS, but I think correct language choices were made early on.

    What?! Of all of the languages and syntax’s I have learned: CSS, Javascript, C#, HTML, VB.NET, SQL, etc, etc – CSS has been the hardest to fully understand and frankly the messiest to use. It’s popular because we don’t have a decent alternative.

    • From your perspective as someone who knows how to code, that makes sense. CSS breaks a lot of programming rules. Chris’ point, I think, is that variables make CSS less accessible to a designer or hobbyist, which is probably true. However, you can say the same thing about programming languages themselves. Programming Basic was, well, pretty basic.

      CSS was never built to be a programmatic language. It was merely a page of styles to complement the markup.

      CSS is finally growing up.

    • Yes, it takes a long time to really master. But the root language is very simple. In ten seconds you can show someone a block of code and explain how it works in such a way they completly get it.

      h1 {
        color: red;
      }
      

      Perhaps you’re referring to advanced selectors or float page layout? Those don’t have much to do with the language itself, I don’t think.

      I find it very hard to believe that, if you’ve fully learned javascript, you find CSS, as a language/syntax, harder to understand.

      Concepts like clearing floats? maybe.

    • Philipp
      Permalink to comment#

      He is talking about the syntax. I don’t think any of the languages you named has an easier syntax than CSS.

  5. If CSS Variables didn’t happen, preprocessors would become more and more sophisticated and CSS accessibility would suffer. Take a look at javascript. Javascript never REALLY became a super popular language until libraries like jQuery abstracted all the plumbing required to make it work consistently and reliably. Before then, it was purely the domain of cut n’ pasters and early-adopters.

    Yes, CSS became popular because it was so simple, but CSS also held back many systems-based logical thinkers from doing any work in them. Many back-end developers HATED CSS because it was anathema to what computing was all about. There were too many implementation headaches and browser rendering inconsistencies. There were too many hacks (the float model, anyone) and anti-patterns. They didn’t hate it because they hated design, they hated CSS because it was a tool that didn’t work all the time.

    Preprocessors are the result of a bunch of logically-trained people HATING the repetition and redundancy of CSS. They got together and developed SASS and LESS to FIX CSS. Essentially, they’re the jQuery of CSS. They allow CSS to move forward without pain of adoption. Developers have already adopted variables and loops in CSS.

    What you WILL likely see is more engineering of CSS happen. Most designers will likely dabble less in CSS, for better or for worse… but the best ones will still seek to understand their tools.

  6. Permalink to comment#

    I’ve been playing with abstraction for css using php and php variables. Mostly this is just because I wanted it easy to manage the colors as we iterate through branding ideas. It sucks to have to change my blacks, grays, reds, and blues whenever we want to try something new. So the php variables for color have worked out nicely for me so far.

  7. Ezekiel Chentnik
    Permalink to comment#

    I think we’re witnessing first hand the natural progression of a maturing language because it’s finally being treated as important or “real code”. We’re realizing it needs a few more things to make it better and maintainable as it grows in complexity.

    Regardless of how anyone feels about abstraction and regardless if the responsible ‘CSS guy’ is capable (or not), you are going to have folks wielding their CSS swords – why limit the tools and features for those who can take advantage of them because there are those who can’t???

  8. Good points, Chris–well made.

    I totally accept your clarification that good abstractions take time to shake out. The comparisons between Haml and Coffeescript to Sass are spot-on.

  9. Ezekiel Chentnik
    Permalink to comment#

    What you WILL likely see is more engineering of CSS happen. Most designers will likely dabble less in CSS, for better or for worse… but the best ones will still seek to understand their tools.

    I agree with that statement and think its a move in the right direction.

    I’ve experienced a lot of projects where CSS was the after thought or treated like it was not a real language (for the same reasons
    Armstrongest mentions ). The CSS duties were left to the designer or the lesser developers who didn’t know how to properly yield their css swords – this had a huge impact on maintainability, performance, and success of the project. Which is just totally NUTS!!! CSS is arguably the most important part of the end product (it impacts what the customer sees) and you’d never treat back end code like CSS code has been treated.

    “hey guys, I’m sick of dealing with this [insert backend language] thing, let the intern take care of it…….”.
    OR

    “its just one line of code, skip testing and just push it live to see if it works….”

    OR

    “this page will be seen by 1 million IE users, oh well, let the logo designer who’s never opened IE deal with it.”

    CSS needs to be treated more like a programmatic language (at least how its perceived), these tools, preprocessors, etc. are more than just tools, they are perception, and best practices to make CSS code better……

  10. For me, CSS never really was a language, but more of a data format. Browsers consume CSS data just like JavaScript would consume a JSON object.

    Since it’s really just data, I think it’s fully open to revision.

    To your point though, that data has always had a certain syntax, and things like keyframes really mess with it.

  11. I’m not sure I get why it’s okay for SASS to have the abstractions, but not CSS.

    If everyone’s using SASS (and other preprocessors & abstractions), then no one really benefits from CSS not having them – no one is writing pure CSS. Furthermore, in a general way (with lots of exceptions!), those who do write pure CSS won’t be on a level field with everyone else who has all of these abstractions to help them.

    The best of both worlds would be for CSS to have these abstractions, but for them to be optional and backwards compatible. Don’t want the extra complexity? Don’t use it. Are you capable of understanding them? Make use of them!

    Mind you, this is dependent upon specs allowing the new rules to be optional and compatible, and maybe it’s not possible or ideal. But it seems like that’s the holy grail we should at least try to aim for.

    • Klaus
      Permalink to comment#

      I second that.

    • traq
      Permalink to comment#

      I’d be perfectly fine with SASS literally replacing CSS in the browser.

      As long as I didn’t have to use the scss syntax. : )

    • I’m certainly an advocate for Sass, and potentially even for Sass replacing CSS. However, I do think there’s merit to maintaining the simplicity of the core compiled language of CSS.

      The main benefit in keeping the abstraction layer out of the core language is that it saves the browser from another step in processing. By moving the abstraction into CSS, the browser now has the responsibilities that preprocessors have – creating more work for the client when it comes to parsing and rendering. At least with Sass et al those extras steps happen at or before build time.

      Besides, phasing out old browsers (IE) takes time. It may be years before complete support comes for the latest CSS spec. In the meantime we’ll have to use a polyfill (read: preprocessors) to achieve the same result.

  12. Ryan
    Permalink to comment#

    I love this article. It’s funny seeing two sides of the story when looking at how some people LOVE CSS and some people despise it. After reading another article on CSS variables and watching the video, it really shows how much further we have to go before we get “A Perfect Web”.

    Question: If we love Sass and other preprocessors so much, why don’t we drop CSS and just render straight from Sass without converting everything? Pretty much what i think will happen is CSS will become more like Sass (dare I say, better than Sass) and people will drop Sass because there would be no point in using it. So couldn’t we just skip the work needed to make them similar and just use what we already have?

  13. Erik
    Permalink to comment#

    The difference in my mind in CSS/Sass being rather easy to build upon is because thus far everything that is needed to make more complex things happen is simply built upon a basic framework.

    You can build a great looking website with simple CSS. But if I want it to be easily-managed, I use Sass and use variables/mixins/etc. It’s not needed, but it makes my life easier and my work happen faster.

    In more abstract languages, which seem to be more OOP-oriented based on the examples given, need the abstractions in order to be useful. IMHO. Perhaps I’m misunderstanding the point of this post.

    In C++ and PHP, you NEED to understand variables and programming structures and syntax right away. However, based on how things are going with CSS, I think as long as the basic foundation stays put people will continue to grasp it and be able to build their knowledge as they get more comfy.

    • Millan
      Permalink to comment#

      But then what’s the point of using a preprocessor other than gaining abstractions?

  14. DarrenM
    Permalink to comment#

    I think that these are what I would call constants, not true variables. You assign an arbitrary value to a label once and then use that label anywhere you would want that value to be used. The browser parses the CSS once when the page is loaded and substitutes in that value wherever it sees the label. The value does not change at ‘run time’ – or while the page is being displayed.

    SASS has both constants and variables. Constants are created with the $name:value syntax and used in the same way throughout the CSS. Variables are what you pass into a mixin function – but they are only variables to the SASS compiler because the CSS output will have the actual computed value hard-coded.

    A true variable would allow the value to change at ‘run time’, ie during the display of the page, based on some environmental or user-invoked parameter. That would allow virtually any attribute in the CSS to respond to changing circumstances without scripting or media queries. It moves the CSS from being fairly static to being a bit of re-entrant code. I don’t know whether that should be the ultimate form of it or not.

    I use SASS and my only real issue with it is that once you go down that path, you are locked into it and everyone working on the project must use it. If someone hacks the CSS directly, then you may as well throw away your SCSS source files. It would be like someone hacking the binaries of a compiled application.

    Having it built in to the CSS syntax would allow you to discard the preprocessors. The only reason we have them is because CSS doesn’t natively support the things that we want to do. Personally I have no problem with CSS becoming more like SASS, as long as the simple syntax remains, it shouldn’t be a problem for anyone.

  15. MK Safi
    Permalink to comment#

    I never thought about abstractions in that way. Come to think of it, without loops or variables, CSS is really like how I imagine low-level machine sequential instructions to look like.

    But showing a very simple example and saying that anyone can get it is misleading.


    h1 {
    color: red;
    }

    This block of code is easy to understand because CSS has visual effects which humans like and can easily understand. But its effect as complex or even more complex than the following JavaScript code:


    javascript:alert('hi!')

    Seeing how ugly and broken most websites are is a proof that CSS sucks. It shouldn’t be just easy to play with, it should be easy to make reliably beautiful interfaces with it.

  16. That reminds me very much of what Jens Meiert said a while back: CSS has not nearly been understood by authors. We could use CSS more effectively and write much better code but nobody even bothers to because everybody screams for more stuff, and the CSS working group keeps on delivering

  17. RobWence
    Permalink to comment#

    I think there is really no need for this besides removing the need for preprocessor languages such as SASS or LESS.

    Granted as coming from a programming background myself the introduction of this would be a great time saver, however it doesn’t really ADD anything special to the mix that isn’t already available.

    Using SASS currently the ease of use is wonderful, the variables, mathematic calculations, mixins, save SOooooo much time. It reduces development time dramatically and saves you from writing the same stuff over and over again. I’m currently happy with using 3rd party software/languages to compile out working css files. I truly believe adding in variables will inevitably further slow down website rendering as now the browser will have to execute the css code and handle the variables appropriately.

    Generally as a programmer CSS and Web Development as a whole irritate me on a whole other level, as you have to write the same bits of code 9 different ways from Sunday to get it to work properly in each browser, but that is a whole different conversation.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".