How to vertically align text in a RichTextLabel?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Diet Estus

Labels have a valign attribute which can be used to set vertical alignment.

As far back as 2016, there was talk on GitHub of adding such an attribute for RichTextLabels. But as far as I can tell from the documentation, this never happened.

So my question: Is there a built-in way to vertically align potentially multiple lines of text in a RichTextLabel? If not, is there a workaround?

I have unknown, varying lengths of text for the RichTextLabel, and the RichTextLabel doesn’t automatically scale to the size of the text, so I don’t think I could use a VBoxContainer in a workaround.

:bust_in_silhouette: Reply From: Empyrean

You could add RichTextLabel inside VBoxContainer and set Alignment of it to Center. That way Whole RichTextLabel node will be always in vertical center of VBoxContainer.

The problem is that I have variable lengths of text for the RichTextLabel, and the RichTextLabel doesn’t automatically scale to the size of the text. Your method (I think) only works if you know the size of the text beforehand and can adjust the size of the label manually.

Diet Estus | 2018-04-11 12:13

I actually tested and my approach doesn’t seem to work. RichTextLabel seems to be squeezed to 0 height by center alignment of VBoxContainer and no text is visible.

And if add Min Size added, then RichTextLabel is no longer centered correctly and also when multiple lines are added, they don’t stretch label height.

Empyrean | 2018-04-11 12:39

1 Like
:bust_in_silhouette: Reply From: Zaven Muradyan

I needed this as well (specifically, needed to vertically center the text), and as a workaround ended up just dynamically setting the RichTextLabel’s margin-top based on the text data. Here’s basically the idea:

onready var label = get_node("path/to/RichTextLabel")
onready var label_rect = label.get_rect()  # Cache the original pos
# The max number of lines that the label can hold
const MAX_LINES = 3

func reposition_label(text):
	var regex = RegEx.new()
	regex.compile("\\n")
	# Assumes that there are no trailing newlines.
	var linecount = len(regex.search_all(text)) + 1

	var line_offset = label_rect.size.y / MAX_LINES / 2
	var top_offset = line_offset * (MAX_LINES - linecount)
	# Adjust the margin by the computed amount
	label.set_margin(MARGIN_TOP, label_rect.position.y + top_offset)

What this basically does, in English:

  1. Counts the number of newlines \n in the text
  2. Computes the offset it needs for each line that is “missing” (i.e. if the max lines that the label can hold is 3, and the actual line count is 1, then the label is “missing” 2 lines). This offset is actually 1/2 the size of the line, since we want to center everything, not push it to the bottom.
  3. Sets the label’s margin to its current value plus that offset value. It’s important to cache the label’s initial margin, so that this function can be called multiple times .
:bust_in_silhouette: Reply From: Reneator

Update: Labels now have an autowrap setting. Setting a label to expand in size-flags and deactivate the shrink. When now setting the align and valign as centered could have the same result as the description below.

I know this is an old post, but may have found a simpler solution (Maybe it didnt exists in the older versions. currently using 3.2.3.stable):

Im doing this inside of a PanelContainer, but think should work for other containers as well.

By activating “Fit Content Height” the RichTextLabel will resize itself to properly show the content inside itself.

Then in the Size Flags i deactivate the Vertical Fill, so that the RichTextLabel doesnt fill the entire container.

I activate the Size Flag “Vertical - Shrink Center” so the RichTextLabel gets aligned in the vertical center. And due to the “Fit content Height” the RichTextLabel doesnt get squished to zero height, so no need to work with min-size here.

And the Text should now be centered vertically!

You can test this best with like one or two words and a bigger panel. If the line-count is too big,the richtextlabel will automatically fill the container its in and push outwards.

Oh wow it works perfectly! Thank you very much!

Zero | 2022-02-08 21:05