Skip to content

Commit c9af451

Browse files
committed
Border collapse problem with rowspan/colspan cells
https://bugs.webkit.org/show_bug.cgi?id=5515 rdar://94163960 Reviewed by Alan Baradlay. Currently for a table of 2 columns and 4 rows. * the first column has a rowspan = 3 (so 2 cells with one covering the first 3 rows) * the second column has 4 cells on 4 rows When specifiying a different bottom border color for each first 3 rows, WebKit is adopting the color of the first cell defined in the second colum for the bottom color of the rowspanned cell instead of the color of the third row like Gecko and Blink do. This patch is fixing and only this. It doesn't fix the more general issue for vertical border shared in between the rowspanned cell and the second column cells. This will need to be fixed in https://webkit.org/b/20260 as it requires a larger architectural change on border segmenting. This didn't have WPT tests before, this is adding one covering this behavior. Tests: imported/w3c/web-platform-tests/css/css-tables/rowspan-cell-border-after-color-ref.html imported/w3c/web-platform-tests/css/css-tables/rowspan-cell-border-after-color.html * LayoutTests/imported/w3c/web-platform-tests/css/css-tables/rowspan-cell-border-after-color-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-tables/rowspan-cell-border-after-color-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-tables/rowspan-cell-border-after-color.html: Added. * Source/WebCore/rendering/RenderTableCell.cpp: (WebCore::RenderTableCell::computeCollapsedAfterBorder const): Canonical link: https://commits.webkit.org/306471@main
1 parent 39ba510 commit c9af451

File tree

4 files changed

+147
-5
lines changed

4 files changed

+147
-5
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!doctype html>
2+
<html>
3+
<link rel="author" title="Karl Dubost" href="https://otsukare.info/">
4+
<style>
5+
table {
6+
border-collapse: collapse;
7+
}
8+
9+
td {
10+
width: 100px;
11+
height: 50px;
12+
border: 1px solid black;
13+
}
14+
15+
/* Row borders */
16+
#ref tr:nth-child(1) {
17+
border-bottom: 5px solid blue;
18+
}
19+
20+
#ref tr:nth-child(2) {
21+
border-bottom: 5px solid green;
22+
}
23+
24+
#ref tr:nth-child(3) {
25+
border-bottom: 5px solid red;
26+
}
27+
28+
/* The rowspan cell should have red bottom border */
29+
#ref .rowspan-cell {
30+
border-bottom: 5px solid red;
31+
}
32+
</style>
33+
<p>The cell with rowspan=3 should have a red bottom border (from row 3), not blue (from row 1).</p>
34+
<table id="ref">
35+
<tr>
36+
<td class="rowspan-cell" rowspan="3">Rowspan 3</td>
37+
<td>Cell B</td>
38+
</tr>
39+
<tr>
40+
<td>Cell C</td>
41+
</tr>
42+
<tr>
43+
<td>Cell D</td>
44+
</tr>
45+
</table>
46+
</html>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!doctype html>
2+
<html>
3+
<link rel="author" title="Karl Dubost" href="https://otsukare.info/">
4+
<style>
5+
table {
6+
border-collapse: collapse;
7+
}
8+
9+
td {
10+
width: 100px;
11+
height: 50px;
12+
border: 1px solid black;
13+
}
14+
15+
/* Row borders */
16+
#ref tr:nth-child(1) {
17+
border-bottom: 5px solid blue;
18+
}
19+
20+
#ref tr:nth-child(2) {
21+
border-bottom: 5px solid green;
22+
}
23+
24+
#ref tr:nth-child(3) {
25+
border-bottom: 5px solid red;
26+
}
27+
28+
/* The rowspan cell should have red bottom border */
29+
#ref .rowspan-cell {
30+
border-bottom: 5px solid red;
31+
}
32+
</style>
33+
<p>The cell with rowspan=3 should have a red bottom border (from row 3), not blue (from row 1).</p>
34+
<table id="ref">
35+
<tr>
36+
<td class="rowspan-cell" rowspan="3">Rowspan 3</td>
37+
<td>Cell B</td>
38+
</tr>
39+
<tr>
40+
<td>Cell C</td>
41+
</tr>
42+
<tr>
43+
<td>Cell D</td>
44+
</tr>
45+
</table>
46+
</html>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!doctype html>
2+
<html>
3+
<link rel="author" title="Karl Dubost" href="https://otsukare.info/">
4+
<link rel="help" href="https://www.w3.org/TR/CSS2/tables.html#border-conflict-resolution">
5+
<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=5515">
6+
<link rel="match" href="rowspan-cell-border-after-color-ref.html">
7+
<meta name="assert" content="A cell with rowspan should use the last row's border for its after (bottom) border, not the first row's border">
8+
<style>
9+
table {
10+
border-collapse: collapse;
11+
}
12+
13+
td {
14+
width: 100px;
15+
height: 50px;
16+
border: 1px solid black;
17+
}
18+
19+
/* Different border colors for each row */
20+
#test tr:nth-child(1) {
21+
border-bottom: 5px solid blue;
22+
}
23+
24+
#test tr:nth-child(2) {
25+
border-bottom: 5px solid green;
26+
}
27+
28+
#test tr:nth-child(3) {
29+
border-bottom: 5px solid red;
30+
}
31+
</style>
32+
<p>The cell with rowspan=3 should have a red bottom border (from row 3), not blue (from row 1).</p>
33+
<table id="test">
34+
<tr>
35+
<td rowspan="3">Rowspan 3</td>
36+
<td>Cell B</td>
37+
</tr>
38+
<tr>
39+
<td>Cell C</td>
40+
</tr>
41+
<tr>
42+
<td>Cell D</td>
43+
</tr>
44+
</table>
45+
</html>

Source/WebCore/rendering/RenderTableCell.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* (C) 1998 Waldo Bastian ([email protected])
55
* (C) 1999 Lars Knoll ([email protected])
66
* (C) 1999 Antti Koivisto ([email protected])
7-
* Copyright (C) 2003-2025 Apple Inc. All rights reserved.
7+
* Copyright (C) 2003-2026 Apple Inc. All rights reserved.
88
* Copyright (C) 2016-2017 Google Inc. All rights reserved.
99
* Copyright (C) 2025 Samuel Weinig <[email protected]>
1010
*
@@ -1115,10 +1115,15 @@ CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderC
11151115
return result;
11161116
}
11171117

1118-
// (3) Our row's after border. (FIXME: Deal with rowspan!)
1119-
result = chooseBorder(result, CollapsedBorderValue(parent()->style().borderAfter(), includeColor ? resolvedBorderColor(parent()->style(), afterColorProperty) : Color(), BorderPrecedence::Row, parent()->style().usedZoomForLength()));
1120-
if (!result.exists())
1121-
return result;
1118+
// (3) Our row's after border. Account for rowspan by using the last row in the span.
1119+
// For a cell spanning multiple rows, the after border should match with the border
1120+
// of the last row in the span, not the first row.
1121+
size_t lastRowIndex = rowIndex() + rowSpan() - 1;
1122+
if (CheckedPtr lastRowInSpan = section()->rowRendererAt(lastRowIndex)) {
1123+
result = chooseBorder(result, CollapsedBorderValue(lastRowInSpan->style().borderAfter(), includeColor ? resolvedBorderColor(lastRowInSpan->style(), afterColorProperty) : Color(), BorderPrecedence::Row, lastRowInSpan->style().usedZoomForLength()));
1124+
if (!result.exists())
1125+
return result;
1126+
}
11221127

11231128
// (4) The next row's before border.
11241129
if (nextCell) {

0 commit comments

Comments
 (0)