Get element CSS property (width/height) value as it was set (in percent/em/px/etc)

It's not as simple as just calling WebKits getMatchedCSSRules(), it does return the matched rules in order of priority (altho I've seen no mention of this order in the docs), but the order does not take regard to property important priority and does not include element styles. So I ended up with this function:

getMatchedStyle

function getMatchedStyle(elem, property){
    // element property has highest priority
    var val = elem.style.getPropertyValue(property);

    // if it's important, we are done
    if(elem.style.getPropertyPriority(property))
        return val;

    // get matched rules
    var rules = getMatchedCSSRules(elem);

    // iterate the rules backwards
    // rules are ordered by priority, highest last
    for(var i = rules.length; i --> 0;){
        var r = rules[i];

        var important = r.style.getPropertyPriority(property);

        // if set, only reset if important
        if(val == null || important){
            val = r.style.getPropertyValue(property);

            // done if important
            if(important)
                break;
        }
    }

    return val;
}

Example

Given the following code and style rules:

<div class="b">div 1</div>
<div id="a" class="a d2">div 2</div>
<div id="b" class="b d3" style="width: 333px;">div 3</div>
<div id="c" class="c d4" style="width: 44em;">div 4</div>

<style>
div      { width: 100px; }
.d3      { width: auto !important; }
div#b    { width: 80%;   }
div#c.c  { width: 444px; }
x, div.a { width: 50%;   }
.a       { width: 75%;   }
</style>

this JS code

var d = document.querySelectorAll('div');

for(var i = 0; i < d.length; ++i){
    console.log("div " + (i+1) + ":  " + getMatchedStyle(d[i], 'width'));
}

gives the following widths for the divs:

div 1:  100px
div 2:  50%
div 3:  auto
div 4:  44em

(At jsFiddle)


Apparently there is no DOM API for this

https://developer.mozilla.org/en/DOM/window.getComputedStyle#Notes

EDIT: oops, just realized this was marked for Google Chrome

Try window.getMatchedCSSRules()


Good news everyone! There seems to be a CSS Typed OM on his way in the w3c drafts.

Fast reading this document, it seems that the goal of this maybe to-be specification, is to ease the access of CSSOM values from javascript.

The really important part of this for us here is that we will have a CSSUnitValue API, which will be able to parse CSS values to an object of the form

{
  value: 100,
  unit: "percent", // | "px" | "em" ...
  type: "percent"  // | "length"
}

And add a computedStyleMap() method, to the Element interface, from which we will be able to get the values actually applied on our elements.

As of today, only Chrome implements it (since 66).

(() => {
  if (!Element.prototype.computedStyleMap) {
    console.error("Your browser doesn't support CSS Typed OM");
    return;
  }
  document.querySelectorAll('.test')
    .forEach((elem) => {
      let styleMap = elem.computedStyleMap();
      const unitvalue = styleMap.get('width');
      console.log(elem, {
        type: unitvalue.type(),
        unit: unitvalue.unit,
        value: unitvalue.value
      });
    });

/* outputs

  <div class="b test">first</div> {
    "type": {
      "length": 1
    },
    "unit": "px",
    "value": 100
  }
  
  <div id="a" class="a test">second</div> {
    "type": {
      "percent": 1
    },
    "unit": "percent",
    "value": 50
  }

*/

})();
div.test {  width: 100px; }
x,div#a {  width: 50%; }
.a {  width: 75%; }
<div class="b test">first</div>
<div id="a" class="a test">second</div>