'How to implement pseudo classes in a custom CSS engine (:hover etc) / How does a CSS engine work?

I'm trying to write a simple custom CSS engine and currently my structure is as follows: On startup parse all CSS rulesets and the DOM tree, and for each element, starting from the root, traverse downwards through each child, loop through all selectors and check if they apply, if so, collect the style rules and their specificity, and after going through all CSS rules, apply the style rules with the highest specificity to the current element.

That is a one time thing though, which works fine for simple cases but now I want to implement pseudo classes like :hover, which would require some kind of resetting all style rules for the element whose state has changed and re-running the whole style computation for it. I'm not sure, that's where I need help. I have tried to look through some open source code like for instance for Webkit, but code of professional codebases is way to abstract and spread out and I can't understand it or find the relevant parts.

Pseudocode (because my problem is language agnostic):

function apply_matching_rules_to_element(element, rulesets) {
  style = {}
  for ruleset in rulesets {
    for selector in ruleset.selectors {
      if does_selector_match(element, selector) {
        for declaration in ruleset.declarations {
          specificity = calculate_selector_specificity(selector)
          if not style[declaration.property] or (style[declaration.property] and style[declaration.property].specificity < specificity) {
            style[declaration.property] = { specificity = specificity, name = declaration.property, value = declaration.value }
          }
        }
      }
    }
  }
  for property in style {
    element.style[property.name] = property.name
  }
}

rulesets = parse_style("style.css")
root_element = parse_html("index.html")

function apply_rules(dom_element) {
  apply_matching_rules_to_element(dom_element, rulesets)
  for child in dom_element.children {
    apply_rules(child)
  }
}
apply_rules(root_element)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source