The implementation of the feature only outwardly looks simple.

In order to implement the complex selectors, the CSS runtime is implemented as a specialized state machine: an appearance of a new HTML element in the parsing stream pushes the event to all selectors (they may either refuse the event or to change the entire runtime state). A closing HTML tag pops to previous state. At any document parsing point we can request the runtime to generate a list of properties matches the current CSS runtime state. Actually it is done for every parsed HTML element and it defines the final document style.

The single-pass approach works well in most cases, but :last-child / :last-of-type creates problems for it because it cannot look ahead and determine if a particular tag is the last one or not. Keep in mind that :last-child / :last-of-type can be combined with other conditions such as P[attr=value]:last-child, so a quick HTML scan by tag name is not enough. Also, the actual “last child” could be at the end of a huge HTML document, megabytes away from the current parse point.

All of our previous approaches to implementing :last-child / :last-of-type functions resulted in a significant performance degradation, drastic for large HTML and CSS documents. We’ve already tried to fork HTML and CSS parsers to check in idle run whether a particular element is the last one in terms of selector conditions; we tried to clone the CSS state with last=true and last=false and then remove the misguessed state. Both approaches did not match our acceptance criteria from performance perspective.

We have not exhausted new ideas on how to implement the feature yet, but, I’m afraid, we will be able to return to them only closer to September