Skip to content

Commit 4a682db

Browse files
authored
Merge pull request #2618 from different55/relative-flexgrid
Calculate relative offsets for grid and flex children.
2 parents c57a44e + 7639bfb commit 4a682db

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

tests/layout/test_position.py

Lines changed: 95 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

@@ -445,3 +447,96 @@ def test_fixed_positioning_regression_2():
445447
assert (article.position_x, article.position_y) == (15, 20)
446448
header, = article.children
447449
assert (header.position_x, header.position_y) == (5, 10)
450+
451+
452+
@assert_no_logs
453+
def test_flex_relative_positioning():
454+
page, = render_pages('''
455+
<style>
456+
@page { size: 100px 100px }
457+
article { display: flex }
458+
.box { width: 20px; height: 20px }
459+
.relative { position: relative; top: 10px; left: 10px }
460+
</style>
461+
<article>
462+
<div class="box"></div>
463+
<div class="box relative"></div>
464+
</article>
465+
''')
466+
html, = page.children
467+
body, = html.children
468+
article, = body.children
469+
div1, div2 = article.children
470+
471+
assert (div2.position_x, div2.position_y) == (30, 10)
472+
473+
474+
@assert_no_logs
475+
def test_grid_relative_positioning():
476+
page, = render_pages('''
477+
<style>
478+
@page { size: 100px 100px }
479+
article { display: grid; grid-template-columns: 20px 20px }
480+
.box { width: 20px; height: 20px }
481+
.relative { position: relative; top: 10px; left: 10px }
482+
</style>
483+
<article>
484+
<div class="box"></div>
485+
<div class="box relative"></div>
486+
</article>
487+
''')
488+
html, = page.children
489+
body, = html.children
490+
article, = body.children
491+
div1, div2 = article.children
492+
493+
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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,9 @@ def flex_layout(context, box, bottom_space, skip_stack, containing_block, page_i
937937
absolute_layout(
938938
context, absolute_box, box, fixed_boxes, bottom_space, skip_stack=None)
939939

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

weasyprint/layout/grid.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ def grid_layout(context, box, bottom_space, skip_stack, containing_block,
579579
if skip_stack and box.style['box_decoration_break'] != 'clone':
580580
box.remove_decoration(start=True, end=False)
581581

582+
if box.style['position'] == 'relative':
583+
# New containing block, use a new absolute list
584+
absolute_boxes = []
585+
582586
# Define explicit grid
583587
grid_areas = box.style['grid_template_areas']
584588
flow = box.style['grid_auto_flow']
@@ -1372,6 +1376,19 @@ def _add_page_children(max_row=inf):
13721376
LOGGER.warning('Inline grids are not supported')
13731377
box.baseline = baseline or 0
13741378

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+
13751392
# Resume early when there’s no resume_at.
13761393
if not resume_at:
13771394
context.finish_block_formatting_context(box)

0 commit comments

Comments
 (0)