Skip to content

Don't let hanging whitespace end the line early, and fix hanging-whitespace content widths - #802

Closed
nicoburns wants to merge 1 commit into
linebender:mainfrom
DioxusLabs:devin/1788901716-hang-ws-on-785
Closed

nicoburns wants to merge 1 commit into
linebender:mainfrom
DioxusLabs:devin/1788901716-hang-ws-on-785

Conversation

@nicoburns

Copy link
Copy Markdown
Collaborator

LLM Contributions: Generated with Fable 5.1 Low.

A few hanging whitespace fixups. Followups for #785 needed to mitigate Blitz WPT test regressions.

…espace content widths

Line breaking: when hanging whitespace overflows the line width, keep
scanning instead of immediately starting a new line. Hanging whitespace
does not end a line on its own: a following forced break (e.g. a newline)
terminates the line normally, and following non-whitespace content that
doesn't fit breaks at the opportunity marked after the hanging
whitespace. Previously every overflowing whitespace atom appended to the
line and then immediately broke, producing spurious empty lines (e.g.
"X<space>\n<space><space>" in a 1ch-wide box produced 4 lines instead
of 2).

calculate_content_widths: a max-content line never wraps, so nothing can
hang off it — stop subtracting the running hanging whitespace from
max-width candidates. Also only accumulate hanging whitespace when
wrapping is enabled (text_wrap_mode == Wrap): under a nowrap mode such
as white-space:pre, trailing preserved whitespace is part of the line's
width and must not hang (CSS Text 4 § 4.3.2), matching the updated
line-break hanging advance computation.
@nicoburns
nicoburns requested a review from tomcur September 9, 2026 16:41

@tomcur tomcur left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is targeting the same as #790, but differs in that this does not implement the spec's conditional hanging of whitespace when it is followed by a newline or the end of the layout (see CSS Text 4 § 4.3.2 Step 4). This leaves the line breaker hanging whitespace unconditionally.

That then means this is internally inconsistent, as the max-content width can be greater than the layout's calculated width when it's broken to that width (the trailing whitespace should not hang in that case).

We also decided in #790 to wait until WhiteSpaceCollapse is available as a style in the layout, as these rules should only be applied in case of WhiteSpaceCollapse::Preserve.

Comment thread parley/src/layout/data.rs
running_max_width += advance;

if !can_hang {
if !can_hang || text_wrap_mode != TextWrapMode::Wrap {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The branches below check the same thing, so this is technically superfluous. If this condition stays, perhaps the other branches should be updated to remove their checks.

(The cluster branch actually checks this per character of the cluster, which may matter if the wrap mode changes inside the cluster, though I don't know if that matches browsers.)

@nicoburns

Copy link
Copy Markdown
Collaborator Author

Superceded by #790

@nicoburns nicoburns closed this Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants