Clock Blog
My Stylus Mixin for CSS3 Linear Gradients in Node
I've been getting my hands dirty with more Node development recently, and one of the best parts of it as a front-end developer is the utilisation of Stylus.
Stylus, combined with Jade speeds up my output so much. I love the cleanliness of the markup (well, what markup there is) - it's clean, efficient and most importantly, quick once you get your head around it.
I won't go into too much detail about what Mixins are (you can find out all about that on GitHub), but one of the things I have found them most useful for is; browser vendor prefixes. As someone who uses TextMate, I use my colleague JackBB's excellent bundle to write styles quickly (he's made a couple that are worth a look), and one of the best things about that is tab-completion of my browser prefixes. With the immediate shorthand he's got going on I end up something like the following:
border-radius 5px 5px 5px 5pxAnd with a quick hit of the dash key, followed by Tab, I get:
-webkit-border-radius 5px 5px 5px 5px -moz-border-radius 5px 5px 5px 5px -ms-border-radius 5px 5px 5px 5px -o-border-radius 5px 5px 5px 5px border-radius 5px 5px 5px 5pxAdd this as a Stylus Mixin and by writing 'border-radius 5px' anywhere in the site, my Mixin handles the rest. It's great for all the progressive enhancement we want adding to our site. Lean, efficient CSS3 markup - so far, so good. Until I wanted to do the same thing with CSS gradients. Creating a new Mixin in the same format as my others would give:
vendor(prop, args)
-webkit-{prop} args
-moz-{prop} args
-ms-{prop} args
-o-{prop} args
{prop} args
border-radius()
vendor('border-radius', arguments)
background-image()
vendor('background-image', arguments)
The problem is that a CSS gradient is a declaration within the background-image property, and I obviously didn't want my Mixin to have any affect on the other background-image styles on the site. If I left it like this, any background-image reference in my Stylus files would create vendor-prefixed versions, which I didn't want.
So, I created a new Mixin called 'background-linear-gradient' and I wanted to be able to control as many properties as possible from wherever I actually write my style. I wanted to provide fallback for older browsers that don't support CSS gradients, as well as making it suitable for all modern browsers. The Webkit announcement that they now opt for the Gecko syntax makes this easier as it's not totally necessary to provide alternative syntax for these browsers. This is what I came up with:
background-linear-gradient(startPoint, startColor, startInterval, endColor, endInterval) background-color startColor background-image -webkit-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -moz-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -ms-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -o-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image linear-gradient(startPoint, startColor startInterval, endColor endInterval)And this is the style declaration in my Stylus file:
background-linear-gradient(top, #FFFFFF, 45%, #000000, 55%)After testing in Firefox, Chrome, Opera and IE10 I was happy. Then I checked it in Safari…and it wasn't working. Unfortunately Safari 5.1 hasn't been released yet, meaning that my Safari 5.0.5 still requires the old Webkit syntax for gradients. I want it to work in the latest versions of Safari, so I decided to tweak my Mixin to allow additional support for optional deprecated Webkit syntax:
background-linear-gradient(startPoint, startColor, startInterval, endColor, endInterval, deprecatedWebkitStartPoint = false, deprecatedWebkitEndPoint = false) background-color startColor if deprecatedWebkitStartPoint && deprecatedWebkitEndPoint background-image -webkit-gradient(linear, deprecatedWebkitStartPoint, deprecatedWebkitEndPoint, color-stop(startInterval, startColor), color-stop(endInterval, endColor)) background-image -webkit-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -moz-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -ms-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image -o-linear-gradient(startPoint, startColor startInterval, endColor endInterval) background-image linear-gradient(startPoint, startColor startInterval, endColor endInterval)By utilising the Stylus logic within my Mixin, I can state that if no values are set for my Webkit-specific start and end points, then I don't want the old syntax output in my Stylus file. Therefore when I declare my style, I can either stick to:
background-linear-gradient(top, #FFFFFF, 45%, #000000, 55%)Whereby all CSS gradient-enabled versions of Safari below 5.1 will fall back to my plain startColor value, or I can add the extra parameters in:
background-linear-gradient(top, #FFFFFF, 45%, #000000, 55%, left top, left bottom)
And we now have full control over the gradients in older compatible browsers, as well as the most modern versions too.
So there we have it - a nice easy-to-use Mixin for the linear gradients you may want to use within your Stylus / Node / Other (delete as appropriate) projects. TJ Holowaychuk has also written an excellent extension to Stylus which does something similar - but for what I wanted, Nib seemed like quite a few extra files to add to my site, when I really just wanted to use a few lines of code to achieve my objective in this case.
Like what you've read?