CSS - Apply style to last element being not of a certain type

Viewed 188

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>.

5 Answers

.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.

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 :)

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>

you may try:

span:last-of-type {
  color:red;
}
Related