CSS-like styling for GTK+

Lately, I’ve been intermitently working on the gtk-style-context branch, which is meant to supersede GtkStyle and get rid of all its limitations in creating contemporary UIs, to name a few:

  • Cairo as a first class citizen: This means elements may be rendered on any surface, not only on X resources.
  • No more widget peeping: There is now a GtkWidgetPath abstraction, which fully defines the widget in a styling point of view.
  • Widget is no longer a plain area: Widgets may define named regions, which can be styled independently.
  • Animation support: Theming engines no longer have to hack their way to animate some UI element, there is built in support for animations on state changes.
  • No more detail string: GtkStyleContext may contain several classes, which can be checked by the theming engine.

As a consequence, the GtkRC parser has been replaced as well by a CSS-like parser, the property names aren’t currently fully following the CSS spec (Selectors do), and there are some semantics that don’t apply, but OTOH there is support for symbolic colors. The format is enough for people into web development to get the gist of it:


@named-color: #01a4f9;

/* Set background on GtkCheckButton
* and other types inheriting from
* it
*/
GtkCheckButton {
  background-color: #14a414;
}

/* Theme buttons inside a table,
* not necessarily a direct child
*/
GtkTable GtkButton {
  foreground-color: #f01df4;
  text-color: #f01df4;
}

/* Theme scale widgets that are
* direct children of a GtkTable
*/
GtkTable > GtkScale {
  foreground-color: #01ab39;
}

/* Widget states may be defined */
GtkButton:active {
  background-color: #f01;
}

/* Generic classes may be used as well */
.button:prelight {
  background-color: #10f;
}

/* any widget with this name will be themed */
*#some-widget-name {
  font-color: #e0a;
}

/* This will apply if both states happen on the
* widget, such as a pressed checkbox button with
* the pointer on it.
*/
GtkButton:active:prelight {
  background-color: shade (#f01, 1.3);
}

/* Set bg color on odd rows */
GtkTreeView row:nth-child(even) {
  background-color: #f00f10;
}

/* Theme first notebook tab differently */
GtkNotebook tab:nth-child(first) {
  background-color: @named-color;
}

/* And paint a bit darker if active */
GtkNotebook tab:nth-child(first):active {
  background-color: shade (@named-color, 0.7);
}

/* Animate checkbutton transitions */
GtkCheckButton:active {
  transition: 200ms ease-in-out;
}

If you compile the gtk-style-context branch and put this into ~/.gtk-2.0.css, you should see something like this:
(Disclaimer: this is the default engine, I know it’s ugly, let’s leave art for artists)

At the moment, widgets have been roughly ported to this new code indirectly through making GtkStyle rely on GtkStyleContext, so they could be a lot more talkative about the elements they render and contain. If you’re a theme engine developer try out the GtkThemingEngine API, this is what theming engines must implement and use in order to render UI elements, constructive feedback is most welcome.

35 thoughts on “CSS-like styling for GTK+”

  1. Wow, this is incredible!

    This alone will do wonders for the future of Gtk+!

    This has got to be one of the /most/ requested features in Gtk, and having this code is the single most important work that Gtk+ needs to help developers.

    Thanks a lot for the work Carlos!

  2. Might this help GTK+ and Qt theming converge? It would be really nice if my Qt theme could “just work” with my GTK+ applications (i.e. Firefox) and vice versa.

  3. Why would you ever want to do this? Doesn’t the theme engine do the rendering of widgets for you? Why would you want a single widget to be a different colour to the rest, which will potentially clash with the theme.

  4. Meh. We should be getting rid of gtk styling altogether and concentrating on one, beautiful theme that shouts ‘gtk’ or ‘GNOME to the world’. Not encouraging Joe Web Hacker to add to the thousands of half-assed, half-finished themes we have already.

  5. Thanks all for the positive comments 🙂

    @mmonreal: I’m aiming to have this ready for GTK+ 3.0

    @alex: Maybe not converge, but nothing would stop Qt and others to mimic GTK+ appearance without resorting to hacks such as keeping a widget pointer, AFAICS QGtkStyle could do wonders with this.

    @nona: That is certainly a possibility, I’ll keep it in mind, thanks 🙂

    @bob: well, it is up for themes to do something sensible with this, in the same way they ship a gtkrc file, they’d need a css file. And users have been always able to mess things up through ~/.gtkrc-2.0 🙂

    @Fizzy: GTK+ works on different platforms, where it should fit in just fine, and there is also a need for a accessible themes, I’m afraid you can’t get rid of theming like that

  6. Props for named colors. Having CSS stylesheets is great for suddenly opening doors to hundreds of designers familiar with it. I also like the cascading – defining basic style with a generic selector and then diving in for specific widget. What I expect from the theming to provide for me:

    – padding, border, margin per widget
    – linear gradients for strokes (border) and fill, allowing RGBA colors. Radial gradients if I can have Christmas.
    – named colors [yay!]. Some color functions would be sweet — gtk’s shade, invert, saturate, complement
    – rounded corners / border-radius
    – specific widgets like a checkbox I don’t really want to paint manually so some svg>cairo convertor or just having SVG/images not be slow would be nice.
    – if images aren’t slow, some more complex widgets might benefit from 9slicing ala border-image in css3 http://www.w3.org/TR/css3-background/#border-images

  7. This is great! 🙂

    I would suggest supporting many of the CSS3 features (like border-image as Jakub was saying).

    And I think the property names should really follow the CSS spec e.g. ‘font-color’ and ‘foreground-color’ should be changed to ‘color’.

    Also a really really nice feature to have is the ‘inherit’ property and have a default style-sheet (like a user-agent stylesheet) that sets inherit properties on certain properties, e.g. color, font-family, etc (the ones that CSS currently has)

    Anyway this is really really great and I like it a lot!

Leave a Reply

Your email address will not be published. Required fields are marked *