Find all CSS rules that apply to an element

Many tools/APIs provide ways of selecting elements of specific classes or IDs. There's also possible to inspect the raw stylesheets loaded by the browser.

However, for browsers to render an element, they'll compile all CSS rules (possibly from different stylesheet files) and apply it to the element. This is what you see with Firebug or the WebKit Inspector - the full CSS inheritance tree for an element.

How can I reproduce this feature in pure JavaScript without requiring additional browser plugins?

Perhaps an example can provide some clarification for what I'm looking for:

<style type="text/css">
    p { color :red; }
    #description { font-size: 20px; }
</style>

<p id="description">Lorem ipsum</p>

Here the p#description element have two CSS rules applied: a red color and a font size of 20 px.

I would like to find the source from where these computed CSS rules originate from (color comes the p rule and so on).


Since this question currently doesn't have a lightweight (non-library), cross-browser compatible answer, I'll try to provide one:

function css(el) {
    var sheets = document.styleSheets, ret = [];
    el.matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector 
        || el.msMatchesSelector || el.oMatchesSelector;
    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for (var r in rules) {
            if (el.matches(rules[r].selectorText)) {
                ret.push(rules[r].cssText);
            }
        }
    }
    return ret;
}

JSFiddle: http://jsfiddle.net/HP326/6/

Calling css(document.getElementById('elementId')) will return an array with an element for each CSS rule that matches the passed element. If you want to find out more specific information about each rule, check out the CSSRule object documentation.


EDIT: This answer is now deprecated and no longer works in Chrome 64+. Leaving for historical context. In fact that bug report links back to this question for alternative solutions to using this.


Seems I managed to answer my own question after another hour of research.

It's as simple as this:

window.getMatchedCSSRules(document.getElementById("description"))

(Works in WebKit/Chrome, possibly others too)