[cssom] Directions for better OM expansions

We've been discussing CSSOM stuff recently in Chrome team, and I
wanted to push back some of the discussion to the CSSWG list.  This
email *does not* represent Chrome's position, just my own, though
various team members' contributions have played a part in forming
these opinions.

We've been mostly discussing Anne's proposed Values API.  I think it's
a great start, but doesn't address the larger problem that the shape
of the APIs surrounding CSS is somewhat crazy.  They don't work
together - you've got el.style pointing to the @style attribute on an
element, el.ownerDocument.defaultView.getComputedStyle('someproperty')
to get a resolved value (sometimes a 'computed', sometimes a 'used'
value), and the stylesheet-based API.  These all work *completely*
differently, with vastly different access patterns, some being
writable while other are readonly, etc.  It's just a bad situation
overall.

So, I've boiled down the use-cases I think are useful to address (not
included in this email for brevity, but can be provided upon request)
and come up with the list of what I think are the necessities for a
complete and sane CSS API.  I'm working out right now what I think
this would actually end up looking like - I'll send a separate email
when I have some concrete suggestions.

On the subject of what values to get/set:

1. Author should be able to get the set of all cascaded values that
contribute to the element's style.  These should have the context
(selector if they're from a decl block, or otherwise indicating that
they come from a @style attribute or inheritance) and a specificity
(possibly the list is sorted by specificity?).  These entries should
be readable and writable (except for decl blocks from user
stylesheets, of course).  (Possibly, @style should always be in the
list, even if it doesn't actually specify any values.  The inheritance
block should always be in the list, because it always passes
*something*, even if just the initial values to the root element.)

2. Author should be able to easily read and write styles in
stylesheets and @style attributes.  CSSOM has interfaces for the
former, though they're clumsy.  The latter is already exposed in a
convenient way through the .style attribute of elements.

3. Author should be able to read the actual used style for all
properties.  This is the result of resolving all the cascaded values
for each property to a single value.  (This more-or-less refers to the
"used value" in the CSS Values & Units draft.)  In particular, this
should do what authors naively *expect* el.style to do - it should
give you the value of, say, font-style no matter whether it came from
@style, cascaded in from a style sheet, or inherited in from the
parent.

4. Author should be able to read the "animated style" of an element -
the current value of the property as affected by
transitions/animations/other stuff that changes the value without
actually touching the "specified value".

5. Author should be able to write to an "override style" that doesn't
affect any specific decl block or @style attribute.  This can be
thought of as a special js-only style attribute on the element, with
appropriate specificity (probably, stronger than everything except
user !important rules).  That is, it automatically overrides any value
that comes from stylesheets or the @style attribute.  (It can, of
course, subsequently be unset, allowing normal cascading to happen.)

6. Author should be able to ask a given element to convert an
arbitrary value from one unit to another.  This is useful for various
scripting purposes, when you're trying to set various lengths and
being able to refer to the environment of a particular element (for
its definition of em or %, for example) is useful.

Possibly #3 and #5 can be merged to be the read/write behavior of a
single interface.  Except for user !important rules, setting #5
immediately changes the value of the property no matter what, and
reading #3 gives you the final value, which, if #5 was used, is the
value from #5.  Not completely certain this gives us the most sane
behavior, but it should be definitely be looked into, to make author's
lives easy.

I could also see #5 instead participating in some slightly magical way
in the list returned by #1, though I'm still working out how I'd like
it to look.

Notice that *not* listed above is a specific segregation between
specified/computed/used values.  This distinction between specified,
computed, and used is completely useless to authors in general.  When
they're getting at decl blocks or @style (from #1 or #2), sure, stick
with the specified value in the form that was provided.  But when
you're accessing the "real style" (#3 above), they shouldn't have to
care - they should be able to ask for the value in px, em, or percent
(or keyword, rgb, or hsl, for that matter) no matter what the original
value was specified in.  Using Anne's Values API for this seems great.
 Possibly use it for #1 too, with some caveats that it can only
convert between certain units (specifically, those that don't depend
on layout to figure out, so px->em is cool, but not %->px).

This does bring up a few interesting conflicts.  For example, how can
you distinguish between wanting the specified value regardless of
source (say, "50%"), and the used/actual value based on layout (if the
element is display:none, "0px" or maybe some defined "this value
doesn't exist" value, since there's no box to measure - especially
important for prop)?

I think that can be punted by the fact that authors would have easy
access to both the cascaded values (#1) and the "real value" (#3).  #1
is easy to ask for the specified value - if nothing else, you can just
walk the returned array (assuming it's sorted by specificity),
grabbing the value from the first block that specifies it.  We could
easily convenience this away, too, giving the author an easy ability
to ask "what decl block contributed the winning value for this
property?".  #3 is then free to be as magical/useful as we can make
it, properly paying attention to layout and such.  Once you've dropped
down to used value level, converting between units should be easy to
do, too - all the information you need is already there.

I think the "animation style" (#4) would be similar, in terms of
allowing easy conversion between units?

I think this hits all the major use-cases for things we want to do
with CSS, in a relatively sane way.  You can access all the various
stylesheet levels for reading/writing, get access to the declaration
blocks that contribute values for specific properties, set style
regardless of what comes in from the document, and query for the used
value of a property in any unit.

Thoughts?  Am I missing something?  Am I off-track in something?

~TJ

Received on Tuesday, 14 September 2010 01:37:13 UTC