Customize your own GTK3 themes using CSS

Eye Candy

© Lead Image © Feng Yu, Fotolia.com

© Lead Image © Feng Yu, Fotolia.com

Article from Issue 239/2020
Author(s):

We'll show you what a GTK3 theme is made of and how you can customize it to match your tastes.

The GTK3 toolkit and graphical UI library is the foundation for many Linux applications. The list of GTK3-based applications includes popular tools such as Evolution and Shotwell, as well as desktop environments like Gnome, Cinnamon, and XFCE. Early versions of GTK3 inherited several these engines from GTK2 and used to be very themeable, but in 2015, GTK3 developers removed much of the support for themes. Starting with version 3.14, GTK3 now only uses themes based on CSS markup. That change also marked a change in terminology: a GTK3 theme is now referred to as a style sheet. In today's GTK3, anyone can still make a style sheet and use artwork assets for more stunning looks.

This tutorial explains how a GTK3 theme is organized and what it takes to alter a theme or make a new theme based on an already existing one. I'll offer a real-world example of mastering a custom GTK3 theme using the CSS markup code. The goal is to help you produce a good-looking theme that fits your personal tastes.

Inside a Style Sheet

GTK3 is a foundation of the Gnome Shell desktop and that's why trends in Gnome affect the GTK3 UI library. One recent development is the inclusion of the stock Adwaita theme in the main Gnome codebase. Gnome developers tend to discourage the use of custom style sheets and themes, but the Linux community needs more freedom and more choice and is therefore committed to desktop customization. Currently, you will not find the Adwaita CSS code in /usr/share/themes, but you can start with any other theme. The best way to learn how to use CSS for theming GTK3 is to study an existing theme and then try to modify it.

A style sheet is a text file with a tree-like structure: the first level defines a UI widget, the second level describes its look, and the third level is used for describing widget states (Figure 1). There is normally one more level for widget state details, so the tree might have a deeper structure. A GTK3 application uses this tree structure as a reference for styling widgets (elements). Most of the top-level nodes are treated as either widget names or style classes.

Figure 1: The list of elements with all their states is long but easy to read.

When style classes are used in selectors, they have to be prefixed with a period. Widget names can be used in selectors like IDs. When used in a selector, widget names must be prefixed with a # character. The full specification of the CSS markup for GTK3 is available at the Gnome website [1].

In more complicated situations, selectors can be combined in various ways. To require that a node satisfies several conditions, combine several selectors into one by concatenating them. To only match a node when it occurs inside some other node, write the two selectors after each other, separated by whitespace. To restrict the match to direct children of the parent node, insert a > character between the two selectors.

The following example illustrates the aforementioned markup:

notebook > header > tabs > arrow,
button {
  min-height: 20px;
  min-width: 16px;
  padding: 2px 6px;
  notebook > header > tabs > arrow,
  button.flat {
    background-color: transparent;
    background-image: none;

Modern GTK3 themes are complex and feature several files for style definitions, colors, and usually some artwork assets too (Figure 2). The theme is a complex mix of several modules and parts, some of which use plain CSS while others use Sassy Cascading Style Sheets (SCSS) for the sake of some extended features that are not part of the universal CSS standard. So, the usual components are: gtk.css and gtk-dark.css – main reference files with a comprehensive description of all widgets, their states, and their actions, from header bars to menus, and whatnot. The contents of files is as follows:

  • _colors.scss and _colors-public.scss – global color definitions that define the looks for light and dark theme variants.
  • common.scss – paddings, backgrounds, outlines, offsets, etc. This is the right place to commit changes or other tweaks to alter the vanilla style sheet.
Figure 2: A good theme is more than just CSS code. Buttons, checkboxes, and lots of other elements use external artwork assets.

You may find extra .sccs files used to override certain style elements for designated apps, but they are arbitrary.

Before the source files of a GTK3 theme can be used to actually style something, they need to be processed by the SASSC generator [2], which bakes the final CSS files out of source SCSS and CSS files.

The list of general definitions in gtk.css is huge; it takes over 2,000 lines of code. Add common.scss, which has two times more lines, and you'll know why most theme developers just fork Adwaita and only maintain a series of overrides instead of mastering their themes from scratch. The code for Gnome's default Adwaita theme is available on GitHub [3].

Another reason for modifying the Adwaita theme is that Gnome Shell and the GTK codebase frequently change in a way that can cause custom themes to become broken. Therefore, it makes sense to alter only what is needed and apply that on top of the stock GTK style sheet. This is exactly what Canonical does with their Yaru theme for Ubuntu, and many other vendors take the same approach.

Altering a Theme

Many Linux users dislike the wide paddings and offsets in Adwaita. It's not just a matter of taste – those too-spacious elements eat a lot of screen real estate and leave less space for useful content. As an example of modifying a theme, I'll make the Nautilus path bar (or search bar) smaller. I'll begin by overriding the .path-bar-box element for global GTK3 definitions. Create the gtk-light.scss file with the contents of Listing 1.

Listing 1

gtk-light.scss

@import 'common';
.nautilus-window {
    .path-bar-box {
        border: 1px solid rgb(182,182,179);
        border-radius: 3px;
        &:not(:backdrop) {
            background-color: rgb(232,232,231);
        }
    }
}

The code in Listing 1 changes the path bar border width, its color, and rounding radius. The &:not(:backdrop) part defines the look of every included element except for backdrop, which is an easy way to apply many changes at once if you have just a single or very few exceptions.

Next, copy this file as gtk-dark.css and change the rgb values to some darker shades. This way, you will maintain the dark theme support within the altered theme.

It is now time to define the actual look of the GTK3 widgets in the _common.scss file. First, define the minimum values for the headerbar.titlebar element, including details for the window button(s) and path bar (Listing 2).

Listing 2

headerbar.titlebar Element

headerbar.titlebar {
    min-height: 0;
    button {
        min-height: 16px;
        min-width: 16px;
        padding: 4px;
        &.text-button {
            min-width: 100px;
        }
    }
    .path-bar {
        button {
            min-width: 0;
        }
    }
    .path-bar-box {
        padding: 1px 0;
    }
}

Next goes the notebook header, which represents the area with tabs just below the header bar (Listing 3).

Listing 3

notebook header

notebook header {
    margin: 0;
    padding: 0;
    tabs {
        margin: 0;
        padding: 0px;
        tab {
            min-height: 20px;
            min-width: 42px;
            padding: 4px 12px;
            margin: 0;
        }
    }
    &.top tabs tab {
        padding-top: 3px;
        padding-bottom: 4px;
    }
    &.bottom tabs tab {
        padding-top: 4px;
        padding-bottom: 3px;
    }
    &.left tabs tab {
        padding-right: 16px;
    }
    &.right tabs tab {
        padding-left: 16px;
    }
    tabs button {
        min-height: 0;
        min-width: 0;
        padding: 0;
        margin-left: 10px;
    }
}

The values in pixels are my personal estimates, but they are all smaller than what Adwaita suggests by default. As for the rest, you still need to define a small portion of extra UI elements further in the current file (Listing 4).

Listing 4

UI Elements

spinbutton, button {
    min-height: 20px;
    min-width: 16px;
    padding: 2px 4px;
}
spinbutton {
    padding: 0;
}
entry {
    min-height: 24px;
}
switch slider {
    min-height: 24px;
    min-width: 42px;
}
row.activatable {
    min-height: 20px;
    padding: 4px 4px;
}
.nautilus-window .path-bar-box {
    border-radius: 3px;
    border-style: solid;
    border-width: 1px;
}

The paddings part is rather obvious, but as for the multiple min-height values, you need them to make sure that elements within the same area have consistent height and fit nicely into the 24px-tall entry panel. Elements like button, spinbutton, and row.activatable are 20px tall and have one vertical padding of 4px, which adds up to the same 24px.

Once you have made the changes to the code, you need to compile the .scss files into final .css files with the help of the SASSC generator. Each of the two source files should be processed as follows:

$ sassc -M -t compact gtk-light.{scss,css}
$ sassc -M -t compact gtk-dark.{scss,css}

The SASSC tool will merge the contents of each of the two files with the appropriate lines from the _common.scss file and produce the resulting ready-to-use CSS files. The only thing left is to rename files and put them in the right places. Create a folder with a theme name, then add the gtk-3.0 subfolder, and finally, copy your CSS file to the subfolder as gtk.css. Copy the theme folder to ~/.themes and then apply the theme using the appropriate tool of your desktop environment (e.g., Gnome Tweak Tool). There is also the great gtk3-widgets-factory command that lets you easily see all GTK3 widgets at once and check if they look correct with your theme (Figure 3).

Figure 3: gtk3-widgets-factory lets you see all UI elements combined on a single canvas and check if the theme applies correctly.

Changing Colors

Paddings and widths aren't always an issue. Sometimes all you need is to change the stock style sheet colors to something more eye-pleasing. If that is your case, consider the following sequence as a basic template.

First, make a copy of the theme you want to edit. Locate the _colors.scss file and make some edits to it. In most cases, the following seven values are used to define the palette: $base_color, $text_color, $bg_color, $fg_color, $selected_bg_color, $selected_fg_color, and $top_hilight (pretty much self-explanatory). A common convention is to use color values in HEX (#343536) or in plain text format (red, green).

Convert the main .scss file with SASSC. This will take color edits into account:

$ sassc -M -t compact gtk_file.{scss,css}

Rename and place the files into the theme folder, and you can use the theme with new colors.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News