linear-gradient standardization / a quick fix

Since a while I've been trying to adopt to a fresh work pattern: whenever a new browser version is pushed I quickly run through my blog templates to see if anything broke in the process. There was a time when I dared to rely on browser vendors to keep things functional between major updates, but those times are clearly behind us. For those of you who haven't checked your sites in FF16 ... here's why you probably should.

vendor prefixes and standards

To be fair though, not all things that break between browser updates are actually related to browser bugs. For the longest time people have been telling us that vendor-prefixed css is unstable and probably not very safe to use in commercial projects. While we all know this (or at least we should know this), up until recently reality used to tell us something different. Apart from some small rendering differences, syntaxes and implementations have slowly been growing towards each other and cross-browser implementations have been fairly stable so far.

Some time ago a first big warning was issued when the entire flex-box syntax was rewritten from the ground up. People relying on the old syntax (polyfilling it for older browsers) broke a sweat and had some serious patching to do. The thing is that not too many people had been using flex-box in commercial projects, so the damage was almost negligible.

The recent release of Firefox 16 introduced a new problem though. Firefox 16 is the first stable browser version to implement the unprefixed, standardized linear-gradient syntax and implementation, which (surprisingly I must say) turns out to be a little different from what we've been using so far. The syntax may not have changed, but the defaults have.

linear-gradient and less/sass

.gradient(@start, @color1, @color2) { background:-webkit-linear-gradient(@start, @color1, @color2); background:-moz-linear-gradient(@start, @color1, @color2); background:-o-linear-gradient(@start, @color1, @color2); background:linear-gradient(@start, @color1, @color2); }

Chances are that you've been using a mixin like this (I assume the sass version isn't all that different) for applying css gradients in your projects. I know I have and so far it didn't bring up any problems. When I checked this site in Firefox 16 last week I noticed that some gradients were suddenly botched though. Not missing as such, but drawn in a different direction. Other gradients were still showing up fine, so confused as hell I looked around for hints of what might've happened.

It turns out some changes were made to the defaults of the linear-gradient implementation. If you've been using keywords to indicate the starting position you're pretty much safe, but if you've been using degrees you're bound to run into some problems. When defining a linear-gradient in your prefixed css the starting position (0 degrees) of a gradient runs from left to right and goes counterclockwise. When defining a linear-gradient in standard css the starting position of a gradient runs from bottom to top and clockwise.

In practice this means that 45deg gradients will still be the same, but all the others starting positions defined in degrees will yield different results. Sweet!

thanks you less/sass for including simple math functionalities

.gradient(@start, @color1, @color2) { background:-webkit-linear-gradient(@start, @color1, @color2); background:-moz-linear-gradient(@start, @color1, @color2); background:-o-linear-gradient(@start, @color1, @color2); background:linear-gradient((-1)*@start+90, @color1, @color2); }

Luckily the solution to this problem isn't too difficult. All we have to do to fix this is to add to difference between the angles of both starting positions (90) and invert the orientation (* -1) for the standard implementation. Just add this to your mixin and all will be alright again (now this is why I love preprocessors).

.gradient(@start, @color1, @color2) { background:-webkit-linear-gradient((-1)*@start+90, @color1, @color2); background:-moz-linear-gradient((-1)*@start+90, @color1, @color2); background:-o-linear-gradient((-1)*@start+90, @color1, @color2); background:linear-gradient(@start, @color1, @color2); }

One important sidenote here is that the first mixin is just the proposed fix to be used in existing projects. If you're starting a new project it's better to take the standard implementation as the starting point and adapt the prefixed implementation accordingly. The same formula applies, which leads us to the second mixin.

conclusion

Next time someone tells you it's entirely safe to use prefixed css properties, think twice. I'm not saying that we should all avoid prefixed css properties in our commercial projects, but the disclaimer that the syntax and/or implementation can change at all times isn't just an empty threat. In this particular case the fix is simple, but there's no guarantee that the next problem will be just as easy to tackle.