Up to date
This page is up to date for Godot
If you still find outdated information, please open an issue.
Introduction to GUI skinning¶
It is essential for a game to provide clear, informative, and yet visually pleasing user interface to its players. While Control nodes come with a decently functional look out of the box, there is always room for uniqueness and case-specific tuning. For this purpose Godot engine includes a system for GUI skinning (or theming), which allows you to customize the look of every control in your user interface, including your custom controls.
Here is an example of this system in action — a game with the GUI that is radically different from the default UI theme of the engine:
Beyond achieving a unique look for your game, this system also enables developers to provide customization options to the end users, including accessibility settings. UI themes are applied in a cascading manner (i.e. they propagate from parent controls to their children), which means that font settings or adjustments for colorblind users can be applied in a single place and affect the entire UI tree. Of course this system can also be used for gameplay purposes: your hero-based game can change its style for the selected player character, or you can give different flavors to the sides in your team-based project.
Basics of themes¶
The skinning system is driven by the Theme resource. Every Godot project has an inherent default theme that contains the settings used by the built-in control nodes. This is what gives the controls their distinct look out of the box. A theme only describes the configuration, however, and it is still the job of each individual control to use that configuration in the way it requires to display itself. This is important to remember when implementing your own custom controls.
Even the Godot editor itself relies on the default theme. But it doesn't look the same as a Godot project, because it applies its own heavily customized theme on top of the default one. In principle, this works exactly like it would in your game as explained below.
The configuration that is stored in a theme consists of theme items. Each item has a unique name and must be one of the following data types:
A color value, which is often used for fonts and backgrounds. Colors can also be used for modulation of controls and icons.
An integer value, which can be used either for numeric properties of controls (such as the item separation in a BoxContainer), or for boolean flags (such as the drawing of relationship lines in a Tree).
A font resource, which is used by controls that display text. Fonts contain most text rendering settings, except for its size and color. On top of that, alignment and text direction are controlled by individual controls.
An integer value, which is used alongside a font to determine the size at which the text should be displayed.
A StyleBox resource, a collection of configuration options which define the way a UI panel should be displayed. This is not limited to the Panel control, as styleboxes are used by many controls for their backgrounds and overlays.
To help with the organization of its items each theme is separated into types,
and each item must belong to a single type. In other words, each theme item
is defined by its name, its data type and its theme type. This combination
must be unique within the theme. For example, there cannot be two color items named
font_color in a type called
Label, but there can be another
item in a type
The default Godot theme comes with multiple theme types already defined, one for every built-in control node that uses UI skinning. The example above contains actual theme items present in the default theme. You can refer to the Theme Properties section in the class reference for each control to see which items are available to it and its child classes.
Child classes can use theme items defined for their parent class (
and its derivatives being a good example of that). In fact, every control can
use every theme item of any theme type, if it needs to (but for the clarity and
predictability we try to avoid that in the engine).
It is important to remember that for child classes that process is automated.
Whenever a built-in control requests a theme item from the theme it can omit
the theme type, and its class name will be used instead. On top of that,
the class names of its parent classes will also be used in turn. This allows
changes to the parent class, such as
Button, to affect all derived
classes without the need to customize every one of them.
You can also define your own theme types, and additionally customize both built-in controls and your own controls. Because built-in controls have no knowledge of your custom theme types, you must utilize scripts to access those items. All control nodes have several methods that allow to fetch theme items from the theme that is applied to them. Those methods accept the theme type as one of the arguments.
var accent_color = get_theme_color("accent_color", "MyType") label.add_color_override("font_color", accent_color)
Color accentColor = GetThemeColor("accent_color", "MyType"); label.AddColorOverride("font_color", accentColor);
To give more customization opportunities types can also be linked together as
type variations. This is another use-case for custom theme types. For example,
a theme can contain a type
Header which can be marked as a variation of
Label type. An individual
Label control can then be set to
Header variation for its type, and every time a theme item is
requested from a theme this