Making a panel shrink to fit a label

Godot Version

4.2.1

Question

I’m trying to create a panel with a label to use as a callout in my game.

The nodes look like this:
PanelContainer->Label

Here’s what I would like to achieve:

  1. When the text is longer than 200px, the label should auto-wraps and the panel shouldn’t be get than 200px (this I can achieve by setting the custom_minimum_size of the PanelContainer to 200)
  2. When the text is shorter than 200px, the panel should shrink accordingly

I feel like I tried everything (both in the editor and through) code, but I just can’t get nr 2 to work.
Has anyone achieved something like this?

Thanks

this just looks like a label will need to have its container that control maximum size and the label itself can have its own theme override StyleBox that act like panel container’s background texture,
here the proposal about maximum size for child Add a `rect_max_size` property to Control nodes · Issue #1802 · godotengine/godot-proposals · GitHub

there you can find a SpanLimiter code but it’s in Godot 3 script, so you will want to convert it to godot 4 first to use it

Have you tried setting: PanelContainer → Layout → Container Sizing → Horizontal and Vertical from Fill to Shrink Begin?

Just tried it - no luck…
Thanks for trying though, I sure am surprised this doesn’t seem doable.

You can set a background to the label by setting the Label.normal theme StyleBox

But if you still want to use a PanelContainer then you’ll need to listen to the Label Control.resized signal and change the PanelContainer Control.size to the Label minimum size with Control.get_minimum_size()

Example:

@tool
extends PanelContainer

@onready var label: Label = $Label

func _ready() -> void:
	# set the label minimum width to 200px
	label.custom_minimum_size.x = 200
	# set autowrap
	label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	# set the size flags to begin to avoid the label being positioned incorrectly when changing the size
	label.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
	label.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
	# When the label gets resized, change the size of this panel container to the minimum size of the label
	label.resized.connect(func():
		size = label.get_minimum_size()
	)
1 Like

Unfortunately this has no effect - the panel always remains 200px wide, and label.get_minimum_size() always returns 1.