Why does .class:last-of-type not work?

Problem

Why does this not work? http://jsfiddle.net/84C5W/1/

<style>
   p{
     display : none;
   }
   p.visible:last-of-type {
     display : block;
   }​
</style>
<div>
  <p class="visible">This should be hidden</p>
  <p class="visible">This should be displayed</p>
  <p class="">This should be hidden</p>
</div>

In fact, none of my <p>'s are visible. If I remove the reference to ".visible" in the stylesheet, this does show the last <p> in the div, but this is not what I want.

Of course I could only keep one ".visible" at all times, but this is for a reveal.js presentation and I do not have control over the javascript. Only the stylesheet...

Edit: Ok, so obviously .class:last-of-type does not work. As put by @Justus Romijn, the :last-of-type pseudo class was designed for selecting elements only (which in my opinion is enormously limiting, and places this particular pseudo class in a more or less useless state).

Anyway, I want to rephrase my question at this point: How can I select the last element inside the div WITH the class ".visible"? I do NOT want to use Javascript for this.

Problem courtesy of: Øystein Amundsen

Solution

I did some testing, but the last-of-type selector only works on node-selectors, not classnames.

HTML:

<p class="visible">First paragraph.</p>
<p class="visible">Second paragraph.</p>
<p>Third paragraph.</p>

CSS:

p:last-of-type{
  /* this will be applied in the third paragraph bacause the pseudo-selector is applied  to nodes only */
  font-weight: bold;
}
p.visible:last-of-type {
  /* this does not get applied, because you are using the pseudo-selector with a class. */
  display: block;
}

From the W3C:

The :last-of-type pseudo-class represents an element that is the last sibling of its type in the list of children of its parent element.

Because it has to be a sibling, it ignores classnames probably because then you can mix it up with other elements.

Why is there no followed by or parent selector? This could potentially memory-lock a lot of webpages by changing just one classname dynamically on the page. Making extensive use of CSS3 selectors is already heavy on the browser and not recommended.

Dave Hyatt, while working on the WebKit implementation in 2008, mentioned some reasons why these implementations are avoided:

With parent selectors it becomes extremely easy to accidentally cause a document-wide grovel. People can and will misuse this selector. Supporting it is giving people a whole lot of rope to hang themselves with.

The sad truth about CSS3 selectors is that they really shouldn’t be used at all if you care about page performance. Decorating your markup with classes and ids and matching purely on those while avoiding all uses of sibling, descendant and child selectors will actually make a page perform significantly better in all browsers.

Solution courtesy of: Justus Romijn

Discussion

For future reference, this will be covered in CSS level 4: https://www.w3.org/TR/selectors4/#the-nth-last-match-pseudo

Browser support at the moment of writing, is non-existant: http://css4-selectors.com/selector/css4/structural-pseudo-class/

When this is ready, this should be the solution:

p {
  display : none;
}
p.visible:nth-last-match(0) {
  display : block;
}
<div>
  <p class="visible">This should be hidden</p>
  <p class="visible">This should be displayed</p>
  <p class="">This should be hidden</p>
</div>

Discussion courtesy of: Øystein Amundsen

in my case, i made a mistake.

p.visible : last-of-type (x)
p.visible:last-of-type   (o)

just what i i did

Discussion courtesy of: fitjimong

Target the second last tag.

.visible:nth-last-of-type(2);
Discussion courtesy of: Thisismint

The problem is that :last-of-type only matches element selector. In your example, you try to match a class selector. That's why it's not working.

An example: http://dabblet.com/gist/4144885

Discussion courtesy of: Simon Boudrias

This recipe can be found in it's original form on Stack Over Flow.