HSplitContainer in Godot – Complete Guide

Welcome to our tutorial on the HSplitContainer in Godot 4. Mastering GUI elements and their behaviors is essential to creating polished and user-friendly games and applications. The HSplitContainer is one such element that can significantly enhance the interface of your project by providing an adjustable, two-panel layout that users can interact with. Whether you’re designing an elaborate game menu or creating an in-game inventory system, understanding how to use the HSplitContainer will empower your development skills and open up new creative possibilities. So let’s dive in and learn about this powerful component!

What is the HSplitContainer?

The HSplitContainer is a user interface control node provided by Godot Engine. As its name suggests, it’s designed to split its area horizontally into two sections. These sections can house any two child controls, and the space allocated to each can be adjusted by the user with a simple drag of the grabber—the divider between them.

What is the HSplitContainer Used For?

The primary use of the HSplitContainer is to create flexible layouts where the content can be resized according to user preference. This can be incredibly useful for creating custom UIs where you want to give the user control over how much space each section takes up—for example, in a file explorer or an adjustable game UI where players might resize their chat window or inventory panel.

Why Should I Learn to Use the HSplitContainer?

Learning to use the HSplitContainer will not only enhance the visual appeal and usability of your user interfaces but also give you more control over how content is presented within your game or application. An understanding of this control is a step toward more advanced Godot UI development, giving you the tools to handle dynamic content sizing, which is a cornerstone of modern user interface design. Plus, the skills you develop with HSplitContainer are transferable to other UI components, making your future learning curve that much more manageable.

CTA Small Image

Creating a Simple HSplitContainer

To begin using the HSplitContainer in your project, you first need to understand how to create one. Here’s a straightforward example that adds an HSplitContainer node to your scene and sets up two ColorRects as its children.

var split_container = HSplitContainer.new()

var left_panel = ColorRect.new()
left_panel.color = Color(1, 0, 0) # Red

var right_panel = ColorRect.new()
right_panel.color = Color(0, 0, 1) # Blue

This script will add an HSplitContainer node to the scene and two colored rectangles will appear side by side, which can be resized by dragging the separator.

Adjusting the Draggable Area

By default, the draggable area of the HSplitContainer, which is the separator that users drag to resize the panes, is set to a standard size. You can customize the appearance and behavior of this area with various properties. Let’s adjust the draggable margin and set a minimum size for both panes:

split_container.drag_margin = 10
left_panel.rect_min_size = Vector2(100, 0)
right_panel.rect_min_size = Vector2(100, 0)

These settings ensure that the draggable area is comfortable for the user to grab and that the panels can’t be resized smaller than a width of 100 pixels.

Configuring Panel Ratios

The HSplitContainer allows the initial ratio between the left and the right panels to be defined. This ratio gives you control over the starting sizes of the panels, without relying on user interaction from the start.

split_container.split_offset = int(split_container.rect_min_size.x * 0.3)

The `split_offset` property determines the position of the split in pixels. In the example above, we’ve set the left panel to take up 30% of the available width of the HSplitContainer upon first loading.

Responding to User Interaction

To make your application or game more dynamic, it’s important to respond to how users interact with the UI components. Connecting to signals emitted by the HSplitContainer when the user resizes the panels is a great way to create responsive behavior.

func _ready():
    split_container.connect("resized", self, "_on_HSplitContainer_resized")
func _on_HSplitContainer_resized():
    print("Panels have been resized")

The example above shows how to connect to the `resized` signal. This will print a message to the console every time the user resizes the panels.

By following these examples, you now have a fundamental understanding of how to create and customize an HSplitContainer, adjust the draggable area, configure the initial panel ratios, and respond to user interactions. This will set a solid foundation for further enhancing and integrating the HSplitContainer into your Godot projects.We now have a functioning HSplitContainer, but what if we want to create a more complex interface? Perhaps we’d like to nest additional controls within our panels or add functionality that depends on our container’s state. Let’s delve further into customization and usage.

Nesting Controls Within Panels

You can easily add more complex controls within each panel of the HSplitContainer. For instance, let’s place a Label in the left panel and a Button in the right panel. This demonstrates how you can build out a complete UI within the two sections of your split container.

var label = Label.new()
label.text = "Left Panel Content"

var button = Button.new()
button.text = "Click Me"

The nested controls will now appear within each corresponding panel, inheriting the properties and limitations of their parent containers.

Handling Button Interaction within HSplitContainer

Let’s go a step further and interact with the Button we’ve just added. We’ll connect the Button’s `pressed` signal to a custom function, offering us a chance to act upon user interaction.

button.connect("pressed", self, "_on_Button_pressed")

func _on_Button_pressed():
    label.text = "Button was pressed!"

When the Button is pressed, the text of the Label on the left panel will change, demonstrating a simple interaction within the HSplitContainer.

Adjusting Panel Visibility

Maybe you want to give users the ability to toggle the visibility of a panel. Here’s how you could set up a Checkbox control to hide or show the right panel, for instance.

var checkbox = CheckBox.new()
checkbox.text = "Toggle Right Panel"
checkbox.connect("toggled", self, "_on_Checkbox_toggled")

func _on_Checkbox_toggled(button_pressed):
    right_panel.visible = !button_pressed

This code snippet creates a new Checkbox control, adds it to the left panel, and connects its `toggled` signal to a function that hides or shows the right panel based on the checkbox’s state.

Programmatically Adjusting the Split

You might want to adjust the split container’s division programmatically, depending on certain conditions in your application or game. Here’s how you could reset the split to evenly distribute the space between the two panels.

func reset_split_evenly():
    var half_width = split_container.rect_size.x / 2
    split_container.split_offset = half_width

With this function, called `reset_split_evenly`, the split position is reset so that each panel has exactly half the width of the HSplitContainer.

Applying a Style to the HSplitContainer

To give our HSplitContainer a custom look, we can define a style for it. Let’s add a StyleBox to our grabber area for a visual overhaul.

var style = StyleBoxFlat.new()
style.bg_color = Color(.5, .5, .5)  # a stylish grey
split_container.add_stylebox_override("splitter", style)

With this snippet, we create a new StyleBoxFlat, set its background color, and apply it to the grabber, or ‘splitter’, of our HSplitContainer. Now the grabber will have a distinctive grey color, making it stand out from the rest of the UI.

These additional examples show that the HSplitContainer is not just a basic layout tool. It can be the foundation for creating a functional and interactive user interface, tailored to your project’s needs. As you build up complexity within your Godot projects, techniques like nested controls, signal connections, visibility toggling, and styling become invaluable. By mastering these, you ensure your UI is not only functional but also enjoyable for the users, enhancing their overall experience.Understanding how dynamic layouts respond to window size changes is crucial when developing resizable applications or games. Let’s explore how the HSplitContainer adjusts when the window is resized and ensure our UI remains functional and visually consistent.

Responding to Window Resizing

To handle window resizing gracefully, you can update the HSplitContainer’s size and position dynamically. Here’s an example of how to connect the resize event of the scene to update the container:

func _ready():
    get_tree().connect("screen_resized", self, "_on_screen_resized")

func _on_screen_resized():
    var new_size = OS.window_size
    split_container.rect_min_size = new_size

By connecting the `screen_resized` signal from the scene tree to a custom function `_on_screen_resized`, we make sure our container always fits the window size and resets the division of the panels.

Saving User Preferences for Panel Sizes

Users appreciate when their chosen layout preferences are remembered between sessions. Here’s how you might save the user’s adjusted split position using Godot’s `ConfigFile`:

var config = ConfigFile()

func save_split_position():
    config.set_value("layout", "split_position", split_container.split_offset)

func load_split_position():
    var err = config.load("user://preferences.cfg")
    if err == OK:
        var split_position = config.get_value("layout", "split_position", split_container.rect_size.x / 2)
        split_container.split_offset = split_position

Call `save_split_position` when the application is about to close or when the user manually saves settings, and `load_split_position` when the application starts up or when the scene containing your HSplitContainer loads.

Embedding an Editor within the HSplitContainer

In more complex applications, we may want to include a script editor or a similar component. To embed a multiline text edit node within the right panel of our HSplitContainer, we can do the following:

var text_edit = TextEdit.new()
text_edit.rect_min_size = Vector2(150, 300)  # Ensure it's reasonably sized

The `TextEdit` node provides a powerful set of features suitable for creating text boxes that can handle code editing, making it an excellent choice for an embedded editor in development tools and game editors.

Adding a Collapsible Side Panel

Sometimes, you may want to add functionality to collapse one of the panels fully. This can help maximize work area space. Let’s introduce a button to collapse and restore the right panel:

var collapse_button = Button.new()
collapse_button.text = ">>"
collapse_button.connect("pressed", self, "_on_CollapseButton_pressed")

var panel_visible = true

func _on_CollapseButton_pressed():
    panel_visible = !panel_visible
    right_panel.visible = panel_visible
    collapse_button.text = "<>"

This script adds a button with text ‘>>’. When pressed, it toggles the visibility of the right panel and updates its text to indicate the action (“<>” to collapse).

Leveraging Godot’s flexible UI system with the HSplitContainer can lead to a wide range of customized elements, building user interfaces that are both intricate and user-friendly. By continuing to experiment and incorporate new functionalities, like responding to window resizing, saving user settings, creating an embedded editor, and adding collapsible panels, we continue to sharpen our UI design skills, directly impacting the quality and usability of our projects.

Continuing Your Godot Journey

You’ve dipped your toes into the world of Godot’s UI components with the HSplitContainer, but this is just the beginning of what’s possible with Godot. If you’re keen to build on your new skills and delve deeper into game development, our Godot Game Development Mini-Degree is the perfect next step. You’ll find that beyond UI, there’s a universe of 2D and 3D game development lessons waiting for you, along with a comprehensive overview of the GDScript programming language, and much more.

With a range of courses suitable for both beginners and those with experience, there’s something for every stage of your learning journey. Not only will you be able to create a portfolio of real Godot projects, but also gain an understanding that could open doors to exciting career opportunities in the game development industry. And for those who wish to explore a broader range of topics in Godot, be sure to check out our full collection of Godot courses.

Join us at Zenva to go from beginner coder to game development pro, learning at your own pace, and becoming part of a community that shares your passion for creating amazing games. Let’s turn that curiosity into expertise together!


Embarking on the adventure of game development with Godot opens up a world of creativity and technical prowess, and mastering elements like the HSplitContainer is just the start. Through hands-on practice and exploration, you will find yourself crafting interfaces that are not just functional but also a joy to interact with. With each step on this journey, you’re not only building games; you’re crafting experiences, learning valuable skills, and perhaps, most importantly, having fun creating something truly unique.

Don’t let your momentum stop here; join us at Zenva’s Godot Game Development Mini-Degree to gain comprehensive insights and continue growing as a game developer. With each tutorial, challenge, and project, you’re paving the way towards mastering Godot. Whether your goal is to develop games for a living or simply to enjoy the process of bringing your ideas to life, we’re here to help you all the way. Let’s build some amazing games together!

Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.