Right now we only have a single interface that exposes the CSS property names as attributes (CSSStyleDeclaration), but no browser does it right, and the spec behavior is also not great.
In particular, the spec behavior means that you expose stuff like fontFaceRule.style.color, which doesn't quite make sense.
WebKit and Blink (though WebKit may have changed recently) historically use named getters for this (which is also not great, see https://github.com/w3c/csswg-drafts/issues/1089).
Note also that:
Gecko does something which IMO is better. Gecko exposes them as attributes as the spec describes, but on an interface that derives from CSSStyleDeclaration called CSS2Properties which we use for all the "style" declarations (so, inline style declarations, CSSStyleRule.style, getComputedStyle, CSSPageRule.style, and individual keyframe declarations). (link, link). I think something like what Gecko does, but with similar interfaces for the declaration blocks that should have descriptors, like @font-face and @counter-style, would generally be much saner.
Since there's movement around here, and the interop story here is quite sad, I think there's quite a fair amount of room for improvement, and if we can align in a model that is both consistent and useful for developers it'd be great.
Does the thing I described above seem reasonable? Other ideas?
cc @gsnedders @foolip @andruud @xiaochengh @heycam
Per recent discussion with @gsnedders WebKit trunk may have changed behavior?
WebKit trunk basically follows the CSSOM spec here, with each property (and descriptor, because we didn't stop exposing them) a separate IDL attribute rather than using named getters. The old named getter had some bugs that led to some "interesting" behaviour hence that change.
I could probably live with that too, if people think it's fine to expose something like 'src' in document.body.style.
(Though not a terrible fan of it it might be the path of least resistance...)
I assume that for stuff that doesn't apply you just always return the empty string?
I don't think we have any opposition to changing behaviour for descriptors; it was just the simple change to move away from the named getter (and also effectively the minimal change).
@emilio Your proposal sounds good to me. Having to expose src and other descriptors on .style (etc) feels like a design failure, so it's a bit annoying. (Though maybe not a huge problem for authors in practice).
Yes, I've been wanting to improve this for a long time; the current situation is ridiculous.
Having child interfaces for properties and for each at-rule that contains only the properties/descriptors relevant to the context would be great.
Just a note to consider introspection for whatever is decided, which is immensely useful for tooling. The situation right now is far from ideal.
issues related to this were the hardest part of getting VisBug to work across browser
The CSS Working Group just discussed [cssom] The way CSSStyleDeclaration exposes properties is not ideal, and agreed to the following:
RESOLVED: Having different interfaces for declarations blocks that expose a different set of descriptors/propertiesThe full IRC log of that discussion
<dael> Topic: [cssom] The way CSSStyleDeclaration exposes properties is not ideal
<dael> github: https://github.com/w3c/csswg-drafts/issues/5649
<dael> emilio: It's a mess everywhere. I made a proposal. Seemed to be agreement to try and go for it
<dael> emilio: Not in love with...need to decide on names. I'm fine deciding the names on GH or another call
<dael> emilio: Idea is to have different interfaces for different declarations. fontFace only has a set of descriptors. Spec is sad and doesn't match browsers. Maybe WK but it adds descriptors.
<dael> emilio: Agreement from browser engines it's a decent path forward
<dael> Rossen_: You're okay continuing discussion in GH?
<dael> emilio: It would be ideal to resolve sep interfaces for declarations that declare different things. Names tbd
<dael> TabAtkins: I would love to have this. Please have it
<dael> Rossen_: Do you have prop written up? Is it a PR or anything more?
<dael> emilio: I can summarize in IRC
<dael> fantasai: Go ahead
<dael> Rossen_: With a couple minutes remaining I doubt we'd get to anything other than this
<emilio> Having different interfaces for declarations that expose a different set of descriptors/properties
<emilio> declaration blocks* I guess, naming in the spec is wrong
<dael> fantasai: I think it's good for each to have different set. Exposing declarations that don't apply is confusing and may have future problems
<dael> Rossen_: I'm hearing support
<dael> Rossen_: We can resolve to adopt the proposal and you can come back with more concrete interfaces. Does that work?
<dael> emilio: Sounds great
<dael> Rossen_: Objections to Having different interfaces for declarations blocks that expose a different set of descriptors/properties
<dael> RESOLVED: Having different interfaces for declarations blocks that expose a different set of descriptors/properties
So, here's a proposal. All of the interfaces below would extend CSSStyleDeclaration and thus have a getPropertyValue / setProperty / cssText / length / item / etc...:
CSSStyleProperties (CSS2Properties) for style declarations: inline style / getComputedStyle / CSSStyleRule.style. This is basically the current CSSStyleDeclaration. I like CSSStyleProperties a bit more, because it's more consistent, but there's precedent for CSS2Properties, and that's what Gecko calls it, so it's a bit more compatible.CSSPageProperties for @page rules, with only the page descriptor.CSSCounterStyleProperties for @counter-styleCSSFontFaceProperties for @font-faceetc. Two thoughts:
CSS{Style,Page,...}Declarations, but I think that might be confusing with the existing CSSStyleDeclaration.Properties would be Block (so, CSSStyleBlock / CSSPageBlock / ...), which could be nice because it avoids using Properties for something that's "descriptors"...But this eventually comes down to naming, so... thoughts?
CSSStyleProperties(CSS2Properties) for style declarations: inline style /getComputedStyle/CSSStyleRule.style. This is basically the currentCSSStyleDeclaration. I likeCSSStylePropertiesa bit more, because it's more consistent, but there's precedent forCSS2Properties, and that's what Gecko calls it, so it's a bit more compatible.
That precedent comes from DOM Level 2 Style. From an aesthetic point-of-view I'd like to get rid of the lie that it's only CSS2, so if you wanna try renaming it in Gecko and see if it sticks I'd quite like that?
An alternative that doesn't use
Propertieswould beBlock(so,CSSStyleBlock/CSSPageBlock/ ...), which could be nice because it avoids usingPropertiesfor something that's "descriptors"...
Is there any reason why we can't go for CSSStyleProperties/CSS2Properties then CSSPageDescriptors, CSSCounterStyleDescriptors, etc?
I guess not really, that'd be fine for me.
Most helpful comment
Yes, I've been wanting to improve this for a long time; the current situation is ridiculous.
Having child interfaces for properties and for each at-rule that contains only the properties/descriptors relevant to the context would be great.