views:

105

answers:

4

I was thinking of using Javascript to automatically transform CSS3 attributes like border-radius, transform, box-shadow, etc. to their browser specific counterparts.

I did some research and found that you can iterate over the stylesheets defined via document.styleSheets. You can find the CSS rules via document.styleSheets[0].cssRules[0].cssText.

I want to modify the CSS rules that contain CSS3 attributes by injecting the browser specific attributes with the appropriate vendor-prefix, like -webkit-border-radius, moz-border-radius, etc.

However, it seems that the cssText property is preprocessed in each browser, to filter out CSS attributes that it doesn't understand. That practically breaks this idea.

Question: is there any way to retrieve the CSS text exactly as defined in the stylesheet? Or: is there another way to accomplish this via Javascript? I'd like to maintain clean CSS files without the need for defining each attribute multiple times for each specific browser.

+6  A: 

Why don't you just create stylesheets that have each browsers unique Pre-CSS3 counterparts in them already? As you mentioned, each browser filters out properties they don't recognize. It doesn't matter if you have -webkit-border-radius and moz-border-radius and border-radius all defined simultaniously for the same css selector. If a browser recognizes one of them, it'll be used, and if it doesn't, it'll be discarded. Even if a browser recognizes multiple versions, they are most likely going to have identical values, so it wouldn't matter.

jrista
+1: That's a good point
Sarfraz
Thanks, that's what I'm doing right now. I guess it's still the only way — but it's so ugly :)
Monokai
Yes, it tends to be ugly...no one ever said CSS script itself was pretty. ;) It just makes your UI pretty through a massive throng of complexity and hax.
jrista
+2  A: 

Looks like you have done your research on this well. It is not possible by accessing the CSSStyleDeclaration or the CSSRuleList object as unindentified properties get filtered out, which is a an implementation bug in most major browsers as they are supposed to list all properties - even ones they don't understand. See a related question for more on this.

The remaining alternatives require a bit too much work as @Sarfaraz already mentioned. It all boils down to parsing everything by hand and re-doing the work browsers have already done for us. Assuming your style declarations are inline, either in <style> tags, or as an element's style attribute, then you would have to parse the text and construct a map of all interesting CSS3 properties. With an inline-attribute, it's basically parsing text somewhat similar to:

`prop1: value; prop2: value2; ..`

See @Nick Craver's answer to a similar question, where he has linked to a regex approach for doing this.

With inline tags, the text to be parsed will be of the form:

[selector] {
    prop1: value1;
    prop2: value2;
    ...
}

...

This is an oversimplification ignoring all grammar production rules, and there are loads of issues to be handled here.

If the stylesheets are external, and are referenced inside the page, then you would have to lookup the <link> elements having an attribute rel equal to "stylesheet", and get their href property. Also, parse the url for imported stylesheets. Once you have these urls, you can make an AJAX call to fetch the actual contents of these stylesheets assuming nothing is blocking the call on the server side. Once you have the text from each file, it's basically a parsing step same as above, and adding necessary rules using insertRule or addRule depending on the browser.

There may be open-source CSS parsers that could help you in this.

This may be a long way of saying that I think @jrista's solution is a pretty good one. If you don't want to write all permutations of vendor-specific code, then an easier and better approach would be to have a CSS generation layer that's part of some build process which generates all permutations and spits out CSS files.

This layer could also contain optimizations by inspecting the User-Agent header and only generate the required styles, which is essentially what GWT does (but it generates all possible permutations beforehand, instead of doing it at runtime).

This may be a serious undertaking, so at the end of the day, you have to evaluate your options and see if the effort of achieving code-purity outweighs the benefits of having a little redundancy.

Anurag
Thanks. I like the idea of parsing the stylesheets manually. It's actually a smart way of accomplishing what I want. But the overhead of making a custom parser will be a little overkill. Also, I don't know how browsers will behave if you load the CSS file twice. Hope it will be cached.I think I'll give it a try. If that doesn't work, then modifying the CSS in the build process is also a nice solution.
Monokai
+1  A: 

Isn't it what IE7.js (and IE8.js and IE9.js) already do? Maybe you should take a look to the approach taken by Dean Edwards to add support for min-height, opacity, many CSS3 selectors, position:fixed; and overflow:visible; to these old browsers we all hate.

EDIT: btw, I prefer jrista solution: prefix CSS3 properties with -moz and -webkit and -ms and -o when needed.
It's an annoying task we'll have to do for ~5 years but it's far LESS annoying than if the W3C changed its mind about some properties (CSS3 modules are far from Recommendation). Then your script will still recognize the old syntax and give it to browsers whocan tell the difference between -vendor-property: oldsyntax_from_2010; and property: newsyntax_from_2015;
And what would you do if you find -moz-border-radius: 4px; border-radius: 20px; ; which one is the good one?

EDIT2: http://css3generator.com/ is a handy tool if you don't want to stuff your brain with details like syntax differences between -webkit-border-bottom-right-radius and -moz-border-radius-bottomright :)

Felipe Alsacreations
@Felipe, I don't agree that we'll have to do it for 5 years. Chrome already supports the spec'd properties, for example - `border-radius`. Other browsers vendors are taking CSS3 very seriously as well.
Anurag
Thanks. I will have a look at that script to see if I can take some ideas from it. CSS3Generator isn't a very good solution I'm afraid, as it is merely a copy-paste kind of thing.
Monokai
A: 

Seems like someone build something nice to solve this: http://ecsstender.org/

Monokai