diff --git a/tests/layout/test_float.py b/tests/layout/test_float.py
index a47edb7ac5..1609d3881b 100644
--- a/tests/layout/test_float.py
+++ b/tests/layout/test_float.py
@@ -840,3 +840,46 @@ def test_first_letter_float():
assert first_letter.position_x == 0
# TODO: fix problem described in #1859.
# assert text.position_x == 20
+
+
+@assert_no_logs
+def test_float_break_after_page():
+ # https://github.com/Kozea/WeasyPrint/issues/2277
+ # break-after: page on a floated element should force a page break.
+ pages = render_pages('''
+
+
float
+ end
+ ''')
+ assert len(pages) == 2
+ html1, = pages[0].children
+ body1, = html1.children
+ float_div, = body1.children
+ assert float_div.position_y == 10
+ html2, = pages[1].children
+ body2, = html2.children
+ end_div, = body2.children
+ assert end_div.position_y == 10
+
+
+@assert_no_logs
+def test_float_break_before_page():
+ # break-before: page on a floated element should force a page break.
+ pages = render_pages('''
+
+ start
+ float
+ ''')
+ assert len(pages) == 2
+ html1, = pages[0].children
+ body1, = html1.children
+ start_div, = body1.children
+ assert start_div.position_y == 10
+ html2, = pages[1].children
+ body2, = html2.children
+ float_div, = body2.children
+ assert float_div.position_y == 10
diff --git a/weasyprint/layout/block.py b/weasyprint/layout/block.py
index 701ddbcb91..457b0c7658 100644
--- a/weasyprint/layout/block.py
+++ b/weasyprint/layout/block.py
@@ -237,7 +237,7 @@ def relative_positioning(box, containing_block):
def _out_of_flow_layout(context, box, index, child, new_children,
page_is_empty, absolute_boxes, fixed_boxes,
- adjoining_margins, bottom_space):
+ adjoining_margins, bottom_space, next_page):
stop = False # whether we should stop parent rendering after this layout
resume_at = None # where to resume in-flow rendering
new_child = None # child rendered by this layout
@@ -260,10 +260,36 @@ def _out_of_flow_layout(context, box, index, child, new_children,
# Float child layout.
elif child.is_floated():
+ # Check for forced break-before on the float.
+ # https://drafts.csswg.org/css-break/#break-between
+ last_in_flow_child = find_last_in_flow_child(new_children)
+ if last_in_flow_child is not None:
+ page_break = block_level_page_break(last_in_flow_child, child)
+ if force_page_break(page_break, context):
+ page_name = child.page_values()[0]
+ next_page = {'break': page_break, 'page': page_name}
+ resume_at = {index: None}
+ stop = True
+ return (
+ stop, resume_at, new_child, out_of_flow_resume_at,
+ next_page)
+
new_child, out_of_flow_resume_at = float_layout(
context, child, box, absolute_boxes, fixed_boxes, bottom_space,
skip_stack=None)
+ # Check for forced break-after on the float.
+ page_break = child.style['break_after']
+ if force_page_break(page_break, context):
+ new_child.index = index
+ new_children.append(new_child)
+ page_name = child.page_values()[1]
+ next_page = {'break': page_break, 'page': page_name}
+ resume_at = {index + 1: None}
+ stop = True
+ return (
+ stop, resume_at, new_child, out_of_flow_resume_at, next_page)
+
# Check that child doesn’t overflow page.
page_overflow = context.overflows_page(
bottom_space, new_child.position_y + new_child.height)
@@ -298,7 +324,7 @@ def _out_of_flow_layout(context, box, index, child, new_children,
page = context.current_page
context.running_elements[running_name][page].append(child)
- return stop, resume_at, new_child, out_of_flow_resume_at
+ return stop, resume_at, new_child, out_of_flow_resume_at, next_page
def _break_line(context, box, line, new_children, needed, page_is_empty, index,
@@ -734,10 +760,11 @@ def block_container_layout(context, box, bottom_space, skip_stack, page_is_empty
if not child.is_in_normal_flow():
# Layout out-of-flow child.
abort = False
- stop, resume_at, new_child, out_of_flow_resume_at = (
+ stop, resume_at, new_child, out_of_flow_resume_at, next_page = (
_out_of_flow_layout(
context, box, index, child, new_children, page_is_empty,
- absolute_boxes, fixed_boxes, adjoining_margins, bottom_space))
+ absolute_boxes, fixed_boxes, adjoining_margins,
+ bottom_space, next_page))
if out_of_flow_resume_at:
context.add_broken_out_of_flow(
new_child, child, box, out_of_flow_resume_at)