Closed Bug 32169 Opened 25 years ago Closed 24 years ago

getComputedStyle (DOM Level 2) not implemented

Categories

(Core :: DOM: CSS Object Model, enhancement, P3)

enhancement

Tracking

()

VERIFIED FIXED

People

(Reporter: joe, Assigned: jst)

References

Details

(Whiteboard: [nsbeta2+][6/01])

This is not a bug, it is a feature request.  I am posting it to remind everyone 
that this is one of the most important parts of DOM Level 2 that has not yet 
been implemented.  Without this feature, many DHTML applications are going to 
have problems.

DOM Level 2 specifies the method ViewCSS::getComputedStyle for determining what 
CSS styles are applying to an element.  Currently in Mozilla, this style info 
can be determined via el.style, but only if the styles were set inline (e.g. 
<div style="...">) or via Javascript (e.g. el.style.blah = "blah").  IE5 
implements this functionality using the non-standard el.runtimeStyle... not a 
standard, but at least we can use it.

Without this, developers are encouraged to use the <div style=".."> syntax for 
all CSS, rather than taking advantage of the "cascading" part of CSS.  As an 
example, this means that DHTML app developers will be unable to write an XUL-
like widget with Javascript by reading in style values from a big CSS file, 
then laying out a component according to it's computed box model. You've seen 
the benefits of this in XUL, so imagine how this would benefit developers who 
want to do the same with HTML/Javascript.

I realize everyone is swamped with stuff to do, I just wanted to remind you of 
this feature so you can prioritize it when deciding what things you can and 
cannot finish in time for feature freeze.  IMHO, this one is important.

Read about getComputedStyle in the latest DOM WD:
http://www.w3.org/TR/1999/CR-DOM-Level-2-19991210/css.html#CSS-ViewCSS
While I recognize the importance of eventual DOM2 support, I think that even 
minor CSS1/DOM1 issues should get priority over any CSS2/DOM2 ones.  Once we 
have 100% level 1 support, then move on to level 2.  DOM2 is particularly 
tricky, because it hasn't been finalized by the W3C, so whatever we might 
implement runs the risk of having the standard change underneath us.  Then we'd 
get saddled with the issue of backward-compatibility with an old implementation 
that doesn't match the final standard.  I'll wait until DOM2 has been finalized 
before voting for this feature.
While I agree with you that DOM1/CSS1 issues should get priority, the simple 
fact is that DOM2 provides many tools that are absolutely ESSENTIAL to DHTML, 
and are far more important than minor CSS1 issues.  CSS1/DOM1 are nice, but 
alone they are useless.  DOM1 doesn't even provide a facility for working with 
styles!  Mozilla realized this and implemented the .style attribute, but it 
should also be noted that .style is not enough, we need getComputedStyle to be 
able to truly interact with CSS via the DOM.

Anyway, I do agree that CSS1/DOM1 issues should be resolved first.  Still, this 
issue is just as essential.
*** This bug has been confirmed by popular vote. ***
Status: UNCONFIRMED → NEW
Ever confirmed: true
*** Bug 34500 has been marked as a duplicate of this bug. ***
Status: NEW → ASSIGNED
Target Milestone: --- → M16
I must postulate that it it is incorrect to mark bug #34500 as a duplicate of 
this bug.  

#34500 states that there needs to be a way to get the x/y/width/height of an 
element.  However, getComputedStyle() does not guarantee to return the absolute 
pixel value for size and position.  If, for instance, an CSS had : "width: 
auto".  getComputedStyle() would then return "auto" for the width property, 
which is not is not what the reporter of bug #34500 is looking for.

Instead, let me suggest that #34500 be marked as a duplicate of bugs #9844 and 
#34938.  These bugs refer to the properties offsetLeft, offsetTop, offsetWidth, 
and offsetHeight, which are there to report the exact pixel values of an 
element's position and size.  

getComputedStyle() is meant only to evaluate the cascade of CSS rule-sets for a 
given element, merge them together according to specificity, and return one new 
rule-set with all of the CSS values that are actually applied to the element.  
getComputedStyle() should not actually compute special values for left, top, 
width, and height, it should only determine the value of these properties that 
has cascaded.
Joe, you're right, it's nice to know that at least someone is paying attention
to what I'm doing, since I'm obviously not ;). Thank you.

(I assume that you're reffering to bug #34398 and not bug #34938)
I just ran into a big reason why this feature is important.  When using 
margins, borders, and padding, it becomes impossible to calculate the exact 
coordinates and size of an element.  Because the .offsetLeft (etc..) properties 
only reflect offset from the margin, you can't determine total offset unless 
you can calculate the margin of the offset parent as well.

A real example of this is when trying to calculate the "clientLeft" 
or "clientTop" or an element (their offset from the top/left corner of the 
browser).  Often times, a mouse event will be received and you'll need to take 
the value you get from e.clientX or e.clientY, and determine the distance of 
that point from an element on the page.  Without getComputedStyle(), such a 
calculation is impossible.  If you don't believe me, I'd bet the XPToolkit team 
will run into this problem sooner or later.
Joe, don't worry, I do believe you :), I do see the problems
here and I personally believe that getComputedStyle() will offer
a *lot* to developers of dynamic web content.

There are problems with the way getComputedStyle() is defined tho, the
latest DOM Level 2 CSS candidate recommendation states that the return
value from getComputedStyle is:

CSSStyleDeclaration   The computed style. The CSSStyleDeclaration is
                      read-only and contains only absolute values.
                                             ^^^^^^^^^^^^^^^^^^^^

Now, imagine you have the following document (basically the problem
you're talking about in your comment above):

<html>
<head>
<style>
body {
  margin: 10%;
  padding: 10%;
  border: 2em solid red;
}
</style>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

If we follow the spec and ask for the computed margin for the body
element, what do we get? "10%", no, that's not an absolute value, from
reading the definition of getPropertyValue() it should return an empty
string if the property has not been set, well since we're only dealing
with absolute values here no useable value has been set, so we should
return an empty string? Not very useful. What the developer (script
writer) usually wants in a browser is the absolute value for the
margin, usually in pixels, in this case, if the width of the window is
800 pixels the returned margin should be 80 pixels.


Conclusion:

For getComputedStyle() to be useful to content developers in as many
situations as possible I'd like to (and probably soon will) make
getComputedStyle() really return the computed style, not just what's
immediately specified in the stylesheets since that's rarely enough,
but the actual computed style as it is displayed on the screen (or
whatever media, actually). The implementation will support
CSSPrimitiveValue so the values will be accessible in a number of
units (px, mm, cm, in, pt, ...) depending on the property.


(Besides, I *really* *don't* want to add the offset{Width,Height,...}
properties to all our elements, they simply will not work, they don't
make sense in XML, for instance, what's the offsetParent in a XUL
button, what's the offsetLeft for the button, offset from what? And,
they won't work when DOM3 introduces displaying a document in multiple
views. IMO they don't belong in a *document* object model at all, So,
we really need a replacement for them and IMO getComputedStyle() is
it, I hope people will agree with me, if not, I don't really see the
importance of getComputedStyle)

(I once again think that bug 34500 is a dup of this but I'll wait untill this
is implemented before I mark it as a dump)
I agree with you, except that I think that it is still extremely valuable to be 
able to obtain the literal CSS value that has been assigned to a property, 
whether it is an absolute (pixel) value or not.  

I think that the getPropertyValue method should always return the literal value 
that has cascaded, regardless of it's unit.  If the developer wants to get 
access to the pixel value of a property, they can use getPropertyCSSValue
("margin").getFloatValue(CSS_PX) command.  

I don't think it's safe to assume that for numeric css properties the developer 
will always want the pixel value, and nothing else.  The developer should be 
able to access the actual value that cascades, and use the flexible 
CSSPrimitiveValue methods to interpret this value as they see fit.

Indeed, the DOM spec does unfortunately specify that these values should 
be "absolute".  I think that this is wrong; getComputedStyle() should NOT rob 
the developer of the ability to determine the literal value that has cascaded. 

Vidur, any comments?
Just thought I'd also note that IE5's proprietary .currentStyle property does 
behave the way I'd like it to: for each property it reports the literal value 
that cascades, and doesn't attempt to compute an absolute value.  If you want 
absolute values, you have the offset* properties.

Yes, I see the evil in the offset properties, and agree it's better not to use 
them, but I think the solution I outlined above (using getPrimitiveValue and a 
unit type) is the best solution.
Joe, and others - Would the proposal
http://www.people.fas.harvard.edu/~dbaron/tmp/getCascadedStyle be useful to you?
I would like to send this to www-dom, but I wanted to know if this would be
helpful to you, and if you have any comments on it first.

jst - Have you investigated how hard it would be to fully implement
getComputedStyle()?  I would imagine it would be quite hard, since a lot of the
needed information is all over layout, but I could be wrong.
David, that's an excellent proposal IMHO.  It's clear that getComputedStyle is 
not enough in itself.  However, what I would prefer is that getComputedStyle 
simply be renamed to getCascadedStyle, and the CSSPrimitiveValue interface 
could be used to find the "computed" value.  

After all, what is the point of the CSSPrimitiveValue::getFloatValue method 
anyway?  I would think it would be to transform values like "50%", "3em", 
or "auto" into any other unit (like pixels), thus "computing" the style.  If 
this method will in fact be able to make these computations, then 
getComputedStyle is completely unnecessary. The DOM2 draft is completely vague 
about how getFloatValue will work.  

Vidur, your name is on the draft, can you elaborate?
A few more thoughts. How does getComputedStyle know how to compute 
an "absolute" value for various unit types?  How does it define what units 
are "relative"? It really SHOULDN'T know.  The developer should be able to make 
this decision.  

Sure, maybe "px" is absolute if you're talking about a monitor, but what if 
you're talking about a printed copy?  Then maybe you want "pt".  
getComputedStyle has no way to know what you want.

"font-size" is a good example.  If I want the computed value of "font-size: 
medium", do I want it in "em", "px", "pt", or what?  getComputedStyle doesn't 
know.  What if I want the computed value of "color: red".  Do I wanted it to 
be "red" or "#ff0000".  Again, we should use CSSPrimitiveValue to make this 
decision for ourselves.

So, my proposal to the DOM working group is as follows:

1). rename getComputedStyle to getCascadedStyle

2). The values in the returned CSSStyleDeclaration should not be absolute 
values, they should be whatever value has cascaded.  In the case of computed 
inherited values, the unit of the cascaded value will be the unit that the user 
agent has done the computation in.

3). CSSStyleDeclaration::getPropertyValue would return the string value that 
cascaded.

4). CSSStyleDeclaration::getPropertyCSSValue would get a CSSPrimitiveValue 
interface which could then be used to convert this string into 
whatever "absolute" unit the developer may be seeking.

In response to the comment at 13:46:

I think CSSPrimitiveValue is an inappropriate place for finding computed values
since it can occur in style rules that match multiple elements.  The conversions
done by getFloatValue are explained better in the interface definition for
CSSPrimitiveValue than in the definition of the method.


In response to the comment at 14:09:

Your proposal in (2) for dealing with inherited values has all the
implementation difficulties of dealing with computed values, since inheritance
works on computed values (not cascaded values).

Technically, absolute values are in, pt, pc, mm, cm (or, for angles, any angle
units).  See http://www.w3.org/TR/REC-CSS2/syndata.html#length-units .  So, IMO,
converting everything to absolute values is really a bad idea.  Perhaps the
getComputedStyle should just return a CSSStyleDeclaration where all conversions
are allowed in CSSPrimitiveValue::getFloatValue?  (This would leave the string
values for inherited things implementation-dependent.)
Ok, I see now that, as it is currently defined, CSSPrimitiveValue can't do 
conversions based on the dimensions of any specific element in the document. 
However, having such an ability would be amazingly useful.  Perhaps, as David 
suggested, getComputedStyle (or getCascadedStyle) should return a 
CSSPrimitiveValue which is bound to a specific element, and can therefore make 
relative-to-absolute, relative-to-relative, or absolute-to-relative conversions 
based on information about this element.  
Simple getComputedStyle should be in beta2, what this means is that only a few
properties will be implemented.

David, I like your proposal, I agree that the computed style and the cascaded
style should be different methods. I haven't had time to think about all the
details involved here and I probably won't untill I land the initial support for
this. A full implementation of getComputedStyle() is a lot of work, there's
something like 120 different properties in CSS2 but I don't think that
implementing any one property is really difficult but doing them all is a lot of
work.
Keywords: nsbeta2
I mentioned the discussion on this bug in the W3C www-dom mailing list and got 
this response from Phillipe Le Hegaret:

http://lists.w3.org/Archives/Public/www-dom/2000AprJun/0111.html
Putting on [nsbeta2+][6/01] radar.  This work must be done by 06/01 or we may 
pull this for PR2.
Whiteboard: [nsbeta2+][6/01]
This work was actually done, and it was checked in on 5/16. The current support
is very limited and I've opened bug 39892 for tracking support for more
properties.

Marking FIXED.
Status: ASSIGNED → RESOLVED
Closed: 24 years ago
Resolution: --- → FIXED
Marking Verified per jst comments.
Status: RESOLVED → VERIFIED
Component: DOM Level 2 → DOM Style
You need to log in before you can comment on or make changes to this bug.