4

I am trying to find a way to change the css for a class, only if it's inside a table with 4 td's. The code will probably explain better what is my problem.

HTML

<table class="myclass">
<tr>
  <td>1 <span class="myclass2">xxx</span></td>
  <td>2 <span class="myclass2">xxx</span></td>
  <td>3 <span class="myclass2">xxx</span></td>
</tr>
</table>

<table class="myclass">
<tr>
  <td>1 <span class="myclass2">xxx</span></td>
  <td>2 <span class="myclass2">xxx</span></td>
  <td>3 <span class="myclass2">xxx</span></td>
  <td>4 <span class="myclass2">xxx</span></td>
</tr>
</table>

CSS

.myclass td:first-child:nth-last-child(3),td:first-child:nth-last-child(3) ~ td {
        background-color:white !important;
    }
.myclass td:first-child:nth-last-child(4),td:first-child:nth-last-child(4) ~ td {
        background-color:red !important;
    }
.myclass2 {
  color:blue;
}

a JSFiddle is ready: JSFIDDLE HERE

What I am trying to do is changing the style of "myclass2" only for the elements included in the table with 4 TDs, not with the table with 3 TDs. Is that possible at all?

dippas
  • 58,591
  • 15
  • 114
  • 126
MeV
  • 3,761
  • 11
  • 45
  • 78
  • I don't believe this is possible since the only way to ascertain there are four cells in the `` is with the fourth, or last, `
    `; and there is (as yet) no way to select the previous siblings of that fourth ``. This is, to the best of my knowledge, a problem that will require JavaScript in some way.
    – David Thomas Jun 02 '16 at 13:55
  • @Vohuman this is wrong. see here: http://stackoverflow.com/questions/8720931/can-css-detect-the-number-of-children-an-element-has . Also my example prove that it's somehow possible. – MeV Jun 02 '16 at 13:56
  • @DavidThomas thanks. I am developing an HTML Email so I won't be able to use js :-) – MeV Jun 02 '16 at 13:57
  • Hi MeV, so if the table has 4 TDs it should have class myclass2 whereas the others should not have this class? – Mudassir Jun 02 '16 at 13:58
  • @IPAddress correct. But I would like to make this only via CSS, not via HTML, as the HTML will be dynamic – MeV Jun 02 '16 at 14:00
  • @MeV: interesting find! So surely `td:nth-last-child(4), td:nth-last-child(4) ~ td {/* css */}` should style the `` elements according to your needs? Although there is a risk that a `` with five, or more, `
    ` element siblings will cause problems with those styles: [demo](https://jsfiddle.net/davidThomas/o4on86zs/).
    – David Thomas Jun 02 '16 at 14:02
  • @DavidThomas yes, you are right, with more than 5 elements it could be a problem. See below for the right answer :-) – MeV Jun 02 '16 at 14:07
  • I didn't say _that_ styling is not possible. I meant that based on the way CSS rules are evaluated there is no (yet) standard CSS rule that is applied to descendants of a parent element according to children _count_ of the parent element. – Ram Jun 02 '16 at 14:23
  • @Vohuman then I am not sure how can the solution posted below work..? – MeV Jun 02 '16 at 14:43
  • The answer, which is indeed a smart one, uses the indices. It's not _count_ based. My comment was somehow confusing and I'll remove it. – Ram Jun 02 '16 at 14:56
  • 1
    If you're developing an HTML email, be aware that many email clients strip out or ignore – dogwoodtree-dot-net Jun 03 '16 at 14:46
  • @dogwoodtree-dot-net Thank you! I have actually discovered that css nth() is not supported in outlook so I had to abandon the solution :-( – MeV Jun 03 '16 at 15:00
  • Apologies, I missed the reference to e-mails in the question title before or I would have made mention of the poor support for more advanced CSS in my answer. Will update when I'm back in front of a computer so I can include references. – Shaggy Jun 04 '16 at 19:29

1 Answers1

6

It's possible, yes, but you would need to use multiple selectors, checking the that first cell was also the 4th last cell, the 2nd also the 3rd last, and so on:

.myclass2{
    background:#000;
    color:#fff;
}
td:first-child:nth-last-child(4)>.myclass2,
td:nth-child(2):nth-last-child(3)>.myclass2,
td:nth-child(3):nth-last-child(2)>.myclass2,
td:nth-child(4):last-child>.myclass2{
    background:#f00;
}
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
    </tr>
</table>
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
        <td>4 <span class="myclass2">xxx</span></td>
    </tr>
</table>

Or, alternatively, just select the first child that is also the fourth last child and any cells that follow it:

.myclass2{
    background:#000;
    color:#fff;
}
td:first-child:nth-last-child(4)>.myclass2,
td:first-child:nth-last-child(4)~td>.myclass2{
    background:#f00;
}
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
    </tr>
</table>
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
        <td>4 <span class="myclass2">xxx</span></td>
    </tr>
</table>

Another way to do it, if you wanted to target rows with any number of cells greater than 3 would be to use the negation pseudo-class to select the first cell that isn't the last, 2nd last or 3rd last cell and all cells that follow it:

.myclass2{
    background:#000;
    color:#fff;
}
td:first-child:not(:nth-last-child(-n+3))>.myclass2,
td:first-child:not(:nth-last-child(-n+3))~td>.myclass2{
    background:#f00;
}
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
    </tr>
</table>
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
        <td>4 <span class="myclass2">xxx</span></td>
    </tr>
</table>
<table class="myclass">
    <tr>
        <td>1 <span class="myclass2">xxx</span></td>
        <td>2 <span class="myclass2">xxx</span></td>
        <td>3 <span class="myclass2">xxx</span></td>
        <td>4 <span class="myclass2">xxx</span></td>
        <td>5 <span class="myclass2">xxx</span></td>
        <td>6 <span class="myclass2">xxx</span></td>
    </tr>
</table>

NOTE: These may not be optimal solutions for you, given the poor support some e-mail clients have for CSS.

Shaggy
  • 6,696
  • 2
  • 25
  • 45
  • This is great! Thanks! – MeV Jun 02 '16 at 14:06
  • 1
    You're welcome :) I've updated my answer with a 3rd solution that might be of use to you. – Shaggy Jun 03 '16 at 13:29
  • Thank you! amazing – MeV Jun 03 '16 at 16:30
  • 2
    this wont work across all email clients due to the lack of [support](https://www.campaignmonitor.com/css/) when doing html emails, it is advised to use inline css over "regular css" on `head` among other [stuff](https://www.campaignmonitor.com/dev-resources/will-it-work/guidelines/) – dippas Jun 04 '16 at 19:43
  • Thanks for providing that, @dippas; see my comment on the question made a few minutes ago. – Shaggy Jun 04 '16 at 19:45
  • Inline styles are less important now Gmail supports styles in the head. But nth-chd was probably conceived after Outlook 2003 so email support will be limited – Eoin May 30 '18 at 11:07