Skip to content

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented Sep 23, 2025

Objective

Add rem units support.

Fixes #21208

Solution

  • Base rem units on the root UI Node's TextFont component's font_size value, or, if not present, the size of the default font.
  • Add a Rem variant to Val and a rem helper construction function.
  • Add a rem field to ComputedUiRenderTargetInfo.
  • Update all the Val resolve functions to support rem units.

Based on #21181 for the default text style implementation.

Testing

* Removed `TextFont` and `TextColor` from the `Text`, `Text2d`, and `TextSpan` requires, replaced with `ComputedTextStyle`.
* `update_text_styles` updates the `ComputedTextStyle`s each frame from the text entities nearest ancestors with `TextFont` or `TextColor` components.
/// * For `margin`, `padding`, and `border` values: the percentage is relative to the parent node's width.
/// * For positions, `left` and `right` are relative to the parent's width, while `bottom` and `top` are relative to the parent's height.
Percent(f32),
/// Value relative to the font size of the root element
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this truly the root element of the hierarchy, or the default size in the resource? Normally the "r" in "rem" stands for "root" and everyone knows what it means, but perhaps in our case it should stand for "resource".

Copy link
Contributor Author

@ickshonpe ickshonpe Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses the value of the font size from the root UI node (if it has a TextFont component), or the DefaultTextStyle resource (if not).

I'm wondering if "rem" is the right name to use. I think it probably is, but "root element' is more web terminology again, which I want to avoid. I can only come up with ugly or silly alternatives though, like "rent" for "root entity".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I think we are dealing with conflicting needs here: a tradeoff between simplicity and flexibility.

Unlike the web where there's a single root element (html), in Bevy you have multiple roots. This means that if font size is tied to the UI root, then globally adjusting the font size requires updating every root instead of adjusting a single parameter in a resource.

There's also a concern about cost: for something like an editor or app with nested panels, UI hierarchies can get fairly deep, with a depth of 10-15 levels not being uncommon. Calculating the effective font size for a leaf node could require looking up components on every ancestor.

Copy link
Contributor Author

@ickshonpe ickshonpe Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I think we are dealing with conflicting needs here: a tradeoff between simplicity and flexibility.

Unlike the web where there's a single root element (html), in Bevy you have multiple roots. This means that if font size is tied to the UI root, then globally adjusting the font size requires updating every root instead of adjusting a single parameter in a resource.

Unless the root node is also a leaf text node, most of the time the only reason for setting a font size on the root would be to override the default font size from the resource. It feels to me like it would be very unintuitive if "rem" values weren't based on the font size of the node's root ancestor. Maybe we could have a seperate "gem" (or something) unit based on the global font size?

There's also a concern about cost: for something like an editor or app with nested panels, UI hierarchies can get fairly deep, with a depth of 10-15 levels not being uncommon. Calculating the effective font size for a leaf node could require looking up components on every ancestor.

The final implementation will do propagation on changes. When no font size is set, there won't be any need to walk up the tree. It will just access the default font resource directly.

@ickshonpe ickshonpe added C-Feature A new feature, making something new possible A-UI Graphical user interfaces, styles, layouts, and widgets D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Sep 24, 2025
@ickshonpe ickshonpe added the A-Accessibility A problem that prevents users with disabilities from using Bevy label Sep 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Accessibility A problem that prevents users with disabilities from using Bevy A-UI Graphical user interfaces, styles, layouts, and widgets C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Val::Rem variant
2 participants