Stop Forking Around with CSS3
Issue № 308

Stop Forking with CSS3

It seems like virtually every day there’s a fantastic new example of something amazing you can do with CSS3. Whether it’s as complex as full-blown animations or as (relatively) simple as RGBa colors, drop shadows, or rounded corners, I marvel at how far we’ve come since the lowly days of CSS1 or (shudder) the @font element.

Article Continues Below

The current state of CSS3 reminds me of a typical cinematic device: The scene opens with us, this happy-go-lucky family of developers out for a picnic by the lake on a beautiful summer afternoon. And as we laugh, play, and scamper about entertaining ourselves, the camera pans around, bringing us over to the lake where, beneath the surface, something stirs. Something ominous and foreboding.

Okay, perhaps that was a bit over-dramatic, but what I’m trying to say is that we’re ignoring the beasts within our code, hiding just out of view: forks.

What?#section2

If you’ve been working on the web for more than a decade (I’m probably dating myself), you may remember that bleak time in web design history when JavaScript was a dark art. It earned that reputation because in order to do anything with even the teensiest bit of cross-browser consistency, you had to fork your code.

It was standard practice to have one set of JavaScript functions for Netscape and another set for Internet Explorer. Or, if you were a real masochist, you kept the code combined and created a fork inside the function:

function doSomething(){
  if (document.getElementById)
  {
    // web standards FTW!
  }
    else if  (document.all) 
  {
    // do something in IE
  }
    else if (document.layers)
  {
    // do something in Netscape 4.x
  }
}

In many cases, especially where animation or event handlers were concerned, the code got really gnarly, easily topping even the most atrocious spaghetti code in HTML. The thing about forking your code is that, when you least expect it, it will find a way to fork you right back.

Now, thanks to Web Standards Project browser-standards advocacy and diligent JavaScript library authors, the world of JavaScript is a much nicer place to work and play. Our code is now relatively fork-free, with fewer nooks and crannies in which bugs can hide. Unfortunately, in our rush to use some of the features available in CSS3, we’ve fallen off the wagon.

I think @border-radius was the proverbial “candy” that the forks used to lead us back into their clutches. We all wanted them; hell, we’d come up with myriad ways to fake rounded corners to realize our design dreams. So when Firefox and Safari dangled them in front of our drooling faces, asking only that we add two small forks to our code for the privilege, we jumped at the opportunity.

.this-is-awesome {
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
}

They were only two small forks, after all, how bad could they be?

Well, once we had symmetrical rounded corners, we wanted asymmetrical rounded corners. After all, we need to be able to express ourselves and there comes a time when every man, woman, and child must stand up and set the radius of each corner independently! Unfortunately, Webkit doesn’t like the @border-radius shorthand, but that just means we need to be a little more verbose:

.this-is-slightly-less-awesome {
  border-radius: 10px 5px;
  -moz-border-radius: 10px 5px;
  -webkit-border-top-left-radius: 10px;
  -webkit-border-top-right-radius: 5px;
  -webkit-border-bottom-right-radius: 10px;
  -webkit-border-bottom-left-radius: 5px;
}

Oh, and we probably want to make sure Opera and Konquerer can get the rounded corners too (assuming Opera’s supporting them this week).

.this-is-absurd {
  border-radius: 10px 5px;
  -moz-border-radius: 10px 5px;
  -webkit-border-top-left-radius: 10px;
  -webkit-border-top-right-radius: 5px;
  -webkit-border-bottom-right-radius: 10px;
  -webkit-border-bottom-left-radius: 5px;
  -o-border-radius: 10px 5px;
  -khtml-border-top-left-radius: 10px;
  -khtml-border-top-right-radius: 5px;
  -khtml-border-bottom-right-radius: 10px;
  -khtml-border-bottom-left-radius: 5px;
}

Now, are you seeing a problem here? Does it remind you of anything we used to do in our CSS?

.can-you-hear-me-now {
  padding: 10px;
  width: 200px;
  width: 180px;
  height: 200px;
  height: 180px;
}

Or perhaps you were more fond of something in a nice Tan.

.hooray-for-repetition {
  padding: 10px;
  width: 200px;
  height: 200px;
}
* html .hooray-for-repetition {
  width: 180px;
  height: 180px;
}

Call it forking, call it hacking, call it what you will; we shouldn’t be doing it.

Another way#section3

As you can probably tell, forks get me a little riled up. Rather than just getting angry about it, however, I decided to build a JavaScript library that supports clean living (or at least clean CSS): eCSStender. (Actually, the original impetus behind the library was a little different, but we’ll get to that in a bit.)

Boiled down to its essence, eCSStender (pronounced “extender”) is a JavaScript library (akin to jQuery or Prototype) specifically built for working with CSS. On its own, eCSStender doesn’t do anything but analyze your stylesheets. When powering “extensions,” however, eCSStender allows you to use properties such as @border-radius and selectors like @.seven:nth-child(even) without having to resort to forks or hacks.

If you’re developmentally inclined, you’ll be interested to know that eCSStender not only gives you introspection into the style rules contained in your CSS file(s) and provides a framework for testing a browser’s support (or lack thereof) for things like selectors or properties, it also provides a mechanism for you to patch browser support for CSS.

If, however, you’re more inclined toward the design side of things, you’ll be happy to know that using eCSStender and a handful of extensions allows you to write advanced CSS simply. It Just Worksâ„¢.

.this-is-so-much-better {
  border-radius: 5px;
}

Using eCSStender#section4

Using eCSStender is pretty straightforward. You simply include the eCSStender library and whichever extensions you want to run against your CSS.

<script type="text/javascript" src="eCSStender.js"></script>
<script type="text/javascript" src="eCSStender.CSS3-backgrounds-and
-borders.js"></script>
<script type="text/javascript" src="eCSStender.CSS3-selectors.js">
</script>
<script type="text/javascript" src="eCSStender.CSS3-color.js"></script>

Or, you can pick and choose the pieces you want from the currently available extension bundles and create your own custom extension library.

<script type="text/javascript" src="eCSStender.js"></script>
<script type="text/javascript" src="my-extensions.js"></script>

So where do you get these extensions? Well, I have developed a number of extensions that offer CSS3 functionality and have bundled them such that they correspond to the various modules of CSS3, such as borders and backgrounds, selectors, and color. I am also aware of several other JavaScript wizards who are working on other pieces of the CSS3 puzzle, including a multi-column layout and more. A complete list of known extensions is being maintained on the eCSStender website and, if you’re interested, the website also has extensive documentation on how to roll your own.

Once you have included the JavaScript files, you simply go about using the properties as the spec defines them, and the extensions work their magic to translate what you wrote into something browsers understand. The beauty of this setup is that your stylesheets remain clean and fork-free; the extensions do all the dirty work for you.

Extensions are built to be smart, too. Using the eCSStender API, they can test to see whether or not the property or selector you want is supported in the current browser. If the property is supported, the extension doesn’t run, but if it isn’t supported, the extension is activated. So in the case of border-radius, Safari 5 implements the standard property and the border-radius extension is not run, but in Safari 4, which only understands -webkit-border-radius, the extension needs to run and makes the necessary translations. Once the majority of browsers accessing your site are savvy enough to grasp standards without the hand-holding, you simply delete the extension just as you would a conditionally-commented stylesheet for a version of IE you no longer need to support. Easy-peasy.

You’d probably like an example, right? Well, the eCSStender site is certainly one, but I’ve thrown together another one on the off chance you’d like to see a combination of CSS3 goodies in action. It makes use of:

  • @border-radius,
  • @box-shadow,
  • RGBa backgrounds,
  • @transform: rotate(), and
  • @transition (assuming your browser supports it in some form).

Make sure you hover the box.

Yeah, but “extend”-er?#section5

As I mentioned earlier, eCSStender was not originally designed to act as browser spackle; in fact, the original intent for the library, when I began writing it nearly three years ago, was to make it easy for each of us to get involved in crafting future versions of CSS. Through eCSStender, we can play with new ideas and see our concepts realized in an actual browser. It provides an easy way for us to experiment with syntax and see what works and what doesn’t without having to wait for native browser support.

If you’ll indulge me for a moment, I’ll give you an example. Say, for instance, I thought it might be interesting to imbue elements with physical characteristics and I wanted to use CSS to do it. I might create a new property (with a vendor-specific extension of “easy,” to indicate my company) called @-easy-physics-fill that would take one of several substances, such as “lead,” or “helium,” as its value. With eCSStender I can easily build an extension to look for that new property and apply the requisite physical properties. It’s a contrived example, but I think you get the point.

Used in this way, eCSStender empowers us to show the W3C what we want to see next in CSS. And it can help the CSS Working Group evaluate syntax and experiment with new ideas without having to wait for a browser vendor to implement them. This could streamline the process, as ideas that don’t work well in practical application can be jettisoned before the underlying codebase of any browser has been modified. And who knows, maybe the W3C would even consider an extension to be a valid implementation used as part of the standards-development process.

Pitching the forks#section6

As a library, eCSStender has a few modest goals. First and foremost, it aims to offer robust tools for designers and developers to make working with CSS better.

On one hand, it seeks to equalize support for CSS across all browsers by offering a simple set of developer tools that makes crafting extensions easy and implementing them a breeze. On the other, it provides those same tools to designers and developers who are interested in conceiving and then building real implementations of the properties, selectors, and mechanisms they want to see in future versions of CSS.

Perhaps my dream of a world with equalized CSS support across browsers is pie-in-the-sky thinking, but I like pie. Even if it is best eaten with a fork.

61 Reader Comments

  1. I was just thinking why nobody has done something like this before while reading the Modernizr article.

    I was just wondering, is the eCSStender website on a really slow server because everytime I load a page in Firefox it get’s stuck on your main.js file. Or does it just take so long to process the css?

    I would love to use this script, but only if it is stable and fast enough for real-world use.

  2. Surely whether through Javascript or just normal CSS you are essentially just doing the same thing though. Making Javascript fork the css for you doesn’t make the problem go away.

  3. In line with Narfotics comment, how does Modernizr and eCSStender work together? Or on the other hand – do they cancel each other out? Looks like two nice solutions to the same problem, but in two very different ways. Would love to have the authors take on that.

    Thanks for the nice article!

  4. I like the look of this library. Reminds me of the old “IE7 library”:http://code.google.com/p/ie7-js/ (back before IE7 came out). But this library seems more modular and flexible.

    I think the biggest concern is performance. Would love to see some numbers that address that concern. Also, does the library have a case of “flash of unstyled content” before the JS kicks in?

    Your website mentions that border-radius is only supported on browsers that have native support. You might want to look at “curved-corner”:http://code.google.com/p/curved-corner/ which provides border-radius support for IE 6/7. It is not perfect but might provide a good start (I have noticed it is flaky on some layouts that using lots of CSS positioning, flaky on pages that dynamically change their content and doesn’t support asymmetrical corners but all that could be fixed).

  5. Great work Aaron! A solution like this is overdue – and represents the ideal from a development perspective; write clean CSS code and parse a mess to deal with browser quirks.

    I have to agree with the other commenters on the pageload issues. Right now, it seems slow to render the CSS each time. Might it be possible to capture the final CSS rendered by browsers and serve the cached browser appropriate CSS files?

    Looking forward to using your solution.

  6. Has anyone else tried this? It looks like a miracle. But, the demo’s box-shadows don’t work in Safari 5. They work in Firefox, Opera, and OmniWeb. I tried implementing the border-radius extension on our company’s website, but it didn’t do anything in IE8 or Opera. Perhaps I’ve missed something along the way.

  7. While I think the idea is good, I don’t think it is necessary or efficient enough for use yet. Yes, it saves the developer some time and cleans up our CSS a bit, but we are now adding 12+ kb and the time it takes for the JS to parse possibly large CSS files.

    Even on your site there is a long flash of unstylized content in Firefox for me. While this may get picked up by a few developers we can’t assume widespread adoption so can’t expect it to always be cached in the browser (like jquery). I don’t like the idea of adding new flashes of unstylized content to my designs.

    Also, I don’t think the forking of css is nearly as bad as forking JS used to be. You can easily delete any of the browser-specific forks with a simple regex search-replace that many/most editors can do today.

    Since a lot of people are already running their CSS through minifiers these days, I wonder if it is a better idea to create a minifier that automatically parses and adds your browser-specific definitions to a new css file. That way you will have your main CSS file, free of any forks, and can serve a minified, fleshed out (oxymoron, I know, but you get the idea) version of your CSS file to your users. No ugly forks in your main css file, no flash of unstylized content, and no added weight from new js files to your page.

  8. Very interesting article. While I will agree that what you call “forking” in CSS3 bothers me, I can’t quite wrap my head around using javascript to get around it. You are basically doing the “forking” in js instead of the CSS. I’m struggling to see what the difference would be. You are just changing where the “fork” takes place. Why add scripts to your page and just deal with the browser specific styles on a sheet you were going to include anyway? Still, this was a very good read.

  9. Just to note, internet explorer is still the most used browser (if you put ie6 plus ie7 plus ie8 market quote), and if you work with medical related websites, you should multiply those percentage.
    So still a limitation for us, there is no “stop forking” ready yet.

  10. This looks like a very useful solution. I just read an “article”:http://fadeyev.net/2010/06/19/lessjs-will-obsolete-css/ today about LESS, another way to extend CSS. It also seems very cool. But I have to wonder what sort of a performance hit my sites will take if I keep adding these cool libraries to my pages. JQuery is usually about as much javascript I really want to make my users download, since they’re now also downloading fonts too.

    It seems like these CSS code forks are a small annoyance. Making people download another .js file (or set of files) to fix them seems like big-time overkill to me, since it seems to slow the page load. As Jakob Nielson put it this week, “users _really_ care about speed”:http://www.useit.com/alertbox/response-times.html . And if I have to fork a bit of CSS to maintain it, then I’m probably okay with that.

  11. @djDesigns: I think the idea is to encapsulate the CSS3 browser differences and hide them in a JavaScript library. Then you can write code like you had a CSS3-compliment browser.

    Further, if W3C adopted this methodology then they could approve a specific module which simulated a specific CSS3 feature, this would give an unambiguous (or at least less ambiguous) specification of that figure, one that is less open to the vagaries of interpreting English text.

    But, alas, we all know that’s never going to happen.

    My course of action will be to wait five years until CSS3 is solidly implemented before I start to use it.

    Peace,

    Rob:-]

  12. I definitely hear you all that performance is crucial and it’s something we’ve been taking very seriously with eCSStender. I’ve thrown together “a write-up on the optimizations eCSStender has built-in”:http://ecsstender.org/documentation/optimizing-performance and I’d like to point out that the flash of “unstyled” content is, in most cases, a part of the page rendering process and likely has more to do with size of the CSS being parsed, the number of CSS files being included, and the extensions in use than the eCSStender core itself. The greatest culprit of those is probably the extensions.

    As optimized as eCSStender is (although there’s always room for improvement), it relies on optimized extensions as well. It’s like using an inefficient jQuery plugin or writing native code that isn’t optimized. If there’s a memory or efficiency issue or if the script blocks rendering for a bit or if the script causes too many repaints or reflows, it’s going to be an issue no matter how optimized eCSStender is. This library (or any library for that matter) won’t be able to address the problem of inefficient code that uses it.

  13. but I’m also having problems with the demo page in different browsers. Safari 5.0 does not have a drop shadow on the boxes. Firefox 3.2.3 doesn’t animate the box rotation. Also, I can’t see the ‘download’ button on the eCSStender home page (maybe you are moving the image to a different server?).

  14. if you are advocating removing the forks from CSS files wouldn’t the last section of the article and the idea for developing eCSStender in the first place have the same effect as many forks in the CSS file? They are then just vendor specific, where the vendor is the developer or extension, so your CSS file would then be littered with extension specific references, correct? Obviously it is some what different because they aren’t browser specific forks trying to accomplish they exact same thing.

  15. The article conflates vendor specific extensions with CSS hacks that rely on vulnerable CSS parsers. I think this is a mistake. Vendor specific extensions are invalid but only because they use property names that are outside the CSS standards. However, the standard allows vendor specific extensions and states that if they begin with a hyphen, they can be parsed and ignored.

    See http://www.456bereastreet.com/archive/200911/vendor-specific_extensions_are_invalid_css/

  16. bq. Just to note, internet explorer is still the most used browser (if you put ie6 plus ie7 plus ie8 market quote), and if you work with medical related websites, you should multiply those percentage.

    And that’s why many extensions are working to back-port things like full CSS3 selector support for IE. You’ll also find that that things like CSS rotation do work in IE6. We’re still working on a solution for dynamically managing an @-ms-filter@ stack, which is why the spoon demo won’t currently work in IE, but we’ll have a solution for that in eCSStender 1.3.

    bq. Safari 5.0 does not have a drop shadow on the boxes. Firefox 3.2.3 doesn’t animate the box rotation. Also, I can’t see the “˜download’ button on the eCSStender home page (maybe you are moving the image to a different server?).

    I can’t replicate the Safari issue you’re having on Mac or Windows (Safari 5 did change some innards of its @box-shadow@ support between 4 and 5, but we patched that in the extension). Chrome seems to suffer from that problem though (but Android, Dolphin, and xScope on my Nexus One don’t… go figure). Perhaps a refresh will fix that for you?

    As for Firefox… Firefox doesn’t support CSS transitions in that version (or any non-beta release AFAIK). Some smart folks are working on extrapolating the simple extension I put together into a more robust JS-based animated fallback as we speak.

    And on the download button… that was the issue, yes. It should be there now.

    bq. if you are advocating removing the forks from CSS files wouldn’t the last section of the article and the idea for developing eCSStender in the first place have the same effect as many forks in the CSS file?

    If it is the only implementation of something experimental, there are no forks to be had. Just as @-ms-filter@ is not a fork (no other browser that I’m aware of implements filter either with or without an vendor-specific prefix), neither is @-easy-physics-fill@.

    bq. The article conflates vendor specific extensions with CSS hacks that rely on vulnerable CSS parsers. I think this is a mistake. Vendor specific extensions are invalid but only because they use property names that are outside the CSS standards.

    I never said they were _invalid_, I simply think that having to write the same thing 3 different ways is _undesirable_. eCSStender is not an attempt to jettison vendor-specific prefixes, far from it. eCSStender is about making things better for designers from an authoring standpoint by equalizing browser support, back-porting newer CSS functionality to older browsers, and creating a mechanism for experimenting with the future of the language.

  17. I totally agree that we should try and keep things together instead of the madness of the way that JavaScript went in IE/Netscape etc. but remember all these prefixes -webkit-border-radius and -moz-border-radius are used _in the meantime_ until the standards settle down, they only take the prefix off when it is standardised (and they will then follow the real border-radius property). This is so you can test the functionality while it is still fluid, the plan is not to have multiple implementations in the future all with similar names. The difference with the JavaScript comparison was that this was how things worked, there was no standardisation.

  18. CSS3 for older versions of IE and cleaner CSS code is awesome-ness, though I don’t see myself using it on projects with larger style-sheets, but I believe it will be a great way to demo CSS3.

  19. The spirit of this article is understood, but the examples let it down. Opera and WebKit browsers support border-radius without prefixes, and according to the spec; so you only need to specify:

    -moz-border-radius: 10px 5px;
    border-radius: 10px 5px;

    I think prefixed properties are an important part of getting CSS implemented faster, and as long as it is well understood that they are subject to change then they can be used – sparingly – in many (but not all) production sites.

  20. I echo the previous comments about the shadow and black border colour not showing up in Webkit browsers on OS X. I checked in Webkit nightly (6533.16, r60742) and Chrome (5.0.375.70).

  21. While I do agree with part of this concept, I am hesitant to implement it as this is just one more piece of JavaScript for my page to rely on. At this point, I don’t write enough CSS3 in my sites to justify the use of eCSStender. I would rather write a few extra lines in my CSS and just remove them when CSS3 becomes more straight forward in browsers. It seems like we are just trading cleaner code for another file to rely on.

  22. Kudos for the noble intentions, but I agree with a lot of the other comments above. We rely on javascript way too much as it is, I don’t think this is worth the extra page weight.

  23. Like jquery, I think this is a great idea. However one huge question comes to mind… What if the end user has javascript disabled?

    Sure, you can have a custom message that states you’ll have a better viewing experience if you have javascript turned on. But from a designer stand point, I’m looking at the type of end user that isn’t tech savvy enough to say “Ah, ok! Hey, now the site doesn’t look broken anymore!”

  24. This is exactly what I’ve been looking for for ages; something that allows me to write code semantically without the annoying forking that I’ve been having to do. Going to take a little time out of my working day to look over the JS and see if it’s what I’m looking for.

    Just a side note, there’s a typo on the second bit of code under the header “Using eCSStender” where you’re explaining that one could create a custom extension library – instead of saying <script> it says <scrip>. Feel free to delete this part of the comment when the typo is amended.

  25. I was wondering if there was a way to make CSS3 work on all browsers. If flash can do it why couldn’t CSS?

    Implementing this through Javascript is even better, the users don’t even have to install any plugin.

    However the working example isn’t really… working. I’ll be checking the download link until I manage to get the libraries, I’ll test them in all major browsers including IE6 on Windows XP or Firefox on Ubuntu.

    I’ll post the results here, that’s if I ever manage to download the scripts 🙂

  26. As posted in the “eCSStender FAQ”:http://ecsstender.org/faq and in response to several comments:

    As much as we’d love to say everyone should be using eCSStender, it’s just not practical in many instances. The following are a few reasons eCSStender may not be a good choice for you:

    * You use CSS3 selectors and properties sparingly (e.g. you only use border-radius in a handful of places and that’s it)
    * You don’t care about backward-compatibility (e.g. IE6 is a not-so-fond, but rather distant memory)
    * You aren’t looking to use the extensions to CSS that are available.

    Reasons you may want to use eCSStender include:

    * You use CSS3 all over the place and need backwards compatibility with older browsers (e.g. you want your CSS transitions to work in IE6 so you don’t have to learn JavaScript).
    * You want to take advantage of cutting edge enhancements or proposed additions to the CSS language (e.g. OOCSS, CSS variables, etc.).

    When it comes down to it, there’s a trade-off of file size and flexibility. eCSStender currently weighs in under 20K (before GZipping), but you also need to factor in the size of the extensions as well. It’s a small performance hit (especially if you munge the minified files together and serve them over a CDN), but it’s probably not going to balance out minimal use of advanced properties.

    If you’re considering using eCSStender to get away from vendor-specific prefixes, we’d recommend taking your non-prefixed stylesheet and giving eCSStender a whirl on a dev server. You can, using a developer toolbar of some sort, copy out the content of the stylesheets it embeds in the document and add those rules to your CSS file, comment out eCSStender, and see if there’s a noticeable speed improvement.

  27. I liked the article, and thought it was a certainly a possible solution if combined with Modernizr. However, when I started to try it, the support for properties like border-radius and box-shadow is not consistent at all. And the point of the project is pretty much lost that way, at least in my opinion.

  28. There’s been a ton of debate over the necessity of vendor prefixes, so I thought it worth mentioning that I don’t think vendor prefixes are inherently bad. They serve a very important purpose: allowing implementors (the browser makers) to develop their implementations to track an evolving spec while giving them the leeway to get things wrong during that process.

    eCSStender is not an attempt to get rid of this necessary step in the process (in fact it fosters more people’s involvement in the development of experimental CSS). This library does, however, allow us to even things out the authoring side when it comes to these disparate implementations, leaving it to the extensions themselves to deal with the juggling act of serving the appropriate rules to the appropriate browser. From an author’s perspective (that’s you and me), having to write the same thing umpteen different ways (especially when it involves having to manually overcome incomplete or botched implementations) is an issue we shouldn’t have to deal with. That’s where eCSStender really helps: it makes it possible to write a single rule and leaves it to the extension to make it work everywhere.

    So, in summary, I’m not against vendor prefixes as a tool, I just think we have enough other things to worry about that we should not have to constantly tweak our stylesheets as vendor-prefixed implementations change (which they do). JavaScript is great at doing mundane tasks like that.

  29. Main problem: my Firefox freezes for 10 to 25 seconds when loading *your* website. Not a network/CDN issue.

    Also: maybe you’re introducing “leaky abstractions” to prevent “forking”? ie, fixing the “CSS purity” problem with a tool that’s probably beyond the skillset of many a CSS coder if something goes wrong.

    Using this to prototype CSS extensions sounds cool though.

  30. I don’t see the point in the eCSStender, since it doesn’t seem to work: IE7, IE8 don’t show rounded corners, neither on the eCCStender-site, nore on the ALA-demo-site.

  31. I’m been a bit perplexed at why you would want to use any of these hack CSS3 declarations in the first place. Right now too many browsers don’t support CSS3, and therefore you shouldn’t use them.

    I can’t imagine telling a client that their site looks great in modern browers but the people that visit the website that use older browsers will get a less aesthetically pleasing site. Clients just don’t accept this and furthermore I don’t. Each user should be given the best experience possible no matter what browser they use (unless it’s something like ie 5).

    I ensure my websites look great in all browsers and therefore at this time you have to use background images for rounded corners etc (sprite them if you wish).

    So overall eCSStender is a great plugin despite it not working that well and is slow. But the problem they it is solving is one that shouldn’t even be used in the first place.

  32. I mean, get serious! Most of the untidyness problems of those CSS forks are only of concern to the development. Therefore, the correct solution for this problem is not in the client, but in the deployment process.

    So, what is really needed: a versatile filter framework for deployment of CSS, with the ability to expand those (and other) shorthands – and while we’re at it, to clean those comments you do not want the world to see, put multiple files together and minify the CSS if necessary. And btw, a JS version of such a framework would be useful, too.

  33. Good concept but the eCSStender example page (Spoooon) looks very different in different browsers. It looks great in Safari and very good in Chrome (no drop shadows). There are drop shadows in Opera, but the action of the color boxes is not smooth. With Firefox, there are white letters against a blue square and no moving color boxes. IE 6 cuts off some letters, which are located in the upper left corner, with no color or moving boxes on hover.

  34. I’m sorry, I appreciate the want by some to indulge in extending CSS, but aren’t what is referred to as hacks actually standards compliant vendor prefixes that will eventually dissappear once fully integrated to the specific browser that simply allow for the vendors (and experimental coders) to start testing these new additions to the CSS fold?
    I just feel the hack comparison slightly misplaced, although I concede for the time being the code looks bloated, it is neither ‘forking’ or ‘hacking’.

  35. HI Aaron

    I’m not sure it’s a good idea to hide away vendor prefixes. They are there precisely because some people want to use experimental CSS, like border-radius for example. WebKit and Firefox used different syntaxes precisely because the spec was still in flux, and they correctly used vendor prefixes as this was an experimental implementation. (Opera, by the way, has supported border-radius reliably since version 10, without any vendor prefix and using the final syntax.)

    Other uses of vendor prefixes are for proprietary vendor extensions to CSS, such as gradients. Again, WebKit and Firefox have non-interoperable syntaxes so vendor prefixes are the only way to make sure that each gets the right rule.

    Developers should use each vendor prefix in their code; I advise writing the declarations in alphabetical order (so -moz-, -ms-, -o-, then -webkit-) and finally having a declaration with no vendor prefix, for future browsers that support the final standard. Sure, there’s a risk that the standard might change but if you don’t use the non-prefixed version, you are guaranteed to lock out other browsers – in the same way that if your code doesn’t use plain border-radius, you *guarantee* that it will not work in IE9.

    This is a developer’s responsibility. If you as a developer choose to use experimental, pre-standardised code on a production site, then you need to live with the consequennce of that choice.

  36. I have read all 5 pages of comments and I think a little controversy is good. Let’s everyone know there is a viable issue at hand. Many good points. This banter reminds me of something else… the screen resolution debacle.

    I was going to JS-Fork a website for North American audiences vs. “Global” audiences because I mistakenly believed that there needed to be smaller screen res for the Global community. Turns out that on average, it is the Americans using the highest % of 800×600. In that discussion, several “experts” stood firmly by the 760 for websites – in 2010! Others argued the fluid layout rule. Seems many people can’t maintain “enough” flexibility, combined with “enough” ingenuity, combined with enough “common sense” to render a real decision about the value of a given technology.

    I love the “functional” arguments whose thrust seems to be educating others how this library will function case-specific for them. Function is an Applied Science, not a Pure one.

    I think the library is a great idea which hits its mark and performs a valid service to the much sought after styling of the day. By the time there are standards for border-radius, the hype over rounded corners will be over, (I am using square and round alternating corners for a balanced, masculine/feminine appeal) and it will be left to a designer to express (semantically) what should be either function or fancy.

    In the meantime, tools help take the bleed out of the cutting edge. Thanks, Aaron.

  37. Any time you can move complex work to the server side, you’re going to get a speed improvement and we may add in some server-side components down the line (we’re certainly not ruling it out), but when most people ask this question, they’re weighing eCSStender against a CSS pre-processor like Sass or Less.

    Putting aside the debate over whether alternate CSS syntaxes are better or easier to use, there are definite advantages to using a tool that can translate one syntax into another (as some extensions do), but when your solution is 100% back-end, it does not allow for nuance and interpretation, which is where eCSStender excels.

    At the core of eCSStender’s power is the @eCSStender.isSupported()@ method. This method allows a developer to test for property and/or selector support and then act upon their findings. Using this method, an extension can see that Safari 4 (and other Webkit-based browsers of its generation) doesn’t understand border radius shorthand with unequal radii (e.g. @border-radius: 2px 4px;@). If your preprocessor only knows to translate @border-radius@ to @-webkit-border-radius@, @-moz-border-radius@, etc. and isn’t aware that it also needs to check the values and make further augmentations for Webkit, that’s a problem. And, if your preprocessor is pushing all of that extra markup over the wire, regardless of whether it’s useful to the browser, that too can become a problem.

    Additionally, a pre-processor can’t leverage that nuance to implement JavaScript-based animations as an alternative to CSS-based ones if they aren’t supported because the pre-processors (as they are currently built) take a “one size fits all” approach to handling CSS: everyone gets the same thing. Then there’s also the fact that eCSStender can help you implement a new property or concept you’ve conceived and make it work in the browser in a much more robust way.

    There are definite advantages to using a CSS pre-processor, but nuance and conditional translation/augmentation is what makes eCSStender different.

  38. Unfortunately, IE’s support for advanced things like rotation, gradients, etc. relies largely on the non-standard @filter@ property in CSS and, like CSS shorthand, any time you set @filter@ to a new value (which each extension currently tries to do) it supplants anything that was there before instead of adding it to a stack (which is what we really need to happen). We’re currently looking into this limitation and are working with the IE team to figure out the best overall approach to allow access to and manipulation of the filter stack (so we can enable animation of these properties, for instance).

    It’s a bit much to wrap my head around at the moment, but I assure you it’s in the works. That said, most of the extensions out there work fine in IE. The only place you run into issues is where you have a combination of properties that need to write to @filter@ being applied to the same element. That’s what’s happening in the case of the Spoon example.

  39. So to clean up the messy CSS with -webkit, -moz vendor specific properties, we add a Javascript? What good is that going to do?

  40. Even though the idea sounds great, I think there is still a way to go. Because eCSStender is 18kbs now but all the weird css in the article has been exampled only takes 726bytes. If we multiply that with 10 bordered stuff in a webpage (who would do that?), that means 7kbs, which is still lighter than the eCSStender. I’d advice a jquery (or any other library) version of it or an implementation in jquery code as default which would be greater.

    And an advice, I put these redundant CSS3 and CSS hack stuff in a seperate CSS (or seperate from all other ids’,classes) so when browsers update themselves and become CSS(and)3 and W3 compliant, you can easily get rid of them.

  41. Aaron, thanks for the explanations in comment 32. I can see that eCSStender could be overkill in some situations, while being very useful in others. It’s good to consider it on a case-by-case basis.

  42. Regarding vendor prefixes, the following has been echoed many times:

    bq. when browsers update themselves and become CSS3 and W3 compliant, you can easily get rid of them

    That will be true at some point, but depending on how far back you may need to support certain browser versions, you may have those prefixes in your stylesheets for some time. Just sayin’.

  43. So to clean up our CSS we use JS instead of vendor-specific properties? I don’t get it. It’s a waste of time IMO.

  44. I love the idea of ecsstender but I can’t get it to work in IE – specifically rounded corners or text-shadow. Works OK in webkit and mozilla. Should it work in IE or is that still under development?

  45. Mostly web sides users: approx 70% with IE <= 8. Even IE8 isn't using CSS3. I'm testing some of my domains every few days and thing what's happened with IE9? Or shell we get a other Firefox or Chrome or Safari ...

  46. What you’ve assembled is great. It does make for clean use of CSS3. However, I’m taking exception to the premise that you present it in — specifically losing the need to use conditional forks.

    You are still forking, but you are using JS routines to sniff and detect browsers. A practice that you derided.

    And what happens when JS is disabled? Yes, I know. I know. In this day and age, darn near every site on the web breaks horribly with JS disabled, but the fact is that people do still do it.

    Have you considered doing what you do with JS, but doing it with a server-side language? Having it server-side would circumvent the client-side issue.

    I’m not diminishing what you’ve done. I think it’s great. It certainly makes life easier, through use of a standard libraries that degrade gracefully. What I’m taking issue with is the context of “no more forking” that you present it in.

  47. It won’t really be useful for us designers until we can guarantee that it will work on all browsers, our clients expect the site to look the same across all platforms and hence we cannot see this as a viable solution.

    A shame because I would really love to use this, and it would really make our lives allot easier. 🙂

    btw: you probably already know this but there are still issues with FF on your scripts homepage. 🙂

  48. I agree with comment #56… it’s a great idea, but to me the beauty of CSS3 is that we can do a great deal of what used to be done with Javascript instead with CSS3. I can’t bring myself to use Javascript to cleanup my slightly messy CSS3, knowing that if someone were to visit my page without Javascript (think poor mobile phone support, people switching it off for security, etc.), they would not be able to see the shadows, animations, etc. that they might (depending on their browser) be able to see simply with pure CSS.

    I’d also rather not keep patching up old browsers with Javascript… the more we do this (as developers), the more we’re doing to keep those browsers around. If the web was entirely broken in old versions of IE, would anyone continue to use it? And if they did, would they really care about how sites looked, given that so many would have rendering issues?

    The idea (mentioned in prior comments in this thread) of a CSS pre-processor is a nice one though, it’d be great if something like this could be executed in that fashion (a bit like Sprockets?)

  49. i’ve been super excited to try this, but im looking at the Spoon demo site and it’s not working correctly in anything i view it in:

    -Chrome 6: animates and has rounded corners but no shadow
    -Safari 4: rounded corners with shadows, but no animation
    -FFox 3.6: no corners, no animation, no shadows
    -IE8: no containing box at all, two small quote marks

  50. Well this still doesn’t work in FF. I’m on 3.6.12 / Linux and it’s a no go. Works great in Chrome/Linux though. I’m wondering… with this being such a large file compared to just a few extra lines in our CSS… Is it worth it? I’ve always thought that one of the main points of coding semantically was to reduce bandwidth. So, doesn’t this increase [it] greatly compared to a few extra (ugly) lines of code in our CSS? Am I missing something. Seems like a great tool but just not too sure about the size of the file?

  51. I like this idea a lot and found a similar attempt by Lea Verou. But i have similar concerns.
    1. Performance.
    2. We are watching evolution of support over browsers like linear-gradient in chrome 10 How is that taken care?

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA