3

Question

I want to apply a style to the last child of an element that is NOT of a certain type.

Please do not confuse with: the last element IF it is not of a certain type.

Example

<div class="container>
  <div>Child 1</div>
  <div>Child 2</div>
  <span>Child 3</span>
  <template></template>
  <span>Child 4</span>
  <template></template>
</div>

In this case I want to apply the style to the last element that is not of type <template> (would be Child 4 in this case).

Please be aware that :nth-last-child(2) is not applicable, because there could be potentially more <template> elements.

What I tried (and did not work)

.container > :not(template):last-child {
  // Style here
}

.container > :last-child:not(template) {
  // Style here
}

Thank you already!

EDIT - It seems my question was to abstract, so I will be more concrete.

I want to have a generic spacing class (Applying this to a container will simply add a space between the items):

.vertical-spacing>* {
  margin: 20px 0;
}

.vertical-spacing> :first-child {
  margin-top: 0;
}

.vertical-spacing> :last-child {
  margin-bottom: 0;
}


/* For better visibility of example */

.vertical-spacing {
  background: #ff0000
}

.vertical-spacing>* {
  background: #00ff00;
}
<div class="vertical-spacing">
  <div>Child 1</div>
  <div>Child 2</div>
  <div>Child 3</div>
</div>

I am doing a project in Polymer 3.0 where you can use a conditional template that will be visible only under certain conditions:

<template is="dom-if" if="condition">
  <div>Content</div>
</template>

If the <template> is the last child in the spacing container (or multiple templates are the last children, number is not fixed) and the condition is false, the result is that the content of the <template> is hidden, nevertheless the <template> element itself is still present. By consequence there is a useless space at the end of the container:

.vertical-spacing>* {
  margin: 20px 0;
}

.vertical-spacing> :first-child {
  margin-top: 0;
}

.vertical-spacing> :last-child {
  margin-bottom: 0;
}


/* For better visibility of example */

.vertical-spacing {
  background: #ff0000
}

.vertical-spacing>div {
  background: #00ff00;
}
<div class="vertical-spacing">
  <div>Child 1</div>
  <div>Child 2</div>
  <div>Child 3</div>
  <temlate>
    <div style="display: none">Content</div>
  </temlate>
</div>
<div style="background: #0000ff; color: white">Stuff after container: there is a margin on top as you can see</div>

I now want to be able to apply the style that removes the margin to the last element in the container that is not a <template>.

Community
  • 1
  • 1
JDC
  • 4,247
  • 5
  • 31
  • 74

5 Answers5

1

.vertical-spacing>* {
  margin: 20px 0;
}

.vertical-spacing> :first-child {
  margin-top: 0;
}

.vertical-spacing> :last-child {
  margin-bottom: 0;
}


/* For better visibility of example */

.vertical-spacing {
  background: #ff0000
}

.vertical-spacing>* {
  background: #00ff00;
}


.vertical-spacing > *:last-of-type {
  margin-bottom:0;

}
span{
display:inline-block;
}
<div class="vertical-spacing">
  <div>Child 1</div>
  <div>Child 2</div>
  <div>Child 3</div>
  <p>'p' tag child </p>
  <span>'span' tag child </span>
  <div>Child 3</div>
  <span>'span' tag child </span>
  <template>
    <div style="display: none">Content</div>
  </template>
</div>
<div style="background: #0000ff; color: white">Stuff after container: there is a margin on top as you can see</div>

Simply write

.vertical-spacing > *:last-of-type { margin-bottom:0;}

I think this will solve your margin issue.

  • Nearly! This will not work if you do have different children, e.g. an additional `` instead of only `
    `s. Then there will be no space between those children.
    – JDC Jun 06 '19 at 13:02
  • @JDC - This will work for all the elements. span is not working because it is an inline element. Give display:inline-block to span and see the margin. Please see the snippet. I have added different elements – Mileesh M S Jun 06 '19 at 13:18
  • @JDC - I understood the issue. Let me try again. – Mileesh M S Jun 06 '19 at 13:29
0

Check out this article that neatly explains the difference between :nth-child and :nth-of-type which is probably the reason :last-of-type will work but :last-child will not.

:nth-of-type looks at any and all child elements of a parent but :nth-child works a bit differently and doesn't always work if you have different types of child elements like you do here.

Hope this helps :)

RobC
  • 22,977
  • 20
  • 73
  • 80
Aljoha
  • 3
  • 3
  • If you want to exclude the template tag/tags I would just put it outside the div that the other elements are in, and put that div and those templates in one big div – Aljoha Jun 06 '19 at 09:12
0

You can use the CSS pseudo-class :last-of-type :

https://developer.mozilla.org/en-US/docs/Web/CSS/:last-of-type

jsfiddle: https://jsfiddle.net/y21qL8jz/

0xGorri
  • 101
  • 3
0

here is an example what you are asking I guess, to see the result I put a div in the end, please remove the div and you will see that its not affecting the span, You can put your template in place of span in CSS, Remove and add div to see the results

.container > *:last-child:not(span) {
  font-size: 48px;
  color:red;
}
<div class="container">
  <div>Child 1</div>
  <div>Child 2</div>
  <span>Child 3</span>
  <div>Child 2</div>
  <span>Child 4</span>
  <br>
  <span>dwdw</span>
  <div>atul</div>
</div>
Atul Rajput
  • 4,073
  • 2
  • 12
  • 24
  • That's what code is doing dear, if its last item is span, in JDC's code it will be template, then it will not affect the item at all, otherwise it will, that's what question is asking – Atul Rajput Jun 06 '19 at 09:34
  • I think there is a misunderstanding. If I exclude `span`, I want the last child that is not a span to be formatted. In my case I exclude `template`, so I want the last child that is not a `template` to be formatted. – JDC Jun 06 '19 at 09:47
  • Ohh, My bad then. I misunderstood. let me figure it out if something can be done in this case – Atul Rajput Jun 06 '19 at 09:58
-1

you may try:

span:last-of-type {
  color:red;
}
Alvaro Menéndez
  • 8,766
  • 3
  • 37
  • 57
  • Bu what if I want it to be applied to all elements **EXCEPT** ` – JDC Jun 06 '19 at 09:05
  • I believe you will have to target them individually e.g. ```span:last-of-type```, ```div:last-of-type```, etc. Unfortunately, **CSS** is not that smart yet to be able to figure things out. – Manu Jun 06 '19 at 09:11