Module rsvg::css

source ·
Expand description

Representation of CSS types, and the CSS parsing and matching engine.


Consider a CSS stylesheet like this:

@import url("another.css");

foo, .bar {
        fill: red;
        stroke: green;

#baz { stroke-width: 42; }

The example contains three rules, the first one is an *at-rule, the other two are qualified rules.

Each rule is made of two parts, a prelude and an optional block The prelude is the part until the first { or until ;, depending on whether a block is present. The block is the part between curly braces.

Let’s look at each rule:

@import is an at-rule. This rule has a prelude, but no block. There are other at-rules like @media and some of them may have a block, but librsvg doesn’t support those yet.

The prelude of the following rule is foo, .bar. It is a selector list with two selectors, one for foo elements and one for elements that have the bar class.

The content of the block between {} for a qualified rule is a declaration list. The block of the first qualified rule contains two declarations, one for the fill property and one for the stroke property.

After the first qualified rule, we have a second qualified rule with a single selector for the #baz id, with a single declaration for the stroke-width property.

Helper crates we use

  • cssparser crate as a CSS tokenizer, and some utilities to parse CSS rules and declarations.

  • selectors crate for the representation of selectors and selector lists, and for the matching engine.

Both crates provide very generic implementations of their concepts, and expect the caller to provide implementations of various traits, and to provide types that represent certain things.

For example, cssparser expects one to provide representations of the following types:

  • A parsed CSS rule. For fill: blue; we have ParsedProperty::Fill(...).

  • A parsed selector list; we use SelectorList from the selectors crate.

In turn, the selectors crate needs a way to navigate and examine one’s implementation of an element tree. We provide impl selectors::Element for RsvgElement for this. This implementation has methods like “does this element have the id #foo”, or “give me the next sibling element”.

Finally, the matching engine ties all of this together with matches_selector(). This takes an opaque representation of an element, plus a selector, and returns a bool. We iterate through the rules in the stylesheets and gather the matches; then sort the matches by specificity and apply the result to each element.



  • A CSS at-rule (or ruleset)
  • Prelude of at-rule used in the AtRuleParser.
  • Dummy type required by the SelectorImpl trait.
  • Origin for a stylesheet, per CSS 2.2.
  • Errors from the CSS parsing process
  • A CSS rule (or ruleset)
  • This enum represents the fact that a rule body can be either a declaration or a nested rule.


  • Runs the CSS cascade on the specified tree from all the stylesheets