Don't let a deferred float inflate its block formatting context#2828
Merged
Conversation
When a float overflows the current page it is deferred to the next page, but it was left in the block formatting context's excluded shapes. As a result finish_block_formatting_context grew the fragment's height to contain that deferred float -- which has floated up beside the content that stays on the page -- so the fragment overflowed and the whole block was pushed to the next page instead of being split across the page break. Drop the deferred float from the excluded shapes when breaking before it, so the fragment keeps the height of the content that actually stays.
mvanherwijnen
force-pushed
the
float-defer-excluded-shapes
branch
from
July 7, 2026 13:55
41c8a7b to
64a34ed
Compare
Member
|
Hi! Thanks for the pull request. The problem is actually larger than what your patch fix. I’ll add a commit on top of yours to fix that! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's wrong
When a block that establishes a block formatting context (
display: flow-root,overflowother thanvisible, etc.) contains floats, a float that doesn't fit on the current page can push the entire block to the next pageThis is very visible in print documents full of figures that use
float+ wrapping text: blocks jump to a fresh page instead of partially filling the current one.Minimal example
a; page 2 = float +b..bfc(both paragraphs and the float) is pushed to page 2, wasting ~30px of page 1.Cause
float_layoutappends every laid-out float tocontext.excluded_shapes. When the float overflows and_out_of_flow_layoutbreaks before it (deferring it to the next page viaresume_at), the float is left inexcluded_shapes.finish_block_formatting_contextthen grows the BFC box's height tomax(shape bottoms)including the deferred float, which floated up beside the content that stays on the page. The fragment's height therefore exceeds the page, the caller rejects it, and the whole block is moved to the next page instead of keeping the part that fits.Fix
When breaking before an overflowing float, drop it from the current formatting context's excluded shapes so it no longer inflates the fragment that stays on the page:
Test
Adds
test_float_overflow_splits_formatting_contextintests/layout/test_float.py, reproducing the example above and asserting the block is split (paragraphastays on page 1). It fails before the change and passes after. The fulltests/layout/suite passes with the change.