Up to date

This page is up to date for Godot 4.1. 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:

../../_images/tank-kings-by-winterpixel-games.png

A "Gear Up!" screen in Tank Kings, courtesy of Winterpixel Games

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.

Note

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.

Theme items

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:

  • Color

    A color value, which is often used for fonts and backgrounds. Colors can also be used for modulation of controls and icons.

  • Constant

    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).

  • Font

    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.

  • Font size

    An integer value, which is used alongside a font to determine the size at which the text should be displayed.

  • Icon

    A texture resource, which is normally used to display an icon (on a Button, for example).

  • StyleBox

    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.

Theme types

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 font_color item in a type LineEdit.

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.

Note

Child classes can use theme items defined for their parent class (Button 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)

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 the base Label type. An individual Label control can then be set to use the Header variation for its type, and every time a theme item is requested from a theme this