Customize your own GTK3 themes using CSS
Eye Candy
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.
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.
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).
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
(incl. VAT)
Buy Linux Magazine
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.
News
-
New Slimbook EVO with Raw AMD Ryzen Power
If you're looking for serious power in a 14" ultrabook that is powered by Linux, Slimbook has just the thing for you.
-
The Gnome Foundation Struggling to Stay Afloat
The foundation behind the Gnome desktop environment is having to go through some serious belt-tightening due to continued financial problems.
-
Thousands of Linux Servers Infected with Stealth Malware Since 2021
Perfctl is capable of remaining undetected, which makes it dangerous and hard to mitigate.
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.