CSS type selector specificity



Hey,

I intend to do a somewhat incompatible change to the CSS parsing
algorithms, and I'd like to announce it here. It's mostly meant
informational, but if you disagree with it, feel free to speak up, the
patch hasn't landed yet. If you don't know wtf I'm talking about, just
move along. Anyway, so I (or you) can point people to this when it
comes to it, here we go:

GTK 3.0 uses type information to decide a selectors specificity[1]. So
when matching selectors it looks at the widget type and how close it
is to the actual type. So CSS like
  GtkLabel { color: red }
  GtkWidget { color: blue }
will color a label red. With my changes, this label will be colored
blue, because the label matches both rules and it won't matter anymore
how close we are.

So why am I changing that? First of all, dropping satisfies KISS.
Second, specificity as defined by CSS is independant from the element
to be matched. So you can do a lot of optimizations when parsing and
before actually matching. You can write a selector comparison function
that doesn't have to look at the widget path to be matched. These are
important side effects but not the main reason.

The main reason is defining this specificity for selectors with
multiple elements to be matched.

Example 1: Javier

The example uses this CSS:
  GtkWindow GtkLabel { color: red }
  GtkBox GtkLabel { color: blue }

Javier is a very eager proponent of modern code. So he works on
getting rid of all the vertical/horizontal widgets. He is working on a
widget tree like this:
  GtkWindow => GtkVBox => GtkLabel
This label will be colored red with current CSS (because the first
match matches types exactly, the second doesn't).
Now he ports the app to GtkBox so it looks like:
 GtkWindow => GtkBox => GtkLabel
This will suddenly turn the label blue, because the second CSS rule
now matches exactly, too.

Example 2: Xan

The example uses this CSS:
  GtkWindow GtkLabel { color: red }
  GtkNotebook GtkLabel { color: blue }

Xan is working on Epiphany, a cool web browser without proper ad
blocking. The tabs in this browser are represented by a tree like
this:
  GtkWindow => GtkNotebook => tab => GtkLabel
Currently his app has blue labels, as the second rule matches exactly.
Xan is not a lazy Street fighter player, he wants to make his app more
awesome. Unfortunately the lazy GTK developers don't add the features
he wants to GtkNotebook. All is not lost however, because Xan can
create a notebook subclass - lets call it EphyNotebook - that does
have the features he wants. He ends up with this widget tree:
  GtkWindow => EphyNotebook => tab => GtkLabel
And suddenly the labels turn red, because the first rule now matches
exactly but the second doesn't anymore.


These two examples are reasonably close to reality to make we worried
that we will encounter cases like these and not know why things act
the way they do. I tried to come up with a definition of specificity
that does not have these problems but couldn't find a better one then
just dropping it altogether.

Note that the real-life implications for this should be minimal as
themes should be matching on classes instead of widget types most of
the time. And if they are not, they will likely be matching based on
actual types, not parent types - apart from maybe "GtkWidget", but
that's their own fault, they should be using "*" (which has a lower
specificity).

Benjamin


1: specificity for regular CSS is explained at
http://www.w3.org/TR/CSS21/cascade.html#specificity


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]