diff --git a/weasyprint/layout/flex.py b/weasyprint/layout/flex.py
index 3d610a50f..7a6579321 100644
--- a/weasyprint/layout/flex.py
+++ b/weasyprint/layout/flex.py
@@ -593,7 +593,6 @@ def flex_layout(context, box, max_position_y, skip_stack, containing_block,
# else: Cross size has been set by step 7
# Step 12
- # TODO: handle rtl
original_position_axis = (
box.content_box_x() if axis == 'width'
else box.content_box_y())
@@ -650,33 +649,62 @@ def flex_layout(context, box, max_position_y, skip_stack, containing_block,
child.margin_bottom = free_space
free_space = 0
- if justify_content == 'flex-end':
- position_axis += free_space
- elif justify_content == 'center':
- position_axis += free_space / 2
- elif justify_content == 'space-around':
- position_axis += free_space / len(line) / 2
- elif justify_content == 'space-evenly':
- position_axis += free_space / (len(line) + 1)
+ if (box.style['direction'] == 'rtl' and
+ box.style['flex_direction'].startswith('row')):
+ if justify_content == 'flex-end':
+ position_axis -= free_space
+ elif justify_content == 'center':
+ position_axis -= free_space / 2
+ elif justify_content == 'space-around':
+ position_axis -= free_space / len(line) / 2
+ elif justify_content == 'space-evenly':
+ position_axis -= free_space / (len(line) - 1)
- for i, child in line:
- if axis == 'width':
- child.position_x = position_axis
- if justify_content == 'stretch':
- child.width += free_space / len(line)
- else:
- child.position_y = position_axis
- position_axis += (
- child.margin_width() if axis == 'width'
- else child.margin_height())
- if justify_content == 'space-around':
- position_axis += free_space / len(line)
- elif justify_content == 'space-between':
- if len(line) > 1:
- position_axis += free_space / (len(line) - 1)
+ for i, child in line:
+ if axis == 'width':
+ child.position_x = position_axis
+ if justify_content == 'stretch':
+ child.width -= free_space / len(line)
+ else:
+ child.position_y = position_axis
+ position_axis -= (
+ child.margin_width() if axis == 'width'
+ else child.margin_height())
+ if justify_content == 'space-around':
+ position_axis -= free_space / len(line)
+ elif justify_content == 'space-between':
+ if len(line) > 1:
+ position_axis -= free_space / (len(line) + 1)
+ elif justify_content == 'space-evenly':
+ position_axis -= free_space / (len(line) - 1)
+ else:
+ if justify_content == 'flex-end':
+ position_axis += free_space
+ elif justify_content == 'center':
+ position_axis += free_space / 2
+ elif justify_content == 'space-around':
+ position_axis += free_space / len(line) / 2
elif justify_content == 'space-evenly':
position_axis += free_space / (len(line) + 1)
+ for i, child in line:
+ if axis == 'width':
+ child.position_x = position_axis
+ if justify_content == 'stretch':
+ child.width += free_space / len(line)
+ else:
+ child.position_y = position_axis
+ position_axis += (
+ child.margin_width() if axis == 'width'
+ else child.margin_height())
+ if justify_content == 'space-around':
+ position_axis += free_space / len(line)
+ elif justify_content == 'space-between':
+ if len(line) > 1:
+ position_axis += free_space / (len(line) - 1)
+ elif justify_content == 'space-evenly':
+ position_axis += free_space / (len(line) + 1)
+
# Step 13
position_cross = (
box.content_box_y() if cross == 'height'
diff --git a/weasyprint/tests/test_layout/test_flex.py b/weasyprint/tests/test_layout/test_flex.py
index e0c3be1cd..18e75bc5b 100644
--- a/weasyprint/tests/test_layout/test_flex.py
+++ b/weasyprint/tests/test_layout/test_flex.py
@@ -37,6 +37,33 @@ def test_flex_direction_row():
assert div_1.position_x < div_2.position_x < div_3.position_x
+@assert_no_logs
+def test_flex_direction_row_rtl():
+ page, = render_pages('''
+
+ A
+ B
+ C
+
+ ''')
+ html, = page.children
+ body, = html.children
+ article, = body.children
+ div_1, div_2, div_3 = article.children
+ assert div_1.children[0].children[0].text == 'A'
+ assert div_2.children[0].children[0].text == 'B'
+ assert div_3.children[0].children[0].text == 'C'
+ assert (
+ div_1.position_y ==
+ div_2.position_y ==
+ div_3.position_y ==
+ article.position_y)
+ assert (
+ div_1.position_x + div_1.width ==
+ article.position_x + article.width)
+ assert div_1.position_x > div_2.position_x > div_3.position_x
+
+
@assert_no_logs
def test_flex_direction_row_reverse():
page, = render_pages('''
@@ -64,6 +91,32 @@ def test_flex_direction_row_reverse():
assert div_1.position_x < div_2.position_x < div_3.position_x
+@assert_no_logs
+def test_flex_direction_row_reverse_rtl():
+ page, = render_pages('''
+
+ A
+ B
+ C
+
+ ''')
+ html, = page.children
+ body, = html.children
+ article, = body.children
+ div_1, div_2, div_3 = article.children
+ assert div_1.children[0].children[0].text == 'C'
+ assert div_2.children[0].children[0].text == 'B'
+ assert div_3.children[0].children[0].text == 'A'
+ assert (
+ div_1.position_y ==
+ div_2.position_y ==
+ div_3.position_y ==
+ article.position_y)
+ assert div_3.position_x == article.position_x
+ assert div_1.position_x > div_2.position_x > div_3.position_x
+
+
@assert_no_logs
def test_flex_direction_column():
page, = render_pages('''
@@ -89,6 +142,32 @@ def test_flex_direction_column():
assert div_1.position_y < div_2.position_y < div_3.position_y
+@assert_no_logs
+def test_flex_direction_column_rtl():
+ page, = render_pages('''
+
+ A
+ B
+ C
+
+ ''')
+ html, = page.children
+ body, = html.children
+ article, = body.children
+ div_1, div_2, div_3 = article.children
+ assert div_1.children[0].children[0].text == 'A'
+ assert div_2.children[0].children[0].text == 'B'
+ assert div_3.children[0].children[0].text == 'C'
+ assert (
+ div_1.position_x ==
+ div_2.position_x ==
+ div_3.position_x ==
+ article.position_x)
+ assert div_1.position_y == article.position_y
+ assert div_1.position_y < div_2.position_y < div_3.position_y
+
+
@assert_no_logs
def test_flex_direction_column_reverse():
page, = render_pages('''
@@ -116,6 +195,34 @@ def test_flex_direction_column_reverse():
assert div_1.position_y < div_2.position_y < div_3.position_y
+@assert_no_logs
+def test_flex_direction_column_reverse_rtl():
+ page, = render_pages('''
+
+ A
+ B
+ C
+
+ ''')
+ html, = page.children
+ body, = html.children
+ article, = body.children
+ div_1, div_2, div_3 = article.children
+ assert div_1.children[0].children[0].text == 'C'
+ assert div_2.children[0].children[0].text == 'B'
+ assert div_3.children[0].children[0].text == 'A'
+ assert (
+ div_1.position_x ==
+ div_2.position_x ==
+ div_3.position_x ==
+ article.position_x)
+ assert (
+ div_3.position_y + div_3.height ==
+ article.position_y + article.height)
+ assert div_1.position_y < div_2.position_y < div_3.position_y
+
+
@assert_no_logs
def test_flex_row_wrap():
page, = render_pages('''