A Sass Mixin for Cross-Browser CSS Background Gradients

Yesterday at work, I was referencing the Mozilla article on gradients and noticed a link to Microsoft’s developer docs, mentioning there was a way to do linear gradients with IE as well. I was a bit excited to think that I would no longer have to look at our client projects in IE and think how plain they look. At Hashrocket, we code CSS with graceful degradation in mind. Generally, that means that if there are rounded corners, box shadows or background gradients, we use CSS to create these effects. In particular, that means that the fancy buttons that our designers come up with look like solid color rectangles, possibly with a rectangular border around them. They function fine, but look terrible compared to  what you’re used to looking at by the time you browser test.

I got to thinking about how IE has implemented Web technology advancements first before, but generally they’ve been unused and overlooked. A good example is font-face embedding. I remember being able to do this when I first started into working on the Web, but quickly abandoned it because it didn’t work in the up-and-coming browser, Firefox. You could also change image transparency and style scrollbars, a la MySpace customizations, but those aren’t really good examples.

It turns out that gradients are as old as the formerly mentioned tricks, so I’m thinking nearly 100% of your IE audience will be able to see these gradients (support begins at version 5.5). There are a few limitations, however. First, you can only paint gradients horizontally or vertically. I haven’t looked into it yet, but I think that you can paint them in either direction across each axis by setting the writing mode. In almost every case, though, you won’t want to change that because you’ll have text within the container you’re setting it on. Second, there are no color stops, simply an even linear gradient from one edge to the other; from one color to the other. From what I’ve coded recently, though, this technique covers most of the times I’m adding a background gradient, and the times I’m doing something different aren’t going to detract from the design as significantly if they’re not present.

Before getting into the Sass mixin, here’s an example of the code that makes this gradient possible:

filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#ffffff, endColorstr=#ececec)

The first argument to the gradient method is the type. This is a misnomer, as the “type” is linear in either setting. Instead, it affects the direction. 0 is vertical and 1 is horizontal. startColorstr and endColorstr are self-explanatory, although there’s a little added functionality that may come in handy. You can give each an 8 digit hex value rather than 6 to adjust the alpha channel. Why this is represented in a scale from 0 to 255 is beyond me, but at least you have a way of doing so. The weird thing about it is that these two digits come at the beginning of the number, so if we were to rewrite the hex values to include alpha they would look like #ffffffff and #ffececec. This isn’t at all helpful in our mixin as you’ll soon see, but you could still use this without a mixin. There’s also an argument called “enabled” that is optionally your first argument. This defaults to true, but setting it to false causes the gradient to not be painted. This is really only useful for DOM scripting, so I’ll leave you to read up on that if necessary at the MSDN reference.

Now that we know how the MS gradients work, we can build a cross-browser compatible linear gradient mixin in Sass. If you’re unfamiliar with Sass and/or mixins, check out their site for a quick demo and reference. It’s an amazing CSS extension that I can no longer work without. If you look at its examples and don’t understand why, then you’ll want to bookmark it and come back in a few months after you’ve got more CSS experience. Hashrocket prefers the older Sass syntax rather than the Scss syntax, so I’ll show you that particular syntax. You can easily change it to fit the new syntax if that’s what you’re into. Since we support all major desktop browsers from IE7 and up (note: Opera is not supported), we’ll add in the Mozilla and Webkit CSS properties, like so:

= gradient-bg($color1, $color2)
  background-color: $color1
  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#{$color1}, endColorstr=#{$color2})
  background-image: -moz-linear-gradient(center top, $color1, $color2)
  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from($color1), to($color2))

This mixin covers any case when we want to paint a linear gradient from top to bottom, starting with color 1 and ending with color 2. The first color is set as the background color for those browsers without gradient support. Next, we set IE’s property. One important thing to note is the use of string interpolation. I’m not quite certain why putting the variables on their own in this code doesn’t work, but I’m thinking it has to do with Sass parsing the property incorrectly because of the second colon after progid. Then we have the Mozilla and Webkit vendor-prefixed properties that look relatively similar. You’d then use this mixin in your sass like so:

#container
  +gradient-bg(#ffffff, #ececec)

And there you have it! A great way to use relatively new technology without having to remember all these different syntaxes. You get the added benefit of being able to quickly change the syntax if the browser vendors change it or remove the vendor prefixed properties in favor of a supported native CSS property. You could just as easily make a horizontal gradient mixin as well by modifying the direction each property paints.

Notes

  1. shaneriley posted this