How to Style Your GTK App with CSS and Haskell – codeburst

How to Style Your GTK App with CSS and Haskell

Jun 28, 2018 · 5 min read

For the upcoming release of Gifcurry an open-source, video-to-GIF maker — a completely custom theme was made using CSS and Haskell. The new theme will help maintain a more consistent look and feel across platforms and for Linux — across distros. The theme also ensures the need for only one set of custom icons.

Creating a GTK desktop app and styling it like you would a web application is a great alternative to frameworks like Electron. You can reuse your CSS knowledge and ship a cross-platform product with reduced system requirements. Of course Haskell isn’t required, as you can create and style GTK apps without it, but why would you want to? 😛

The CSS-like syntax will hopefully be much more familiar to many people, lowering the barrier for custom theming. — https://developer.gnome.org/gtk3/stable/gtk-migrating-GtkStyleContext-css.html

Gifcurry running on Ubuntu 14.04

When building a custom theme for your GTK application, you’ll have to consider supporting older versions of GTK. If you have Ubuntu 14.04 users for instance, you’ll need to support the GTK 3.10 CSS file format. Ubuntu 16.04 users will need support for GTK 3.18.

Gifcurry aims to support GTK 3.10 all the way up to GTK 3.24 and beyond. Between 3.10 and now, there are some commonalities but big changes occurred in 3.18, 3.19, and 3.20. Gifcurry applies a base styling and then detects the machine’s GTK version applying more styling rules as the version number goes higher.

Some of the big changes include:

  • Element selectors like GtkButton turning into button.
  • Class selectors turning into element selectors like GtkSpinButton .entry turning into spinbutton entry.
  • Pseudo classes like :insensitive becoming :disabled.
  • Non-standard properties like -gtk-icon-shadow added in later versions.

You can combine most of the differences in the same CSS file and there won’t be any conflicts or exceptions raised.

entry selection,
.entry:selected {
  background-color: #000;
}

GTK will raise exceptions, when parsing your CSS data, for situations like an unknown property or incorrect syntax. This of course doesn’t happen for the web where you browser crashes because of a bad CSS file. Nonetheless, you should test any rules you add. GTK will issue warnings for deprecated rules so be sure to watch the standard streams.

There are a lot of elements and states to consider when creating a whole theme. Depending on what widgets you use, you can get away with not specifying everything.

What I recommended is to select your favorite GTK theme as your system theme. Afterwards, start your app from the terminal specifying you want the interactive debugger.

$ GTK_DEBUG=interactive my-gtk-app

This GUI debugger allows you to inspect any element/node and see what its CSS properties, children, parent, style classes, state, and more are. You can change the theme on the fly and also update the CSS rules as the app is running. It is similar to Chrome’s DevTools but you can’t point-and-click update the CSS properties for example. To update the CSS, you’ll have to click the CSS tab and write out your changes in the provided text box. As you write out your rules, it will underline any errors and/or warnings.

Using the interactive debugger, you can quickly build up the CSS rules that make up your theme. After you get it looking pixel perfect, select the visual tab and change the theme. Look for any breakages and patch your rules as needed. The more themes you test against, the more your app theme will look consistent no matter what the GTK system theme is.

After you’re finished with one GTK version, switch to another and continue this same workflow. I like to test GTK 3.22, 3.18, and 3.10 simultaneously using two virtual machines running Ubuntu 14.04 and Ubuntu 16.04.

You have a few options for getting the CSS rules to GTK. You can write plain CSS, stick it in a .css file, and apply it via the GTK API.

button {
   color: white;
   background: #000;
}

styleFile 
  <- getDataFileName "data/style.css"GI.Gtk.cssProviderLoadFromPath
  provider
  (Data.Text.pack styleFile)GI.Gtk.styleContextAddProviderForScreen
  screen
  provider
  cssPriority

Another option is to use your favorite CSS preprocessor, stick it into your build chain, generate the file, and then apply that via the GTK API. Since we’re using Haskell, we can use Clay — “a CSS preprocessor […] implemented as an embedded domain specific language (EDSL) in Haskell.”

The nice thing about using Clay is that we don’t have to stick it into the build process, generate a .css file, and load it via the GTK API. Clay allows us to stay in Haskell, generate the CSS rules at run time, and apply the rendered output via cssProviderLoadFromData.

let css =
        encodeUtf8 $
          render $
            button ? do
              color white
              background "#000"GI.Gtk.cssProviderLoadFromData
    provider
    cssGI.Gtk.styleContextAddProviderForScreen
    screen
    provider
    cssPriority

If you’ve thought about creating a desktop app, GTK is a great solution that allows fully customizable styling. Using CSS, you’re in complete control of the look, feel, and branding of your app just like you would be with the web. The CSS is slightly different but you’ll hardly notice. And if you need something stronger than styling, you can always create your own custom widget.


Interested in GTK apps? Take a look at Movie Monad. Need a video-to-GIF maker? Download Gifcurry. Enjoyed this article? Show your support by clicking the applause button. Thanks!

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.