12

Is there an open source or generic implementation of CSS that can be applied to an arbitrary display hierarchy? I'm trying to build one for the Flash display hierarchy in AS3.

I'm curious about the procedure used to apply CSS styles to a display hierarchy. It seems to me that some or all selectors would have to be re-applied to the entire display list every time a display object is added, removed, or repositioned, as well as when events occur such as focus changes, given the existence of selectors like "first-child" and pseudo-selectors like ":focus".

Would the initial application of styles involve scanning the entire display list one element at a time, applying styles, or would all objects be sorted up-front and associated with particular rule categories? Or something like that.

I'm really looking for a good general resource on a real implementation.

Update: I'm probably looking for something at the level of this, but I don't know if this is state of the art: "Hierarchical constraints provide a simple, unifying way of understanding much of the CSS 2.0 specification. This viewpoint also suggests that constraint solvers provide a natural implementation technique. Each style property and the placement of each element in the document can be modeled by a variable. Constraints on these variables arise from browser capabilities, default layout behavior arising from the type of the element, from the document tree structure, and from the application of style rules. The final appearance of the document is determined by finding a solution to these constraints." Which begs the question of how and when to solve the constraints.

Triynko
  • 18,766
  • 21
  • 107
  • 173
  • Flex uses CSS with MXML, although I'm not sure if its CSS implementation is open source (it probably is). – BoltClock Apr 29 '14 at 00:17
  • I'll look into that. IBM has a nice writeup on CSS in Flex: http://www.ibm.com/developerworks/web/library/wa-cssflex/index.html I built my own XML display list parser, which I'll be applying CSS support to soon. One place where my implementation will differ is that styles will be applied to both DisplayObjects and TextFields alike. I was thinking of preserving functionality of normal selectors like "tagname" and ".classname" by having them operate exclusively on htmlText in TextFields, while new selectors like "#instancename" and "$instancetype" would apply to object names and object types. – Triynko Apr 29 '14 at 15:28
  • I've already implemented support for intelligent attribute parsing (based on known object type + attribute name pairs, as well as checking objects for an implementation of an IAttributeParser interface), reference resolving in attributes (e.g. other objects in the display list can be referenced via "this.objectname", deferred assignment of reference values and textfield text to ensure references are resolvable and text is assigned last, data-binding (2-way, 1-way, 1-way-to-source), namespace imports, virtual base names for references, tag aliases, constructors that take parameters, and more. – Triynko Apr 29 '14 at 15:36
  • I also just found webkit's CSS implementation: http://www.webkit.org/projects/css/ If I manage to process and understand the implementation, I'll post an answer here, unless someone who already understands it is able to post and explanation. I'm already seeing under trunk/source/Webcore folders for css and cssjit, with methods like SelectorCodeGenerator::generateElementIsNthChild(). – Triynko Apr 29 '14 at 15:43
  • 2
    There's a paper [here](http://www.html5rocks.com/en/tutorials/internals/howbrowserswork) with a high-level explanation of how CSS is implemented in a typical Web browser layout engine such as WebKit, covered in the last few sections. – BoltClock Apr 29 '14 at 15:47
  • That's an awesome article. The "Style Computation" section really outlines the problem well, which is 90% of the solution. I'll keep looking for more detailed info. – Triynko Apr 29 '14 at 15:54
  • Damn... "WebCore simply throws a global switch when any sibling selector is encountered and disables style sharing for the entire document when they are present. This includes the + selector and selectors like :first-child and :last-child." That's one way to handle it, sledghammer to kill a fly, I'll remember not to use those selectors, ever, lol. – Triynko Apr 29 '14 at 16:00
  • Very useful: "After parsing the style sheet, the rules are added to one of several hash maps, according to the selector. There are maps by id, by class name, by tag name and a general map... If the selector is an id, the rule will be added to the id map, if it's a class it will be added to the class map etc. This manipulation makes it much easier to match rules. There is no need to look in every declaration: we can extract the relevant rules for an element from the maps. This optimization eliminates 95+% of the rules, so that they need not even be considered during the matching process(4.1)." – Triynko Apr 29 '14 at 16:08
  • Yes; additionally, in general, [complex selectors are matched from right to left](http://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left) (secondary to these optimizations of course), evaluating each sequence of simple selectors and stepping through each combinator in doing so. – BoltClock Apr 29 '14 at 16:12
  • Nice article provided by both of you @BoltClock. Thanks a lot. – Atal Shrivastava May 20 '14 at 19:54

1 Answers1

1

@Triynko, regarding How Browsers Work at HTML5 Rocks:

Damn...

WebCore simply throws a global switch when any sibling selector is encountered and disables style sharing for the entire document when they are present. This includes the + selector and selectors like :first-child and :last-child.

That's one way to handle it, sledghammer to kill a fly, I'll remember not to use those selectors, ever, lol.

Very useful:

After parsing the style sheet, the rules are added to one of several hash maps, according to the selector. There are maps by id, by class name, by tag name and a general map... If the selector is an id, the rule will be added to the id map, if it's a class it will be added to the class map etc. This manipulation makes it much easier to match rules. There is no need to look in every declaration: we can extract the relevant rules for an element from the maps. This optimization eliminates 95+% of the rules, so that they need not even be considered during the matching process(4.1).

And @BoltClock:

In general, complex selectors are matched from right to left (secondary to these optimizations of course), evaluating each sequence of simple selectors and stepping through each combinator in doing so.

References

Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265