- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Mon, 11 Apr 2011 12:57:27 -0700
- To: www-style list <www-style@w3.org>
I and other on my team been discussing ways in which the CSSOM could be made more author-friendly, and have a number of ideas we'd like to toss out for review. Some we're rather attached to, other are definitely half-baked but address an idea we think is important. This message is about navigating and searching stylesheets. Right now, doing *anything* with actual stylesheets from the CSSOM is a horrifying task. A task that seems like it should be trivial, like finding all the rules that apply to a particular element, requires iterating through every stylesheet in the document and checking every rule, comparing its selector against the element to see if it matches. I think there are some simple additions we can make to the API that would make things like this easier. All of these additions should be useful for authors in at least some situations; they should also be *extremely* useful for editors. Searching a Style Use Case: I want to directly manipulate the stylesheet value for the specific rule that is applying some value to a particular element, so that other elements which that rule applies to are also changed. Problem: The only things I have easy access to are the @style rule on the element. To find the stylesheet rules that are applying to an element, I have to walk all the stylesheets and manually test every ruleset for whether its selector matches my element, then order them (presumably by specificity) so I can easily decide which ruleset to manipulate. Possible Solution: Add elem.rules(), which returns a list of rulesets (CSSStyleRule) that apply to the element, ordered by decreasing specificity. Also, elem.rules(‘property’), which filters the rulesets to only include ones which actually set the particular property. Note: This can be misused somewhat - if you just blindly alter the first ruleset returned, assuming that it corresponds to a particular selector, you’ll blow your foot off when, say, the code runs while the user is hovering the element (and thus a :hover rule is now most specific). This particular use should instead be done by factoring out the value you want to alter into a variable, and just altering the variable instead. We need to remember to note this explicitly when speccing this. Use Case: Similar to above, but I know that there is a *particular* important ruleset that I want to mess with regularly, such as a “base” ruleset for a particular class. Problem: Similar to above, where you have to iterate the stylesheet. Slightly easier, since you probably know what the selector is for that particular ruleset you want, but that introduces a fragility where if you change the precise selector used in the stylesheet your code stops working (or worse, finds a *different* ruleset that also has that selector). Possible Solution: Add an @id name; rule that can be added to declaration blocks, and a document.ruleByID(name) function which returns the ruleset with the given id. Use Case: Similar to above, but the alteration you want to perform is to simply disable the rule temporarily. (I'm not sure of the usefulness of this to ordinary authors, but it's used in editors constantly.) Problem: Right now, you have to delete the rule and remember it yourself, so you can restore it later. Possible Solution: Add a rule.disable() and rule.enable() to CSSRule, and rule.disable(‘property’) and rule.enable(‘property’) to CSSStyleRule, which “turn off” the ruleset or the specific property, and turn it back on again. This could possibly be reflected by a !disabled value appended to the property. Use Case: I’m writing a javascript library that figures out what to do based on the author providing custom CSS. I'm writing a javascript shim that looks for unimplemented CSS and provides a simulated implementation. Problem: Currently, doing this requires iterating through all the stylesheets in the document, and for each stylesheet, iterating through every ruleset to check if a particular property exists. If you're looking for a new/custom property, it's even worse - you have to get the text of each stylesheet, *parse the whole thing yourself*, and then find the rules you wanted. Possible Solution: Allow declaration blocks to be selected with Selectors. A stylesheet is a root node, rulesets are children (some types of rulesets, like media rules, can have more rulesets as children), and properties are attributes on the ruleset. You could then easily find your custom property by doing something like: var x = document .queryRules(“ruleset[my-custom-property]”)[0] .style.myCustomProperty; Calling queryRules() on document would apply it across all active stylesheets and aggregate the results. Calling it on a particular stylesheet would just query that particular stylesheet. Note: Most browsers throw away unrecognized properties. The partial exception is current IE, which pretends the rule doesn't exist (it doesn't show up if you enumerate .style nor does it affect .style.length), but still records the property and make it available. That is, with something like this: div { color: red; foo: bar; } ...calling document.styleSheets[0].cssRules[0].style.foo returns "bar" in IE. This doesn't seem like a killer here, though - in the limit case, browsers can reparse the stylesheet when an unknown property is requested. After all, the parser knows what the property's name was - the error-handling implicitly looks for things that look like property names and values so it can skip over them properly. Assuming this becomes popular, implementations can presumably do this a lot better, like having some custom storage for unknown properties. Thoughts? ~TJ
Received on Monday, 11 April 2011 19:58:14 UTC