1

I have a table that I want to select the very first TH only if it contains a caption. I thought it might be something like this:

.myTable caption + tr th:first-child
{
    /* stuff */
}

It's instead selecting nothing. Is this a bug in CSS or just my logic?

See my JSFiddle: https://jsfiddle.net/ukb13pdp/1/

.objectTable th:first-child
{
    background-color: blue;
    color: white;
}

.objectTable caption + tr th:first-child
{
    background-color: red;
}
<table class='objectTable'>
    <caption>Caption Table</caption>
    <tr>
        <th>A</th>
        <th>B</th>
    </tr>
    <tr>
        <td>1</td>
        <td>2</td>
    </tr>
</table>
<br/><br/>
<span>No Caption Table</span>
<table class='objectTable'>
    <tr>
        <th>C</th>
        <th>D</th>
    </tr>
    <tr>
        <td>3</td>
        <td>4</td>
    </tr>
</table>
James Donnelly
  • 126,410
  • 34
  • 208
  • 218
KannedFarU
  • 305
  • 3
  • 9

2 Answers2

4

The cause here is exactly the same as the one described in this related question about the use of child selectors with tr. The problem is that tr elements are made children of an implicit tbody element, so what ends up being the sibling of the caption is that tbody and not the tr:

.myTable caption + tbody th:first-child

As an aside, if your th elements reside in a header row they should ideally be contained in a thead element and the data rows contained in explicit tbody element(s):

<table class=myTable>
  <caption>Table with header group</caption>
  <thead>
    <tr><th>Header<th>Header
  <tbody>
    <tr><td>Row 1<td>Row 1
    <tr><td>Row 2<td>Row 2
</table>

And selected using

.myTable caption + thead th:first-child
Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
1

You're forgetting about the <tbody> element which wraps the <tr> element. Even though not specified in your (otherwise invalid) HTML, the <tbody> element is automatically implemented by the browser as a way of validating this, so instead of:

<caption>
<tr>

You end up with:

<caption>
<tbody>
    <tr>

As seen in this element inspector capture below:

Element Inspector View

To select the very first <tr> element after a <caption> element, you can instead use:

caption + tbody tr:first-child {
    ...
}

JSFiddle demo.

James Donnelly
  • 126,410
  • 34
  • 208
  • 218