Re: [cssom] Proposal for obtaining robust style information via Javascript - getStyle()

On Sun, 27 Jan 2013 22:20:31 +0100, Mike Sherov <mike.sherov@gmail.com>  
wrote:

> Forgive my ignorance on the subject, and please correct me where I'm  
> wrong
> or missing information or where something exists that does these things
> already...
>
> The web development community at large currently seems to be beholden to
> getComputedStyle() as the only source of information of what styles are
> applied to an element. The resulting CSSStyleDeclaration seems to  
> represent
> a significant loss of information by presenting only the "resolved  
> values"
> of the styles.
>
> For example, consider the following html:
> <style>
> div { margin: auto; }
> .inner { width: 50px; }
> .outer { width: 100px; }
> </style>
> <div class="outer"><div class="inner"> hi </div></div>
>
> In this example, using getComputedStyle() on the inner element will yield
> marginLeft = 25 and marginRight = 25. That's good in some cases. In fact,
> I've argued for this exact behavior before, because it's usually  
> preferable
> to know the used value. However there are use cases where being able to
> detect that the specified value is "auto" is a win.
>
> For example, consider this jQuery UI bug:
> http://bugs.jqueryui.com/ticket/7772
> In this case, I would want to know that "right" was specified, and that
> "left" was not, so that when I want to drag the element and change it's
> apparent position, I can modify "right" instead of "left". But if  
> percents
> were specified, I'd want to know pixels so I can set the exact pixel  
> value
> upon drag instead of having to do the math myself.... so I'd want used
> value, but only if the specified value exists!
>
> In general, it seems as if this one view, getComputedStyle(), can't tell  
> me
> enough information to accomodate everything I want to know. Now, I'm no
> spec writer, but in a perfect world I'd want:
>
> window.getStyle(valueType, element[, psuedoElement]);

The spec currently has getComputedStyle which returns "resolved value"  
which can be computed style or used style.

Recently I added a method getDefaultComputedStyle which returns the  
computed value but ignores author CSS.

The use case presented above asks for specified style. Are there use cases  
for the other kinds of values? Would cascaded value instead of specified  
value be better (i.e. return 'initial', 'inherit' and 'default' instead of  
specified value)?

http://dev.w3.org/csswg/css-cascade/#defaulting

Given the current state of the specification and the presented use case,  
I'm tempted to add the following method alongside getCompueStyle():

    CSSStyleDeclaration getSpecifiedStyle (Element elt, optional DOMString  
pseudoElt);

which is equivalent to getComputedStyle except return specified value  
instead of resolved value.

> and separately a new parameter on CSSStyleDeclaration.getPropertyValue:
>
> CSSStyleDeclaration.getPropertyValue( propertyName[, unit, valueType]);
>
> This would allow me to query any of the values I'd like:
> "default","initial","specified","computed","used","actual", and  
> "resolved".
> getComputedStyle(elem) would be equivalent to  getStyle("resolved",  
> elem). I'd
> also now be able to convert units or value type if I wanted, simply by
> specifiying it as the second and third parameter to getPropertyValue!

Converting units is currently addressed in CSSOM Values.

http://dev.w3.org/csswg/cssom-values/

> For my above example, to get back marginRIght:auto, and then see the used
> value is 25px, I can do this:
>
> var styles = window.getStyle("specified", elem);
> console.log(styles.marginRight);
> console.log(styles.getPropertyValue("marginRight", "px", "used");

With my proposal above it would be

console.log(getSpecifiedStyle(elem).marginRight)
console.log(getComputedStyle(elem).values.marginRight.px);

In this case getComputedStyle probably gives you the used value -- are  
there cases where you want the used style instead of computed style and  
getComputedStyle returns computed style? Or vice versa?

> If incompatible valueTypes and units are combined, an error can be  
> thrown.
>
> Thoughts?

I'd like to see more use cases in this area. :-)

On Fri, 01 Feb 2013 03:17:31 +0100, Boris Zbarsky <bzbarsky@mit.edu> wrote:

> On 1/31/13 9:02 PM, Mike Sherov wrote:
>> I believe the proposal is a bit broader, but I'll take any interest :-)
>> I believe is what we're talking about, so you can get "used",
>> "computed", "specified", "resolved", "actual", "initial", "default" or
>> any other value type for a CSS property or an element
>
> I see.
>
> Getting used values is, in many cases, pretty painful.  Gecko, for  
> example, doesn't really store it in many cases; there would need to be  
> special code to recompute it.  Even the bits we already have to do for  
> getComputedStyle are bad enough.  :(
>
> Actual values might be even worse (e.g. the actual color value is not  
> even under the UA's control; it depends on your monitor hardware, if I  
> understand the definition of "actual value").

There are no stated use cases in this thread for used or actual value  
apart from what is already returned by getComputedStyle.

> Computed and specified are totally worth doing.

OK. Is getComputedStyle good enough for computed value?

> I can't find any documentation of what "resolved" values are.
>
> Initial and default values ought to be reasonably easy to do, I'd think;  
> they're really a special case of specified values with not all rules  
> taken into account at heart.

I haven't seen any use case for getting the initial value. The default  
value is addressed by getDefaultComputedStyle, I think.

On Fri, 01 Feb 2013 03:25:44 +0100, L. David Baron <dbaron@dbaron.org>  
wrote:

> I'd actually rather have separate methods or (probably preferably)
> getters for each sort of value we'd want to return (the set is
> pretty small) than have string arguments for "specified",
> "computed", etc.
>
> For example, maybe something like:
>   element.specifiedStyle.color
>   element.computedStyle.color
>   element.usedStyle.color
>   element.pseudoStyle("::before").specifiedStyle.color

If we go with this API style, should we change  
getDefaultComputedStyle(element) to element.defaultComputedStyle? Or  
should we stick to the current API style?

On Mon, 28 Jan 2013 00:01:13 +0100, François REMY  
<francois.remy.dev@outlook.com> wrote:

> Hi,
>
> Actually the information you want to get is the cascaded value of a  
> property. This value is accessible (with some caveats) in IE via the  
> 'currentStyle' property of an element.
>
>    element.currentStyle.marginLeft == "auto"

We could put this in the spec, although that might have negative Web  
compat impact for non-IE browsers.

> This is not the first time this issue is brought to this mailling list  
> (search for 'currentStyle' in the archives). The last time, it seems  
> like the favored approach would have been
>
>    element.getStyle(
>
>       DOMString
>         'property-name'
>
>       optional DOMString
>          '::pseudo-element'
>
>       optional DOMString
>         | 'used'
>         | 'computed'
>         | 'cascaded'
>         | 'specified'
>         | ...
>
>    )
>
> However, I don't think the discussion continued forward. I agree this is  
> an issue, as is anything which is done by the browser and not  
> harnessable by the scripting (now, the best option you have will be to  
> reperform the matching/cascading yourself, and I guess this is what  
> devtools are doing).

David said (quoted above) that he prefers separate methods.

On Fri, 01 Feb 2013 03:31:51 +0100, Tab Atkins Jr. <jackalmage@gmail.com>  
wrote:

> On Thu, Jan 31, 2013 at 6:27 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
>> Oh, used values?
>>
>> Why does translating between units need those, except for a very small  
>> set
>> of properties?
>
> There are a lot of properties with values that don't become px until
> used-value time, for example.  This covers most properties with
> percentages, a number of properties with 'auto', and a smattering of
> other types of values.

Does this mean that CSSOM Values would only work for used values, not  
specified or computed?

On Fri, 01 Feb 2013 03:34:10 +0100, Tab Atkins Jr. <jackalmage@gmail.com>  
wrote:

> On Thu, Jan 31, 2013 at 6:25 PM, L. David Baron <dbaron@dbaron.org>  
> wrote:
>> For example, maybe something like:
>>   element.specifiedStyle.color
>>   element.computedStyle.color
>>   element.usedStyle.color
>>   element.pseudoStyle("::before").specifiedStyle.color
>
> ...
>
> For the last one, this could give us an excuse to finally reify
> pseudo-elements as DOM constructs, for the return value of your
> pseudoStyle() function (though I'd call it something else).

We can expose pseudo-elements separately when we need them.

On Fri, 01 Feb 2013 04:15:01 +0100, L. David Baron <dbaron@dbaron.org>  
wrote:

> Returning a dead object would be substantially more expensive in
> many cases.
>
> For example, today getComputedStyle(elt, "").color doesn't require
> flushing layout.  If getComputedStyle() returned a dead object, it
> would require flushing layout, and also making lots of copies.
>
> (This is one of the contexts where returning a live object is much
> simpler than returning a dead one.  Some contexts are the other way
> around.)

OK, so let's keep it being live. :-)

On Fri, 01 Feb 2013 11:13:17 +0100, Simon Sapin <simon.sapin@kozea.fr>  
wrote:

> My understanding is that elements do not have used values, only boxes  
> do. (At least that’s how WeasyPrint implements it.)
>
> Also note that one element can generate multiple boxes (list item +  
> maker, table + wrapper, fragmentation across pages, columns, …) and  
> these boxes may have different used values for the same properties.
>
> If you’re tempted to pretend that list item markers, table wrappers or  
> pages can be ignored, consider the used height of a block fragmented in  
> a multi-column context. Each fragment could have a different height.
>
> Used values on elements do not make sense.

So if we want to have an API for getting used value, maybe we should first  
have an API that exposes the boxes.

(That this is an issue already with getComputedStyle is noted.)

On Fri, 01 Feb 2013 15:19:59 +0100, Boris Zbarsky <bzbarsky@mit.edu> wrote:

> On 2/1/13 1:06 AM, Tab Atkins Jr. wrote:
>> You and Boris are giving me conflicting information about which is
>> better.
>
> I don't think so.
>
> I just said being live is a pain to implement.  Being dead, however, is  
> a terrible performance problem.
>
> I didn't state an opinion as to which is "better", or rather less bad...  
> ;)  For this case, I think a live object is probably better.
>
> What I'm not convinced about is an API that has a polymorphic "immutable  
> string or live object" return type, because that seems like a footgun  
> (e.g. saving the return value and then checking it later has different  
> behavior depending on which flavor of the API you managed to call).
>
> David's proposed API does not have that problem.

getComputedStyle() doesn't, either, FWIW.

On Fri, 01 Feb 2013 21:11:03 +0100, François REMY  
<francois.remy.dev@outlook.com> wrote:

> Me too, FWIW. It reminds me of 'style', 'runtimeStyle' and  
> 'currentStyle' of IE.
>
> BTW, while we are at it, it's maybe the good time to support the  
> 'override' style level (more or less 'runtimeStyle' of IE)? It allows to  
> style a pseudo element directly but the implementation is a stub in  
> webkit (returns null) and is not implemented in any other browser (IE's  
> runtimeStyle is not able to target pseudo elements).
>
> http://stackoverflow.com/questions/9798210/is-there-any-way-to-reset-after-before-css-rules-for-an-element
> http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-DocumentCSS         
>            

Use case for 'override' style level? :-) (I checked the stack overflow  
link but he didn't explain his use case AFAICT.)

-- 
Simon Pieters
Opera Software

Received on Tuesday, 7 May 2013 15:34:12 UTC