Important -prefix-free update

Those of you that have been following and/or using my work, are surely familiar with -prefix-free. Its promise was to let you write DRY code, without all the messy prefixes, that would be standards-compliant in the future (which is why I’m always against adding proprietary features in it, regardless of their popularity). The way -prefix-free works is that it feature tests which CSS features are available only with a prefix, and then adds the prefix in front of their occurences in the code. Nothing will happen if the feature is supported both with and without a prefix or if it’s not supported at all.

This worked well when browsers implementations aren’t significantly different from the unprefixed, standard version. It also works fine when the newer and the older version use incompatible syntaxes. For example, direction keywords in gradients. The old version uses top whereas the new version uses to bottom. If you include both versions, the cascade does its job and ignores the latter version if it’s not supported:

background: linear-gradient(top, white, black);
background: linear-gradient(to bottom, white, black);

However, when the same syntax means different things in the older and the newer version, things can go horribly wrong. Thankfully, this case is quite rare. A prime example of this is linear gradient angles. 0deg means a horizontal (left to right) gradient in prefixed linear-gradients and a vertical (bottom to top) gradient in unprefixed implementations, since they follow the newer Candidate Recommendation rather than the old draft. This wasn’t a problem when every browser supported only prefixed gradients. However, now that IE10 and Firefox 16 are unprefixing their gradients implementations, it was time for me to face the issue I was avoiding ever since I wrote -prefix-free.

The solution I decided on is consistent with -prefix-free’s original promise of allowing you to write mostly standards-compliant code that will not even need -prefix-free in the future. Therefore, it will assume that your gradients use the newer syntax, and if only a prefixed implementation is available, it will convert the angles to the legacy definition. This means that if you update -prefix-free on a page that includes gradients coded with the older definition, they might break. However, they would break anyway in modern browsers, so the sooner the better. Even if you weren’t using -prefix-free at all, and had written all the declarations by hand before the angles changed, you would still have to update your code. Unfortunately, that’s the risk we all take when using experimental features like CSS gradients and I think it’s worth it.

-prefix-free will not take care of any other syntax changes, since when the syntaxes are incompatible, you can easily include both declarations. The angles hotfix was included out of necessity because there is no other way to deal with it.

Here’s a handy JS function that converts older angles to newer ones:

function fromLegacy(deg) { return Math.abs(deg-450) % 360 }

You can read more about the changes in gradient syntax in this excellent IEblog article.

In addition to this change, a new feature was added to -prefix-free. If you ONLY want to use the prefixed version of a feature, but still don’t want to write out of all the prefixes, you can just use -*- as a prefix placeholder and it will be replaced with the current browser’s prefix on runtime. So, if you don’t want to change your angles, you can just prepend -*- to your linear-gradients, like so:

background: -*-linear-gradient(0deg, white, black);

However, it’s a much more futureproof and standards compatible solution to just update your angles to the new definition. You know you’ll have to do it at some point anyway. ;)

Edit: Although -prefix-free doesn’t handle syntax changes in radial gradients, since the syntaxes are mutually incompatible, you may use this little PrefixFree plugin I wrote for the CSS Patterns Gallery, which converts the standard syntax to legacy syntax when needed:

StyleFix.register(function(css, raw) {
	if (PrefixFree.functions.indexOf('radial-gradient') > -1) {
		css = css.replace(/radial-gradient\(([a-z-\s]+\s+)?at ([^,]+)(?=,)/g, function($0, shape, center){
			return 'radial-gradient(' + center + (shape? ', ' + shape : '');
		});
	}

	return css;
});

Keep in mind however that it’s very crude and not very well tested.

  • Anonymous

    Very elegant indeed. Thank you for the update.

  • http://jitendravyas.com/ Jitendra Vyas

    Please make it compatible with IE too, specially IE8 and below and with older syntax

    • http://grovman.pl/ GrovMan

      That’s not goal of prefix free. If you want CSS3 working with IE8 and below, try CSS3 Pie. http://css3pie.com/ (But IE isn’t worth)

  • http://croftmedia.co.uk/ Greg Tyler

    Thanks for keeping us informed! I’m so happy to see deprefixing; it’s nice to see stuff moving forward.

  • Scott

    Why the phrase “to bottom”? Seems more verbose and confusing to me. Not sure why we even need to have four directions, a simple “horizontal” and “vertical” with colours in appropriate order would be much clearer.

  • http://twitter.com/megasmack Steve Schrab

    Thank you thank you thank you! This and Modernizr are my most favorite JavaScripts!

  • http://twitter.com/WildWebWatch Hugo Giraudel

    Thanks Lea, and nice work. :)

  • Anonymous

    The newer w3c gradient recommendation will break many existing web apps :( And it’s not implemented in the latest Chrome.

    But your prefix-free rocks nevertheless ;)

  • Jackie Xu

    Time to update it is then. You might also want to update the link on your -prefix-free page.

  • http://www.facebook.com/david.hucklesby David Hucklesby

    You come up with things that are incredibly useful. Thank you so very much.
    Fortunately I have been using SVG for linear gradients, so this has not been an issue for me. But I am updating for sure. :)

  • Pingback: Weekly Web Developers Kit – vol. 19 (7-27-2012) | CSS Tips

  • Pingback: Weekly Web Developers Kit – vol. 19 (7-27-2012) | t1u

  • Pingback: DigestofinterestingnewsandmaterialsfromtheworldofITinthepastweeknumber16(21–27July2012) Web programming blog

  • Pingback: Дайджест интересных новостей и материалов из мира айти за последнюю неделю №16 (21 — 27 июля 2012) | wp2005 Дайджест интересных новостей и материал

  • http://twitter.com/crh0872 Caleb Hearon

    The syntax `background: -*-linear-gradient(0deg, white, black);` is not compatible with LESS, and is causing me some headache.

  • http://www.facebook.com/ofortier Olivier Fortier

    Hmm the original script works, but I couldn’t make the new update work.Don’t know what I did wrong, I just copied it exactly after the first script.

    • http://lea.verou.me/ Lea Verou

      Could you define what “doesn’t work” means? Which update do you mean? The radial gradient snippet?

  • zaqx

    First off, thank you for making this! I’ve used it on several projects now and it’s been a breath of fresh air to be able to write modern CSS to the spec without having to worrying about writing browser specific code.

    My question is: can prefix-free perhaps rewrite instances of ‘top’ as ‘to bottom’ and similar? I’m posting this now because I just discovered that since Firefox has unprefixed their gradients, writing with the old gradient syntax now breaks gradients there even with prefix-free loaded. That’s fine, sort of sucks, but makes sense (should’ve known spec was still changing). However I just wrote some gradients using the current candidate recommendation ‘to bottom’ instead ‘top’ and after hooking up prefix-free discovered they were still broken in Chrome. :( After reading your post I’m discovering that, because of this, writing multiple rules for browsers that have the same support is now unavoidable with prefix-free which is counter to the impression I had of the library allowing developers to write to the spec and ignore variations in implementation as long as the implementation exists.

    Sorry to bring back what is probably an old discussion for you. I’ve been using prefix-free for the last year and half on many different projects, I think it’s truly brilliant.

  • Tim

    Awesome. So just to confirm, if you always use deg. E.g.:

    background: linear-gradient(0deg, #18a0c5 0%, #2fb6db 100%);

    That will work in all browsers that support linear gradients. Correct? Seem pointless using any other unit in that case. :)

    As an aside, when declaring gradients, does it matter if you use background, background-color of background-image?

    Cheers!

  • drclue

    Seeing the various approaches to these issues is always rewarding and occasionally exposes useful concepts. Here prefixing or vendorisms are high crimes like treason. The sole js lib of ~700 lines deals with css remaps in ~15 lines during the first two readystates loading/interactive. The first page load after retiring jQuery had us all worried when from cache empty the page load went idle at 300ms.

    The lib’s CSS querySelector/All methods have changed the way a lot of things are done , accepting HTMLElements,Strings,RegExp etc and returning CSSStyleRule objects from the stylesheets making css3d , keyframes and the like actually low overhead code. Sorta cool for tweaking CSS designs without reloading too as it will happily spit out the CSS source once the realtime tweaking tastes right.

    Another weird side effect of going all in with the standards has been the counterintuitive result that as more functionality is added the filesize actually continues to drop, of course this is largely due to the fact that functions formerly taking up space in code have had their functionality offloaded to the standards whose logic is built into the browser.

    While I’ve always been partial to the standards, this project has added a whole new dimension to that appreciation