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
-
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.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.
-
Plasma Desktop Will Soon Ask for Donations
The next iteration of Plasma has reached the soft feature freeze for the 6.2 version and includes a feature that could be divisive.
-
Linux Market Share Hits New High
For the first time, the Linux market share has reached a new high for desktops, and the trend looks like it will continue.
-
LibreOffice 24.8 Delivers New Features
LibreOffice is often considered the de facto standard office suite for the Linux operating system.
-
Deepin 23 Offers Wayland Support and New AI Tool
Deepin has been considered one of the most beautiful desktop operating systems for a long time and the arrival of version 23 has bolstered that reputation.