at (8,8) content-size 221.359375x77.875 children: not-inline
+ TableRowBox at (8,8) content-size 221.359375x19.46875 children: not-inline
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox at (9,9) content-size 70.046875x17.46875 [BFC] children: inline
+ line 0 width: 70.046875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 8, rect: [9,9 70.046875x17.46875]
+ "Header 1"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (81.046875,9) content-size 72.515625x17.46875 [BFC] children: inline
+ line 0 width: 72.515625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 8, rect: [81.046875,9 72.515625x17.46875]
+ "Header 2"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (155.5625,9) content-size 72.796875x17.46875 [BFC] children: inline
+ line 0 width: 72.796875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 8, rect: [155.5625,9 72.796875x17.46875]
+ "Header 3"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableRowBox |
at (8,27.46875) content-size 221.359375x19.46875 children: not-inline
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox at (9,38.203125) content-size 70.046875x17.46875 [BFC] children: inline
+ line 0 width: 49.609375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 5, rect: [9,38.203125 49.609375x17.46875]
+ "Row 1"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (81.046875,28.46875) content-size 72.515625x17.46875 [BFC] children: inline
+ line 0 width: 41.84375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [81.046875,28.46875 41.84375x17.46875]
+ "Cell 1"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (155.5625,28.46875) content-size 72.796875x17.46875 [BFC] children: inline
+ line 0 width: 44.3125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [155.5625,28.46875 44.3125x17.46875]
+ "Cell 2"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableRowBox |
at (8,46.9375) content-size 221.359375x19.46875 children: not-inline
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox at (81.046875,47.9375) content-size 72.515625x17.46875 [BFC] children: inline
+ line 0 width: 44.59375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [81.046875,47.9375 44.59375x17.46875]
+ "Cell 3"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (155.5625,47.9375) content-size 72.796875x17.46875 [BFC] children: inline
+ line 0 width: 43.25, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [155.5625,47.9375 43.25x17.46875]
+ "Cell 4"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableRowBox |
at (8,66.40625) content-size 221.359375x19.46875 children: not-inline
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox at (9,67.40625) content-size 70.046875x17.46875 [BFC] children: inline
+ line 0 width: 52.078125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 5, rect: [9,67.40625 52.078125x17.46875]
+ "Row 2"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (81.046875,67.40625) content-size 72.515625x17.46875 [BFC] children: inline
+ line 0 width: 43.953125, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [81.046875,67.40625 43.953125x17.46875]
+ "Cell 5"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ TableCellBox | at (155.5625,67.40625) content-size 72.796875x17.46875 [BFC] children: inline
+ line 0 width: 44.234375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
+ frag 0 from TextNode start: 0, length: 6, rect: [155.5625,67.40625 44.234375x17.46875]
+ "Cell 6"
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,8) content-size 0x0 children: inline
+ TextNode <#text>
+ BlockContainer <(anonymous)> at (8,85.875) content-size 784x0 children: inline
+ TextNode <#text>
diff --git a/Tests/LibWeb/Layout/input/table/rowspan.html b/Tests/LibWeb/Layout/input/table/rowspan.html
new file mode 100644
index 0000000000..d738088bef
--- /dev/null
+++ b/Tests/LibWeb/Layout/input/table/rowspan.html
@@ -0,0 +1,32 @@
+
+
+
+
+ Table with rowspan
+
+
+
+
+
+ Header 1 |
+ Header 2 |
+ Header 3 |
+
+
+ Row 1 |
+ Cell 1 |
+ Cell 2 |
+
+
+ Cell 3 |
+ Cell 4 |
+
+
+ Row 2 |
+ Cell 5 |
+ Cell 6 |
+
+
+
+
+
\ No newline at end of file
diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp
index 0757f30ace..f48e51461c 100644
--- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp
@@ -457,7 +457,11 @@ void TableFormattingContext::compute_table_height(LayoutMode layout_mode)
cell.baseline = box_baseline(m_state, cell.box);
- row.base_height = max(row.base_height, cell_state.border_box_height());
+ // Only cells spanning the current row exclusively are part of computing minimum height of a row,
+ // as described in https://www.w3.org/TR/css-tables-3/#computing-the-table-height
+ if (cell.row_span == 1) {
+ row.base_height = max(row.base_height, cell_state.border_box_height());
+ }
row.baseline = max(row.baseline, cell.baseline);
}
@@ -645,7 +649,7 @@ void TableFormattingContext::position_cell_boxes()
auto& cell_state = m_state.get_mutable(cell.box);
auto& row_state = m_state.get(m_rows[cell.row_index].box);
CSSPixels const cell_border_box_height = cell_state.content_height() + cell_state.border_box_top() + cell_state.border_box_bottom();
- CSSPixels const row_content_height = row_state.content_height();
+ CSSPixels const row_content_height = compute_row_content_height(cell);
auto const& vertical_align = cell.box->computed_values().vertical_align();
if (vertical_align.has()) {
switch (vertical_align.get()) {
@@ -671,6 +675,33 @@ void TableFormattingContext::position_cell_boxes()
}
}
+CSSPixels TableFormattingContext::compute_row_content_height(Cell const& cell) const
+{
+ auto& row_state = m_state.get(m_rows[cell.row_index].box);
+ if (cell.row_span == 1) {
+ return row_state.content_height();
+ }
+ // The height of a cell is the sum of all spanned rows, as described in
+ // https://www.w3.org/TR/css-tables-3/#bounding-box-assignment
+
+ // When the row span is greater than 1, the borders of inner rows within the span have to be
+ // included in the content height of the spanning cell. First top and final bottom borders are
+ // excluded to be consistent with the handling of row span 1 case above, which uses the content
+ // height (no top and bottom borders) of the row.
+ CSSPixels span_height = 0;
+ for (size_t i = 0; i < cell.row_span; ++i) {
+ auto const& row_state = m_state.get(m_rows[cell.row_index + i].box);
+ if (i == 0) {
+ span_height += row_state.content_height() + row_state.border_box_bottom();
+ } else if (i == cell.row_span - 1) {
+ span_height += row_state.border_box_top() + row_state.content_height();
+ } else {
+ span_height += row_state.border_box_height();
+ }
+ }
+ return span_height;
+}
+
void TableFormattingContext::run(Box const& box, LayoutMode layout_mode, AvailableSpace const& available_space)
{
m_available_space = available_space;
diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h
index f8ade2a8e2..0b85bb34ea 100644
--- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.h
@@ -78,6 +78,8 @@ private:
CSSPixels max_width { 0 };
};
+ CSSPixels compute_row_content_height(Cell const& cell) const;
+
Vector m_cells;
Vector m_columns;
Vector m_rows;
| |