CSS degrading gracefully

CSS3 has some really nice features – animation, gradients and rounded corners just to name a few. But as with most of this web stuff, you’re going to need an up to date browser like Chrome to really appreciate it. Fortunately older browsers will typically just ignore the newer stuff they don’t understand which makes it possible to deliver a degraded experience.

This afternoon I had a quick bash at creating the visuals for a progress type control. I wanted to take advantage of those nice CSS3 features in Chrome, but still have the control work in IE. Turns out, it’s wasn’t too hard.

Progress bar control in Chrome
Progress bar in IE

All the code and a running example showing the animation can be found on jsfiddle.net. The  CSS does look a little messy as browser vendors put newer CSS features behind a prefix while they’re being standardized. Using a CSS compilation tool like Less can make this a bit more bearable.

Advertisements

With CSS, LESS is more

I’ve got a bit of a secret – I’ve never really liked CSS.

Don’t get me wrong, it’s a nice idea. I’m certainly all for separating content and presentation. And yes, most importantly, it really does work in practice. Just take a look at any of the many CSS galleries that demonstrate how powerful it can be in hands much more talented than mine. However, just like there are some awesome php applications, it doesn’t mean I actually like php.

The problem I have with CSS is that I find I repeat myself a lot. For example, if you have a standard colour or margin width that is reused throughout a site, you have to repeat it every time it’s used. Now one of the first things I learned about programming as a kid is that if you’re repeating the same value, then put it in a variable. CSS, however, doesn’t have variables. Another example is when you have to frequently reuse a series of CSS declarations, like setting colour, font-family and font-weight. There’s no easy way to do that in CSS either. DRY is one of the most basic software engineering principles, and to be honest, CSS completely fails.

LESS is a Ruby tool that extends CSS to make developing it a more pleasant experience. It provides a language that is a superset of CSS – it’s the same language we know but adds variables, mixins (like methods) and basic arithmetic, among other things. Once you’ve written these LESS files, they will be compiled to plain CSS that will work just the same in any browser. Although LESS is a Ruby tool, it doesn’t mean you have to start developing everything in Ruby. In fact, the first project I used LESS on was a Java project, and the idea of requiring a Ruby install on every developer’s workstation and the build server was less than attractive. Fortunately, JRuby is an excellent Ruby runtime and installing a gem (such as LESS) couldn’t be easier. We even put JRuby into our project’s tools directory and checked it into source control. That enabled every developer and the build server to happily run LESS as part of the build process with absolutely no setup or installation.

To demonstrate what LESS can do, let’s start with a great example of CSS. Recently Christian Heilmann put together an excellent Sticky Note Effect demo to show how powerful CSS3 can be. If you’ve got a reasonably recent browser, check it out here.

CSS Sticky Note Demo

It’s a wonderful demo, but if you were to take a look at the CSS, you’d see a lot of repetition. For example, due to the way browsers have evolved support for some of the more recent CSS standards to define rotation, we have a large number of rules for a simple declaration.

-webkit-transform: rotate(-6deg);
-o-transform: rotate(-6deg);
-moz-transform:rotate(-6deg);

With LESS we can make this much more attractive. By simply defining a rotation mixin once with these rules, it becomes only a single statement to reuse them.

.rotate(@rotation) {
    -webkit-transform: rotate(@rotation);
    -o-transform: rotate(@rotation);
    -moz-transform:rotate(@rotation);
}

/* Then to use... */
ul li {
    .rotate(-6deg);
}

Another part of the language that I really like is the ability to nest rules. Take this example from the sticky note css:

ul{
  overflow:hidden;
  padding:3em;
}
ul li{
  margin:1em;
  float:left;
}
ul li a{
  text-decoration:none;
  color:#000;
  background:#ffc;
  /* lots more... */
}

The above is setting rules for ul elements, any li child elements of that ul and then any a elements of those li’s. In this example it’s not too bad, but imagine that the parent element was a specific id. If you wanted to change that id, you’d then have to change every rule related to it. LESS makes this scenario blissfully simple with nested rules. To write the same as the above, the following would be used:

ul{
  overflow:hidden;
  padding:3em;

  li {
    margin:1em;
    float:left;

    a {
      text-decoration:none;
      color:#000;
      background:#ffc;
      /* lots more... */
    }
  }
}

To finish these examples with where I started, LESS adds variables, which means we can define a named value once and reuse it throughout our styles. Need to change it? Just change it in one place.

@background: #666;

body {
   background-color:@background;
}

While LESS is already a super useful tool for developing CSS, the next version is shaping up to be even more exciting. LESS version 2 is written entirely in JavaScript. On the server, this will be run on node.js, but it can run directly inside the client’s browser. To demonstrate this I’ve rewritten the Sticky Note CSS in LESS, and instead of compiling it into CSS first, I’ve just included the new version of less.js and a link to the LESS file. Take a look at it here. When you hit the page, it’ll immediately download the LESS source, compile it and apply it to the page. Is this a good idea for a production deployment? Probably not. That said, it’s a very quick process so it’s an option. It’s certainly great for a demo like this and very useful during development. Dmitry Fadeyev has a great writeup on less.js here.

Find more information on LESS here. If you’re an die-hard .NET developer, you may want to check out the .NET port of LESS – dotLess.