diff --git a/weasy/css/computed_values.py b/weasy/css/computed_values.py
index 67698086..7c8cdb79 100644
--- a/weasy/css/computed_values.py
+++ b/weasy/css/computed_values.py
@@ -549,6 +549,12 @@ def text_align(computer, name, value):
@Computer.register('vertical_align')
def vertical_align(computer, name, value):
"""Compute the ``word-spacing`` property."""
+ # Use +/- half an em for super and sub, same as Pango.
+ # (See the SUPERSUB_RISE constant in pango-markup.c)
+ if value == 'super':
+ return computer.get_computed('font_size') * 0.5
+ if value == 'sub':
+ return computer.get_computed('font_size') * -0.5
if getattr(value, 'type', 'other') == 'PERCENTAGE':
return computer.get_computed('line_height') * value.value / 100.
return length(computer, name, value)
diff --git a/weasy/css/validation.py b/weasy/css/validation.py
index fa71e4ef..11db2665 100644
--- a/weasy/css/validation.py
+++ b/weasy/css/validation.py
@@ -449,9 +449,10 @@ def vertical_align(value):
if is_dimension_or_percentage(value, negative=True):
return value
keyword = get_keyword(value)
- if keyword in ('sub', 'sup', 'text-top', 'text-bottom', 'top', 'bottom'):
+ if keyword in ('top', 'bottom'):
raise InvalidValues('value not supported yet')
- if keyword in ('baseline', 'middle'):
+ if keyword in ('baseline', 'middle', 'sub', 'super',
+ 'text-top', 'text-bottom'):
return keyword
diff --git a/weasy/layout/inlines.py b/weasy/layout/inlines.py
index a5ce5f16..6bc95d36 100644
--- a/weasy/layout/inlines.py
+++ b/weasy/layout/inlines.py
@@ -489,6 +489,16 @@ def inline_box_verticality(box, baseline_y):
one_ex = box.style.font_size * 0.5
top = baseline_y - (one_ex + child.margin_height()) / 2.
child_baseline_y = top + child.baseline
+ elif vertical_align == 'text-top':
+ # align top with the top of the parent’s content area
+ top = (baseline_y - box.baseline + box.margin_top +
+ box.border_top_width + box.padding_top)
+ child_baseline_y = top + child.baseline
+ elif vertical_align == 'text-bottom':
+ # align bottom with the bottom of the parent’s content area
+ bottom = (baseline_y - box.baseline + box.margin_top +
+ box.border_top_width + box.padding_top + box.height)
+ child_baseline_y = bottom - child.margin_height() + child.baseline
else:
# Numeric value: The child’s baseline is `vertical_align` above
# (lower y) the parent’s baseline.
diff --git a/weasy/tests/test_layout.py b/weasy/tests/test_layout.py
index 349c4afc..fe669d99 100644
--- a/weasy/tests/test_layout.py
+++ b/weasy/tests/test_layout.py
@@ -888,6 +888,47 @@ def test_vertical_align():
assert line.height == 77
assert body.height == line.height
+ # sup and sub currently mean +/- 0.5 em
+ # With the initial 16px font-size, that’s 8px.
+ page, = parse('''
+
+
+
+
+
+ ''')
+ html = page.root_box
+ body, = html.children
+ line, = body.children
+ span, = line.children
+ img_1, img_2, img_3 = span.children
+ assert img_1.height == 60
+ assert img_2.height == 40
+ assert img_3.height == 40
+ assert img_1.position_y == 0
+ assert img_2.position_y == 12 # 20 - 16 * 0.5
+ assert img_3.position_y == 28 # 20 + 16 * 0.5
+ assert line.height == 68
+ assert body.height == line.height
+
+ # Pango gives a height of 19px for font-size of 16px
+ page, = parse('''
+
+
+
+
+ ''')
+ html = page.root_box
+ body, = html.children
+ line, = body.children
+ span, = line.children
+ img_1, img_2 = span.children
+ assert img_1.height == 4
+ assert img_2.height == 4
+ assert img_1.position_y == 0
+ assert img_2.position_y == 15 # 19 - 4
+ assert line.height == 19
+ assert body.height == line.height
@SUITE.test