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 Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.
-
Fedora 41 Released with New Features
If you're a Fedora fan or just looking for a Linux distribution to help you migrate from Windows, Fedora 41 might be just the ticket.
-
AlmaLinux OS Kitten 10 Gives Power Users a Sneak Preview
If you're looking to kick the tires of AlmaLinux's upstream version, the developers have a purrfect solution.
-
Gnome 47.1 Released with a Few Fixes
The latest release of the Gnome desktop is all about fixing a few nagging issues and not about bringing new features into the mix.
-
System76 Unveils an Ampere-Powered Thelio Desktop
If you're looking for a new desktop system for developing autonomous driving and software-defined vehicle solutions. System76 has you covered.