Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

PrefixFree: Break Free From CSS Prefix Hell

This article is the first piece in our new series introducing new, useful and freely available tools and techniques presented and released by active members of the Web design community. Lea Verou is well-known for her experiments with CSS and JavaScript and in this post she presents her recent tool, prefixfree, which will hopefully help you break free from the CSS prefix hell.

So What’s the Problem With Prefixes? Link

I’m sure we all agree that CSS3 is pretty cool and that it enables us to do things that were previously impossible. But those of us who use CSS3 a lot have surely experienced prefix hell, as seen in the snippet below (from a real style sheet!):

.download {
   position: absolute;
   top: 1em;
   left: -1.5em;
   width: 6em;
   height: 6em;
   padding: 1em 0;
   background: #80A060;
   background-image: -webkit-linear-gradient(transparent, rgba(0,0,0,.3));
   background-image: -moz-linear-gradient(transparent, rgba(0,0,0,.3));
   background-image: -o-linear-gradient(transparent, rgba(0,0,0,.3));
   background-image: -ms-linear-gradient(transparent, rgba(0,0,0,.3));
   background-image: linear-gradient(transparent, rgba(0,0,0,.3));
   color: white;
   line-height: 1;
   font-size: 140%;
   text-align: center;
   text-decoration: none;
   text-shadow: .08em .08em .2em rgba(0,0,0,.6);
   -webkit-border-radius: 50%;
   -moz-border-radius: 50%;
   border-radius: 50%;
   -webkit-box-shadow: .1em .2em .4em -.2em black;
   -moz-box-shadow: .1em .2em .4em -.2em black;
   box-shadow: .1em .2em .4em -.2em black;
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
   box-sizing: border-box;
   -ms-transform: rotate(15deg);
   -webkit-transform: rotate(15deg);
   -moz-transform: rotate(15deg);
   -o-transform: rotate(15deg);
   -ms-transform: rotate(15deg);
   transform: rotate(15deg);
   -webkit-animation: none;
   -moz-animation: none;
   animation: none;
}

I’m not saying that prefixes are bad. We need them.1 But the reality is that, in most cases, they cause maintenance troubles, they bloat CSS files, and they make it harder to tweak values (because you have to do it up to five times).

A Solution: prefixfree Link

The code I write in my live demo slides and presentations doesn’t have any prefixes, even for things like @keyframes or the transition property, which aren’t yet supported anywhere prefix-less. To be able to do this, I wrote a script that detects the prefix of the current browser and adds it where needed. Recently, I thought, why not adapt the script to process all of the CSS code on a page, so that the CSS in my style sheets is as elegant as the code in my demos? Shortly after, prefixfree2 was born.

prefixfree3

The script essentially does everything in JavaScript’s power to allow you to completely forget about vendor prefixes. It processes linked style sheets (except the ones in @import rules), embedded style sheets, inline styles, even CSS added afterwards (such as in new elements, CSSOM property changes and lookups). And if, in rare cases, you want to use a different definition for a different engine (for example, because one’s implementation is buggy), you can still use prefixed CSS.

The good thing about prefixfree is that once the browser vendors drop their prefixes for CSS3 properties, you can just remove the script and your CSS will still work. Your code will continue to be valid CSS3 (so valid that it will even pass a CSS validator). Your code does not depend on it (unlike CSS preprocessors); rather, it functions more like a polyfill, smoothing out browser differences for the time being.

Another useful feature is that the script auto-detects which properties need prefixing. Its code has no property list. It detects which properties are supported and which of them are supported only with a prefix. Values, selectors and @rules are based on predefined lists, but they are still prefixed only when needed. No browser sniffing is involved; everything is based on feature detection.

prefixfree4

Unlike other solutions5, prefixfree adds the current prefix at runtime, so the user downloads a much smaller CSS file. Some might argue that pre-processed CSS is faster because no client-side processing is involved. To some extent, this is true, but in my experiments there was no significant lag. With the borderline exception of Opera, it was hardly noticeable.

Also, there are a few server-side solutions, but there are two main issues with those. Firstly, the file size of the CSS file is still huge, as it has to contain all the prefixes (and the unprefixed versions). And secondly, the server-side script has to maintain lists of properties at all times, because they cannot be automatically detected, like with prefixfree.

So, what does the rule above become with prefixfree? It becomes this beauty:

.download {
   position: absolute;
   top: 1em;
   left: -1.5em;
   width: 6em;
   height: 6em;
   padding: 1em 0;
   background: #80A060;
   background-image: linear-gradient(transparent, rgba(0,0,0,.3));
   color: white;
   line-height: 1;
   font-size: 140%;
   text-align: center;
   text-decoration: none;
   text-shadow: .08em .08em .2em rgba(0,0,0,.6);
   border-radius: 50%;
   box-shadow: .1em .2em .4em -.2em black;
   box-sizing: border-box;
   transform: rotate(15deg);
   animation: none;
}

Isn’t It Something That’s Better Done Server-Side? Link

This is a valid argument, and there are advantages and disadvantages to both approaches. Using a server-side script means that:

  • It has to be updated very, very often as browser support changes and prefixes aren’t needed any more. PrefixFree automatically detects what needs a prefix and what doesn’t.
  • All the prefixes need to be downloaded, which adds lots of bloat. In a medium size stylesheet, that’s far more bloat than the size of prefixfree.js.
  • In cases of preprocessors like LESS and SASS, you depend on their proprietary syntax, so you can’t just remove the script after a few years.

However, there are some benefits to doing it on the server-side:

  • It takes longer to download, but the user doesn’t see the un-CSS3-ed version of the style at all. With PrefixFree there will be a tiny delay.
  • It will work the same even when JavaScript is disabled. Although, with PrefixFree, if the JS is disabled, the user will just see the design without some CSS3, but it will still be perfectly functional. If your CSS is written correctly, the design should be functional without CSS3 anyway.

Personally, I think it boils down to a matter of personal decision and whether the advantages are more important for you than the disadvantages.

Download the Script on GitHub! Link

You can download prefixfree from GitHub6. The minified version is less than 5 KB, which becomes less than 2 KB after Gzip’ing. Please keep in mind that it’s still a very early beta and might have bugs. You can help fix them7, or at least report them in the issues tracker8. Have fun!

(al)

Footnotes Link

  1. 1 http://www.alistapart.com/articles/prefix-or-posthack/
  2. 2 http://leaverou.github.com/prefixfree/
  3. 3 http://leaverou.github.com/prefixfree/
  4. 4 http://leaverou.github.com/prefixfree/
  5. 5 http://prefixr.com/
  6. 6 http://leaverou.github.com/prefixfree
  7. 7 https://github.com/LeaVerou/prefixfree
  8. 8 https://github.com/LeaVerou/prefixfree/issues
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Lea is currently busy doing research in Human-Computer Interaction at MIT CSAIL. She has previously written an advanced CSS book for O’Reilly (CSS Secrets) and worked as a Developer Advocate at W3C. She has a long-standing passion for open web standards, and is one of the few Invited Experts in the CSS Working Group. Lea has also started several popular open source projects and web applications, such as Prism, Dabblet and -prefix-free and maintains a technical blog at lea.verou.me. Despite her academic pursuits in Computer Science, Lea is one of the few misfits who love code and design equally.

  1. 1

    cancel bubble

    October 12, 2011 7:47 am

    What I think is cool about this: It only sets the needed prefixes based on your browser.

    What I don’t think is cool about this: It’s dependent on JavaScript.

    Seems like LESS/SASS is the way to go, IMO. Although those include every vendor prefix, I’m not so sure file size difference is that big of a deal. Especially if you’re minifying/gzipping.

    Another thing, stylesheets are cached – this method has to reiterate on every single page load.

    1
  2. 2

    Wayne McManus

    October 12, 2011 5:38 am

    Wow this is great. Thanks very much.

    0
  3. 3

    I love the fact you are identifying a common maintenance problem and attempting to fix it. But I cant help shake the fact that using JS is the wrong way to solve it.

    You are placing additional load on the client to process it, the server to send the bigger files and introducing another chain in the rendering of the page.

    My preferred solution to this it to use LESS and LESS.APP on a mac. For .Net Builds I use DotLess on win. I assume there are similar methods for SASS, but i am not familiar with those.

    This way the file is compiled by LESS on save and no overhead is introduced, it keeps your files leaner and the code cleaner, this is also the reason i avoid the JS version of LESS. On a large scale website it introduces another layer of complexity that isnt worth the effort to solve.

    0
    • 4

      “the server to send the bigger files”? How exactly does the server send bigger files? One of the core benefits of prefixfree is that unlike preprocessors and server-side solutions, it actually sends much SMALLER files.

      Also, as for the strain on the client: Like I wrote in the article, the only noticeable delay in my tests was in Opera, and it still wasn’t that huge. It doesn’t really parse anything, just a few String#replace :)

      1
      • 5

        Sorry it was my mis-understanding that you had to create the bigger file first. I have just been re-reading the code and I understand my error :-)

        Out of curiosity did you notice any strain on the server with large css files vs smaller ones? I would expect it to increase as the size of the file does, but if as you stated it isnt causing a large issue in any way my other concern has been addressed.

        Please don’t mistake me for a troll I genuinely appreciate the effort you have gone to!

        0
      • 6

        It’s sending one much larger file — prefixfree.js.

        Even if your vendor prefixes are more than 5K (which is a lot), the client has to establish a connection to your server, parse the javascript, detect which properties are supported, then alter the page. You might not notice it on a desktop, but on a mobile, or using a 3G connection you certainly will.

        The place to do this is server side. Sniff the user agent if you need to.

        0
    • 7

      Yep, LESS and SASS ftw. With the right mixins you can save yourself so much time.

      0
  4. 8

    This is very interesting, I’ll definitely be taking it for a spin.
    Thank you @leaverou

    0
  5. 9

    well i do it like this.. i think this is better..

    div id=”nextcheck” class=”links modal gray menuitem corner15em shadow2px showdowtext1px cpointer” onclick=”checkBoxNextValue();”>Stap >> </div

    .gray{
    background: #a1a1a1; /* for non-css3 browsers */
    background:linear-gradient(top, #ebebeb, #a1a1a1); /* for css3 browsers */
    background: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#a1a1a1)); /* for webkit browsers */
    background: -moz-linear-gradient(top, #ebebeb, #a1a1a1); /* for firefox 3.6+ */
    -pie-background:linear-gradient(top, #ebebeb, #a1a1a1); /* css for ie browsers */
    behavior: url(ie8fixcss/PIE.htc);

    }

    .corner15em{
    border-radius: .15em;
    -khtml-border-radius: .15em;
    -webkit-border-radius: .15em;
    -moz-border-radius: .15em;
    behavior: url(ie8fixcss/PIE.htc);
    }

    etc….

    0
    • 10

      You are using presentational classes, which is universally considered a bad practice. If you ever want to redesign, you will have to change your HTML as well.

      Also, the un-prefixed version should be last, not first, so that it overrides the others if both are supported.

      1
  6. 11

    Alexander Nastase

    October 12, 2011 6:04 am

    This is amazingly helpful, in the past I used something calls CSS3-Finalized but didn’t work anymore and wasn’t this efficient I think…anyway amazing job thank you!!!

    0
  7. 13

    Or you could make your own Less mixins? http://lesscss.org/

    0
  8. 14

    Marco Barbosa

    October 12, 2011 6:05 am

    No offence but I think this is a very bad idea..

    CSS should never depend on JS for presentation purposes. Specially “just” because of vendor prefixes facilitation.

    Maybe an ant script with regex or a small Mac cocoa script would fit this better. LESS seems to do a good job with this as well (with the MAC app).

    Nothing personal Lea, I love your work! :)

    0
    • 15

      I have to say I agree with Marco. This undermines the separation of concerns that we have with JS / CSS / HTML. We used to include style information in pages (font tag, anyone?) but we broke it out with CSS. Introducing a dependency like this just doesn’t make sense to me.

      0
      • 16

        So you’re against Modernizr as well? Or CSS3PIE?
        Or any other script that helps with CSS?
        If so, PrefixFree is not your problem…

        0
        • 17

          I’m not against Modernizr particularly. The reason is that the CSS can still function completely without it, so in effect it allows a developer to augment what’s in the CSS.

          When you make your HTML or CSS dependent on JS to any degree it’s bad; where JS augments the HTML and CSS that’s good. Modernizr augments, PrefixFree is a dependency, and that’s why I am comfortable with the former and not the latter.

          0
          • 18

            I think we are missing a point here, as Lea mentioned in the article “It will work the same even when JavaScript is disabled. Although, with PrefixFree, if the JS is disabled, the user will just see the design without some CSS3, but it will still be perfectly functional.”

            It suggest that your CSS or presentation layer would work just fine and would not depend on javascript. But CSS3 features would not work if the JS is disabled.

            IMO, the person who has intentionally disabled JS would not mind missing some fancy features because he understands the cost of disabling JS.

            0
        • 19

          [quote]
          So you’re against Modernizr as well? Or CSS3PIE?
          Or any other script that helps with CSS?
          If so, PrefixFree is not your problem…
          [/quote]
          I fully agree.
          It’s not about the merits.

          Julia

          0
    • 20

      CSS should not depend on JS, you say?

      I see it differently: if the user deactivates JS then they get the purest standards-compliant CSS code there is, without vendor-specific workarounds. What’s wrong with that?

      In the end, it’s up to the browser makers to catch up. Why don’t we force their hand a little?

      I’m sick and tired of CSS preprocessing.

      0
    • 21

      It’s not a worse idea than vendor prefixes was. And it still degrades just fine. Don’t get hung up on standards just for the sake of standards, man.

      0
  9. 22

    For the most part I’m pretty much happy to just use the standard CSS3 properties in my CSS. The only hassle are things like gradients and I don’t find it too bad to add one or two extra variants just in those cases. Had I found this script a year ago I’m sure I’d be using it right now!

    0
    • 23

      Using only 2 prefixes in gradients isn’t good: You’re leaving out Opera and IE. In general, adding prefixes yourself almost always means you’ll forget some, as proven in this case.

      0
      • 24

        Nah. I typically leave out IE on purpose – Microsoft needs to conform to industry standards – the industry doesn’t need to conform to Microsoft.

        I check IE enough to make certain the interface isn’t broken and the content is acessible – the end.

        0
  10. 25

    This is really exciting! For those who prefer not loading another javascript, you could possibly supply the Prefixfree as a server side service. We upload our prefix-less CSS and download back a correctly prefixed CSS. But then you have 2 versions of the same CSS: one is the source for editing and the other for linking on the web page.

    0
  11. 26

    Stefan Bergfeldt

    October 12, 2011 6:12 am

    I love that you solve a common problem, but just like Vincent I’m uncomfortable with relying on Javascript for the design to work.
    Sure, most clients have Javascript support, and enabled, but still there are the few that doesn’t, and in some (in my case, almost every) cases you have to think about them as well.

    0
    • 27

      If you’re relying on CSS3 for the design to work, you’re going to have issues with old IE anyway.

      0
      • 28

        It’s not an issue with just IE. There’s people who prefer to disable JavaScript for other reasons. They are not a huge chunk, but they’re there. For example, the NoScript add-on for Fireofx has over a two million downloads. Nonetheless, this is a great idea. I might try it out on my personal site.

        0
        • 29

          I think you misunderstood what I’m saying. The site will display just fine to those without JS, it just won’t have some CSS3 fanciness (and only the experimental kind of CSS fanciness that’s only supported with a prefix). If the site is correctly designed, it’s fine without those as well.

          0
        • 30

          Francis Thibault

          March 20, 2012 11:52 am

          2 millions downloads means nothing btw what if all people downloaded but did not used it or like me are web designers and downloaded to test their website without javascript ;)

          0
  12. 31

    Interesting. Will definitely give this a go and do some tests.

    My current solution to ‘prefix hell’ is just writing SASS mixins for all the CSS3 properties I frequently use:

    .myClass {
    @include radius(3px);
    @include gradient(#eeeeee, #cccccc);
    @include box-shadow(1px, 1px, 5px, rgba(0, 0, 0, .2);
    }

    Etcetera, etcetera…

    0
    • 32

      @Mike, why don’t you used Compass that has all these mixins already there, plus so much more.

      0
      • 33

        How I wish I had more time to explore every framework out there. I’m sure you know what I mean ;)

        On my laundry list of tools to try out.

        0
        • 34

          Torkil Johnsen

          October 16, 2011 1:07 pm

          Mike, Compass uses SASS, so it’ll be like SASS, but with a lot of other goodies. Well worth investigating.

          0
    • 35

      ew lol you should check out Stylus, no funky syntax:

      box-shadow: 1px 1px 5px rgba(0,0,0,.2);

      can be defined as a transparent mixin if you use the nib extensions lib http://visionmedia.github.com/nib/

      likewise things like border-radius, gradients etc are written as regular CSS properties

      0
  13. 36

    Andy Pasztirak

    October 12, 2011 6:13 am

    I like the idea, however I have to agree with Vincent, I prefer running SASS+Compass in a CI environment to process my CSS files mainly because this solution while it might not have a huge effect on performance, it’s definitely a bigger hit than having a few lines extra in the prefixed CSS (which should be minified in the production environment anyway so aesthetics have little to do with them?), and it’s a hit on both the client and the server side too.

    0
  14. 37

    I agree with Vincent. I also use LESS with less.php, thus preprocessing on the server-side.
    When the browser downloads the page, if it encounters a script file, it stops rendering to process the js file, that’s why now we put JS at the bottom of the page. But CSS is in the head section, thus the browser renders the original css sheet, encounters the script and changes the rendering, this causes a kind of flickering on the screen…

    A most important problem you are forgeting is that some css3 properties are different between browsers:
    -moz-border-radius-topleft // -webkit-border-top-left-radius !

    Another big problem is the difference of the values between the browsers:
    -webkit-gradient(linear, left top, right top, color-stop(0%, #f00), color-stop(100%, #00f))
    is different from
    -webkit-linear-gradient(left, #f00 0%, #00f 100%)

    How do you solve these ?

    For me, the solution is LESS/SASS mixins.

    0
    • 38

      You can still use prefixed properties/values/anything, and PrefixFree will not change them in any way.

      0
      • 39

        Fine, I can use your snippet and don’t use it… With this I’m still stuck with one solution for some properties, and I have to find another one for other properties… not very productive: different technics (on both server and client side), more files, maintenance conflicts are coming…
        Sorry, I don’t subscribe.
        LESS/SASS mixins solve all CSS3 compatibility problems, not only the prefixes but also what I enlightened (different property names, different values for same properties etc.
        Have a look here : http://lesselements.com/, even if it’s not the most achieved.

        0
  15. 40

    I’m with the rest that think this is a very bad idea. Presentation shouldn’t depend on JS to work, ever.

    Nice try, but you can’t just fix everything with JavaScript.

    0
    • 41

      It’s only the CSS3 that depends on JavaScript, and only some of it. If your design relies on CSS3 to show properly, you’ll have bigger problems anyway :)

      0
    • 42

      I’m with Lea on this one. “Presentation shouldn’t depend on vendor-prefixed css to work, ever” – FTFY. If your site breaks without css3 support than you’re doing it wrong.

      0
  16. 43

    You should check out Turbine. It does the same and more, also with a css-reset rule default etcetc. If you like prefixfree, you will love Turbine.

    (i dont work for turbine, i work with turbine)

    0
  17. 44

    Jitendra Vyas

    October 12, 2011 6:29 am

    This is a good Idea for the maintenance and if you are already using HTML5 Shim, jQuery, Modernizer. then what is the problem of using it. If website is being viewed on browser where JavaScript is turned off. I think that users will also be not interested to see Advance CSS3 stuff.

    Great Work Lea Verou

    0
  18. 46

    Does it work with Less or Sass?

    0
    • 47

      LESS/SASS are usually on the server-side and PrefixFree works on the client side. I don’t see why there would be a conflict. :)

      0
  19. 48

    In CSS Crush (google it) — a PHP based, not client side preprocessor — there is an aliases file specifically for handling the vendor prefix problem.

    I prefer the power, reliability and efficiency you get with server-side preprocessing, though if there was a client side version of CSS Crush it would function a lot like PrefixFree

    0
  20. 49

    Robert Picard

    October 12, 2011 6:47 am

    I’d also recommend trying out http://prefixr.com/

    0

↑ Back to top