6

I'm looking to get the used css values of all DOM elements on a page. When I say "used values" I'm referring to the definition as specified in the W3C specification:

6.1.3 Used values

Computed values are processed as far as possible without formatting the document. Some values, however, can only be determined when the document is being laid out. For example, if the width of an element is set to be a certain percentage of its containing block, the width cannot be determined until the width of the containing block has been determined. The used value is the result of taking the computed value and resolving any remaining dependencies into an absolute value.

These should be the final values computed with respect to the actual page layout. Mozilla's docs claim that you can use window.getComputedStyle to get the used values, but this does not make sense to me because computed values are different from used values (and I want used values). Even if these are the used values, I'm not sure if this only works in Firefox or not. Is there a way to reliably get used values in all browsers?

Community
  • 1
  • 1
user730569
  • 3,940
  • 9
  • 42
  • 68
  • The used value is the one you can fetch using [jquery css](http://api.jquery.com/css/) function. So assuming you have the names of the properties, you just have to iterate over all DOM objects. – Denys Séguret Jun 10 '12 at 17:20
  • 1
    *"this does not make sense to me because computed values are different from used values (and I want used values)"* How so? Can you give an example of where you won't get what you want from `getComputedStyle` (and IE's near-equivalent of it, `currentStyle`)? – T.J. Crowder Jun 10 '12 at 17:26
  • The "computed" in the name of that function means, "computed based on the rules of CSS and the current state of the DOM". – Pointy Jun 10 '12 at 17:28
  • Also, the fact of the matter is that unless you want to undertake a very complicated project, those APIs are all you've got. – Pointy Jun 10 '12 at 17:35

2 Answers2

5

Note: The world has moved on since the question was asked and answered. There are now more layers of values than there used to be: declared, cascaded, specified, computed, resolved, used, and actual. getComputedStyle returns resolved values (which are either computed or used depending on the property). Here are the layers:

From CSS Cascading and Inheritance Level 4:

Once a user agent has parsed a document and constructed a document tree, it must assign, to every element in the tree, and correspondingly to every box in the formatting structure, a value to every property that applies to the target media type.

The final value of a CSS property for a given element or box is the result of a multi-step calculation:

  1. First, all the declared values applied to an element are collected, for each property on each element. There may be zero or many declared values applied to the element.
  2. Cascading yields the cascaded value. There is at most one cascaded value per property per element.
  3. Defaulting yields the specified value. Every element has exactly one specified value per property.
  4. Resolving value dependencies yields the computed value. Every element has exactly one computed value per property.
  5. Formatting the document yields the used value. An element only has a used value for a given property if that property applies to the element.
  6. Finally, the used value is transformed to the actual value based on constraints of the display environment. As with the used value, there may or may not be an actual value for a given property on an element.

Then, the CSS Object Model defines resolved values:

getComputedStyle() was historically defined to return the "computed value" of an element or pseudo-element. However, the concept of "computed value" changed between revisions of CSS while the implementation of getComputedStyle() had to remain the same for compatibility with deployed scripts. To address this issue this specification introduces the concept of a resolved value.

The resolved value for a given longhand property can be determined as follows:

...which is followed by a list of properties (specific ones and categories) saying whether the resolved value is the computed or used value.

With that backdrop:

getComputedStyle works on all major modern browsers. Earlier versions of IE provide a near-equivalent in the form of currentStyle.

getComputedStyle returns resolved values, which for any given property is either the computed value or the used value, with the CSSOM spec defining clearly what properties get returned with which kind of value under which circumstances. I don't see anything in CSSC&I4 or CSSOM defining a way to access used values in cases where the resolved value isn't the used value, or a way to access actual values, and gsnedders says they have checked with the working group and confirmed there isn't a way to get used values, at least not yet.

Resolved values are probably good enough for what you need. For instance, the following example shows 207.5px or similar , not 50%. That's the resolved value, which is also the used value in this particular case (because I used width on an element where the display isn't none or contents), but possibly not the actual value, depending on whether subpixel rendering is feasible and appropriate in this case.

(function() {
  var target = document.getElementById("target");
  var style = window.getComputedStyle(target);
  display("computed width = " + style.width);
  
  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = String(msg);
    document.body.appendChild(p);
  }
})();
<div id="target" style="display: inline-block; width: 50%">x</div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    If you call `window.getComputedStyle()` and pass in an element node, it returns properties whose values often are `normal`, for example, and not pixel values. How could these be used values? – user730569 Jun 10 '12 at 17:33
  • @user730569: Give me a solid example? `normal` sounds like the sort of thing you'd get for `font-weight`, and of course, `normal` is a valid final value for `font-weight`. – T.J. Crowder Jun 10 '12 at 17:34
  • run this in your javascript browser console on this page `window.getComputedStyle(document.getElementsByTagName("div")[0])`. Take a look at the `letterspacing` property for example. There are many more... – user730569 Jun 10 '12 at 17:38
  • @user730569: `normal` is a valid, final value for `letter-spacing`: http://www.w3.org/TR/CSS2/text.html#propdef-letter-spacing If you're asking how to find out what `normal` `letter-spacing` is on any given browser, the answer should be in the CSS spec (and in this case, the answer is: the browser can vary it across the course of the text in the element, if it wants to, to make the text look nice because `normal` = *"This value allows the user agent to alter the space between characters in order to justify text."* and so there **is** no number it can give you). – T.J. Crowder Jun 10 '12 at 17:41
  • Well I assumed that any final "used value" would be pixel lengths. It's confusing because it would seem that different browsers would render `normal` differently. I'm trying to determine whether browsers render css differently because they compute specified values down to used values differently, or because they render the same used values differently. – user730569 Jun 10 '12 at 17:42
  • @user730569: `letter-spacing` is probably a bad example (see above). Can you provide an example where you'd expect a specific number, and the spec doesn't say what that number should be if the value is `normal`? That would help me understand the problem. – T.J. Crowder Jun 10 '12 at 17:43
  • Letter-spacing is actually something that is very important to me. I need to render this consistently in a cross-browser manner. – user730569 Jun 10 '12 at 17:50
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12358/discussion-between-user730569-and-t-j-crowder) – user730569 Jun 10 '12 at 17:50
  • @user730569: (I don't do the chat thing when it's relevant to the question. One of the stupider aspects of SO in my view.) I can't speak to `letter-spacing`, I haven't used it much, but the spec clearly indicates that `normal` means that the browser can do varying spacing between letters if it wants, so there would be no numeric value it could give you (as it varies). – T.J. Crowder Jun 10 '12 at 18:11
  • I want to standardize the default letter-spacing, line-height, and word spacing across browsers. Considering `normal` gets rendering differently across browsers, do you think there would be a standard multiple or addition/subtraction that could standardize these properties across browsers, regardless of the `font-family` or `font-size`? – user730569 Jun 10 '12 at 18:18
  • @user730569: Beyond my knowledge, I'm afraid. – T.J. Crowder Jun 10 '12 at 21:43
  • 1
    `Window.getComputedStyle` returns "resolved values", which are either the "computed value" or the "used value", depending on property (and all new properties return the computer value; the used value case is just for compatibility with CSS 2.0). This nowadays is said in the MDN page (and I realise this answer is years old!). – gsnedders Feb 21 '19 at 14:03
  • @gsnedders - Fascinating, and making for a difficult update to the answer. :-) Is there any way to get the used values, as far as you know? I'm not seeing one in https://drafts.csswg.org/cssom/. – T.J. Crowder Feb 21 '19 at 14:24
  • 1
    @T.J.Crowder Sadly no! Unaware of any way of getting the used value, which is how I ended up here before asking around there. – gsnedders Feb 21 '19 at 15:59
  • @gsnedders - Yeah, that was my impression too. Thanks for letting me know about the answer being outdated! – T.J. Crowder Feb 21 '19 at 16:02
  • 1
    That's OK, all CSS problems these days are trivially solved with Houdini amirite? – BoltClock Feb 21 '19 at 16:58
  • 1
    @T.J.Crowder talking to other people in the WG confirms that the answer is indeed "no", though apparently the definition of "resolved" is more complex than just how old the property is as I claimed above. – gsnedders Feb 21 '19 at 19:38
  • @BoltClock Typed OM doesn't currently, but there is apparently a plan to add a used value map. – gsnedders Feb 21 '19 at 19:39
-4

You could use jQuery or another preferred library in most cases.

For instance, your question title has font-size:100% applied to it which can be retrieved w/firebug. But with jQuery api you can retrieve the value used like so:

$('#question-header .question-hyperlink').css('font-size');//run in console
//or enter this in the url bar
//javascript:alert($('#question-header .question-hyperlink').css('font-size'));
//returns "23.06px"

NB the library is included on this page, but it would be fairly trivial to create a bookmarklet that includes jQuery and polls the necessary properties.

Oleg
  • 24,465
  • 8
  • 61
  • 91