Skip to content

Commit 7639bfb

Browse files
committed
Use the same code for all layouts to manage out-of-flow children
And add failing tests for absolute children of flex and grid containers.
1 parent d004a3a commit 7639bfb

File tree

3 files changed

+71
-4
lines changed

3 files changed

+71
-4
lines changed

tests/layout/test_position.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Tests for position property."""
22

3+
import pytest
4+
35
from ..testing_utils import assert_no_logs, render_pages
46

57

@@ -489,3 +491,52 @@ def test_grid_relative_positioning():
489491
div1, div2 = article.children
490492

491493
assert (div2.position_x, div2.position_y) == (30, 10)
494+
495+
496+
@assert_no_logs
497+
@pytest.mark.xfail
498+
def test_flex_absolute_positioning():
499+
"""TODO: Order is not kept when out-of-flow and in-flow children are mixed."""
500+
page, = render_pages('''
501+
<style>
502+
@page { size: 100px 100px }
503+
article { display: flex; position: relative }
504+
.box { width: 20px; height: 20px }
505+
.absolute { position: absolute; top: 10px; left: 10px }
506+
</style>
507+
<article>
508+
<div class="box"></div>
509+
<div class="box absolute"></div>
510+
</article>
511+
''')
512+
html, = page.children
513+
body, = html.children
514+
article, = body.children
515+
# That’s currently div2, div1
516+
div1, div2 = article.children
517+
518+
assert (div2.position_x, div2.position_y) == (10, 10)
519+
520+
521+
@assert_no_logs
522+
@pytest.mark.xfail
523+
def test_grid_absolute_positioning():
524+
"""TODO: Absolutely positioned grid items are not replaced by placeholders ."""
525+
page, = render_pages('''
526+
<style>
527+
@page { size: 100px 100px }
528+
article { display: grid; grid-template-columns: 20px 20px; position: relative }
529+
.box { width: 20px; height: 20px }
530+
.absolute { position: absolute; top: 10px; left: 10px }
531+
</style>
532+
<article>
533+
<div class="box"></div>
534+
<div class="box absolute"></div>
535+
</article>
536+
''')
537+
html, = page.children
538+
body, = html.children
539+
article, = body.children
540+
div1, div2 = article.children
541+
542+
assert (div1.position_x, div1.position_y) == (10, 10)

weasyprint/layout/flex.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,6 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block, page_i
923923
resume_index, = resume_at
924924
first_level_skip += resume_index
925925
resume_at = {first_level_skip + index: child_resume_at}
926-
block.relative_positioning(new_child, (box.width, box.height))
927926
if resume_at:
928927
break
929928

@@ -938,6 +937,9 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block, page_i
938937
absolute_layout(
939938
context, absolute_box, box, fixed_boxes, bottom_space, skip_stack=None)
940939

940+
for child in box.children:
941+
block.relative_positioning(child, (box.width, box.height))
942+
941943
# TODO: Use real algorithm, see https://www.w3.org/TR/css-flexbox-1/#flex-baselines.
942944
if isinstance(box, boxes.InlineFlexBox):
943945
if main == 'width': # and main text direction is horizontal

weasyprint/layout/grid.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,14 @@ def _resolve_tracks_sizes(sizing_functions, box_size, children_positions,
575575
def grid_layout(context, box, bottom_space, skip_stack, containing_block,
576576
page_is_empty, absolute_boxes, fixed_boxes):
577577
context.create_block_formatting_context(box)
578-
from . import block
579578

580579
if skip_stack and box.style['box_decoration_break'] != 'clone':
581580
box.remove_decoration(start=True, end=False)
582581

582+
if box.style['position'] == 'relative':
583+
# New containing block, use a new absolute list
584+
absolute_boxes = []
585+
583586
# Define explicit grid
584587
grid_areas = box.style['grid_template_areas']
585588
flow = box.style['grid_auto_flow']
@@ -1360,8 +1363,6 @@ def _add_page_children(max_row=inf):
13601363
if baseline is None and y == implicit_y1:
13611364
baseline = find_in_flow_baseline(new_child)
13621365

1363-
block.relative_positioning(new_child, (box.width, box.height))
1364-
13651366
# Abort whole grid rendering if no child fits.
13661367
if this_page_children and not new_children:
13671368
context.finish_block_formatting_context(box)
@@ -1375,6 +1376,19 @@ def _add_page_children(max_row=inf):
13751376
LOGGER.warning('Inline grids are not supported')
13761377
box.baseline = baseline or 0
13771378

1379+
from .absolute import absolute_layout
1380+
from .block import relative_positioning
1381+
1382+
if box.style['position'] == 'relative':
1383+
# New containing block, resolve the layout of the absolute descendants
1384+
for absolute_box in absolute_boxes:
1385+
absolute_layout(
1386+
context, absolute_box, box, fixed_boxes, bottom_space,
1387+
skip_stack=None)
1388+
1389+
for child in box.children:
1390+
relative_positioning(child, (box.width, box.height))
1391+
13781392
# Resume early when there’s no resume_at.
13791393
if not resume_at:
13801394
context.finish_block_formatting_context(box)

0 commit comments

Comments
 (0)