bevyengine / bevyengine/bevy

Add support to `bevy_ui` for units relative to font sizes

Open
#21,207 1 comment 0 reactions 0 assignees View on GitHub
A-Text A-UI C-Feature I-Accessibility
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

## What problem does this solve or what need does it fill?

Add support for units relative to the font size:

https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Values_and_units

These units are especially important for accessibility, as they let text and layouts scale with user font settings, improving readability for people with low vision.

## What solution would you like?

New `Val` variants:
* `Em(f32)`: based on the node's font size.
* `Rem(f32)`: based on the font size of the node's root ancestor, or the font size from the default text style.

Fonts would also need to support `Rem` and `Em` font sizes. In this case an `Em` font size for a node would be based on the font size of its parent.

Root nodes given a `Rem` value would have a font size based on the default text style, but the descendants `Rem` values would be based on the root size. So if the font size of the default text style is `20` and a root node has a font size of `Val::Rem(2.)` (resolving to `2 * 20 = 40` pixels), `Rem` font sizes for the root's descendants would be based on a size of `40` pixels.

`Val::Em` is both less useful (mostly), and more difficult to implement. In particular it might complicate any `Val::Calc` implementation (#5893). So I think we'd want to add just `Val::Rem` initially, and then leave `Val::Em` until after `Val::Calc` is in.

### Problems

Unlike the web, `bevy_ui` supports multiple roots:

@virida
> 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.

So should `Rem` units be based only on the font size of the default text style?

I think for most purposes you probably just want `Rem` to be based on a single global size value, and it would be rare to want to override it for different roots. But the name `Rem` stongly suggests that it's root specific. And there might be a need for the extra flexibility, I'm not certain.

Possibly we could have third variant based on a global value, called `Gem` (or something).

---

Contributor guide

Open the contributing guide

Research direction

Start in bevy_ui with the Val variants and font-size handling, then read the discussion around Val::Calc (#5893) and the multiple-root problem. Decide whether Rem is based on the default text style or each UI root, and define how descendant font sizes resolve. Done means the chosen Rem behavior works for layout values and font sizes with coverage for roots and descendants.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.