[csswg-drafts] [selectors-4] Grid-structural selectors like :nth-col(): having pseudo-classes for rows e.g. :nth-row() is needed for CSS to cope with tables and rowSpan (#8352)

DavidJCobb has just created a new issue for https://github.com/w3c/csswg-drafts:

== [selectors-4] Grid-structural selectors like :nth-col(): having pseudo-classes for rows e.g. :nth-row() is needed for CSS to cope with tables and rowSpan ==
The current Selectors 4 draft introduces the `:nth-col()` and `:nth-last-col()` selectors, as a way to select grid elements (including table cells) that exist within a given column. However, no similar pseudo-classes exist for rows. The draft justifies this on the grounds that tables and similar grid structures are typically row-major; however, that doesn't account for things like the `rowSpan` attribute on table cells.

Consider the following table:

```html
<table>
   <tbody>
      <tr>
         <td rowSpan="2"> A </td>
         <td> B </td>
      </tr>
      <tr>
         <td> C </td>
      </tr>
   </tbody>
</table>
<!--
   layout:
   A B
   A C
-->
```

In this scenario, there is no way to tell that the "A" cell extends to the bottom of the table. Tables are row-major, but we can only tell what row "A" *starts* in; there's no way to tell what row it *ends* in. This causes a few problems:

* Setting a `border-radius` on a table will round off the table's corners, but not the corners of its corner cells; the cells remain rectangular and are drawn overtop the table's rounded corners. To give a table proper rounded corners, we must set `border-top-left-radius` and friends on the top-left, top-right, bottom-left, and bottom-right cells. However, we can't reliably identify the bottom-left cell in the above table using selectors alone.
* Setting `border-collapse` on a table will prevent you from using `border-radius`, and may additionally prevent other effects that rely on separated borders to work. In order to work around this, you have to leave the borders separated, and then emulate `border-collapse` by selectively setting some border widths to zero in order to manually collapse those borders. However, if a cell is rowspanned from a non-bottom row down into the bottom row, you can't reliably detect this, and so you can't collapse its bottom border into the table's bottom border.

Typically, we would detect when a cell is on any edge of the table using the following selectors:

```css
/* Top edge: */
table > :is(thead,tbody,tfoot):first-child > tr:first-child > :is(td,th) {}

/* Bottom edge: */
table > :is(thead,tbody,tfoot):last-child > tr:last-child > :is(td,th) {}

/* Left edge: */
table > :is(thead,tbody,tfoot) > tr > :is(td,th):first-child {}

/* Right edge: */
table > :is(thead,tbody,tfoot) > tr > :is(td,th):last-child {}
```

The selectors above fail for rowspanned cells, and for cells adjacent to them (i.e. "B" in our example above would wrongly test as a leftmost-column cell).

With the column pseudo-classes introduced in Selectors 4, I believe the syntax would now be:

```css
/* Top edge: */
table > :is(thead,tbody,tfoot):first-child > tr:first-child > :is(td,th) {}

/* Bottom edge: */
table > :is(thead,tbody,tfoot):last-child > tr:last-child > :is(td,th) {}

/* Left edge: */
table   :is(td, th):nth-col(0) {}

/* Right edge: */
table   :is(td, th):nth-last-col(0) {}
```

This fixes the "B" case; however, the rowspanned "A" cell in our example table above still won't test as being on the bottom edge. We would need `:nth-row()` and `:nth-last-row()` counterparts in order to cope with `rowSpan`.

I offer a more detailed breakdown of use cases, including links to examples, in [the issue I originally opened in the WHATWG HTML repo by mistake](https://github.com/whatwg/html/issues/8772). Those examples were written before I was aware of the yet-to-be-implemented `:nth-col()` and `:nth-last-col()` selectors, but I believe they still adequately demonstrate the utility of row-based selectors.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/8352 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Monday, 23 January 2023 21:12:31 UTC