1

I have the following code and cannot figure out why it doesn't work :

table {
    border: 1px solid black;
    }

table.whole > tr > td {
    padding: 20px 0 20px 0;
}
<!-- doesn't work via css rule -->
<table class="whole">
    <tr>
        <td>
            <table>
                <tr>
                    <td>abcd</td>
                </tr>
            </table>
        </td>
    </tr>
</table>
<hr>
<!-- works inline -->
<table>
    <tr>
        <td style="padding:20px 0 20px 0">
            <table>
                <tr>
                    <td>abcd</td>
                </tr>
            </table>
        </td>
    </tr>
</table>

May I misunderstand how the child selector > works or is there some kind of limitation here, or a bug ?...

St3an
  • 726
  • 1
  • 6
  • 21
  • 2
    you have the tbody element added by the browser `table.whole > tbody > tr > td` – Temani Afif Apr 30 '21 at 14:13
  • Yes I saw that, but I didn't suspect the rule to be applied _after_ ! Indeed by adding `> tbody` it works, Thx (I'll add `` in the html too) – St3an Apr 30 '21 at 14:14
  • 2
    try not to use the `>` selector. whenever there is a change is HTML, your styling breaks.. which should not be. Better is to add a css class to the td element. – Sudipto Roy Apr 30 '21 at 14:18
  • 1
    @SudiptoRoy ok, here it's a wrapper in a template for an internal email that will be read in Outlook clients... Otherwise I wouldn't even have used tables !! By bumping into the problem, I thought of using a class indeed, but also wanted to understand the problem I had... But yes, you're definitely right it's more risky! – St3an Apr 30 '21 at 14:26

2 Answers2

3

If you inspect your code in the Chrome devtools, you will see that the browser has automatically inserted the required <tbody> element between the <table /> and rows for you. Because of this, the <tr /> is no longer the direct descendent of the <table />. So the issue is that your HTML is malformed/not adhering to the spec. If you add the <tbody /> element and rewrite your CSS accordingly, it will work just fine:

table {
    border: 1px solid black;
}

table.whole > tbody > tr > td {
    padding: 20px 0 20px 0;
}
<!-- doesn't work via css rule -->
<table class="whole">
  <tbody>
    <tr>
        <td>
            <table>
                <tr>
                    <td>abcd</td>
                </tr>
            </table>
        </td>
    </tr>
  </tbody>
</table>
Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
0

In HTML, there must be a <tbody> element between <table> and <tr> elements. Chrome is being nice, so it helpfully inserts it for you. However, that breaks your CSS, because now <tbody> is the child of <table>, and not <tr>.

Solution:

Include a <tbody> (otherwise it would be invalid and confusing), and change your CSS code to:

table.whole > tbody > tr > td {
    padding: 20px 0 20px 0;
}

table {
    border: 1px solid black;
}
table.whole > tbody /* ...and put it here. */ > tr > td {
    padding: 20px 0 20px 0;
}
<table class="whole">
    <tbody> <!-- include a <tbody> element... -->
        <tr>
            <td>
                <table>
                    <tbody>
                        <tr>
                            <td>abcd</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>

Note: the inline styles work because they don't have any random selector errors because they're placed right in the <tbody> element.

illogicalapple
  • 732
  • 3
  • 16
  • https://stackoverflow.com/questions/3078099/is-it-necessary-to-have-tbody-in-every-table states that it is not mandatory in all cases... But I'll use it in the future if needed, or avoid `>` selector in this case. – St3an Apr 30 '21 at 14:39
  • Yes, but Chrome puts it in for you, and you *should* use it, because otherwise you might get unexpected errors. And if you don't use the `>` selector, it might select the nested table. – illogicalapple Apr 30 '21 at 14:43
  • yes, I mean _use a class instead_, not only _not use it_ ... – St3an Apr 30 '21 at 14:56