2

I got stuck when designing a dynamic page of news today when I added a heading tag at the beginning of my section and the first-child of a p tag inside a div stopped working. This is what I was trying to do and it was working until I add the heading tag.

.pubs .newsdate {
    border-top:1px solid rgb(255,179,0);
}
.pubs:first-child .newsdate {
    border:none;
}
<section class="content">
    <h2>News</h2> //issue
    <div class="pubs">
        <p class="newsdate">stuff</p>
    </div>
    <div class="pubs">
        <p class="newsdate">stuff</p>
    </div>
    <div class="pubs">
        <p class="newsdate">stuff</p>
    </div>
</section>

The first border was being removed properly until I added the heading (h2) tag. Then, the pseudo selector stopped working. What could have happened?

TylerH
  • 20,799
  • 66
  • 75
  • 101

2 Answers2

5

.pubs:first-child looks for a class of pubs that is also the first child of its parent element (in this case, parent element is class content. Once you add an h2 element before the first pubs class, then pubs is no longer the first child, but the second.

Try .pubs:first-of-type instead:

.pubs:first-of-type .newsdate {
    border: none;
}

The :first-of-type pseudo-selector will look for the first type of whichever class or ID or element you prepend it with. By this, I mean that it doesn't matter if an element (div), a class (.pub), or an ID (#pub) comes before the pseudo-selector (each one is valid). Although it wouldn't make much sense to use an ID, since those are supposed to be unique.

Also notice I said first type, not first instance (two people have already commented (one deleted their comment) confusedly about what I'm saying). For instance, if you have class .pubs on three div elements and two p elements, your :first-of-type pseudo-selector would apply to the first .pubs div element AND the first .pubs p element.

So first-of-type pseudo-selector can apply to multiple elements, depending on how you use it.

If you think about it, this is a better solution than when you first had it working, because this solution looks specifically for the very first instance of the .pubs class, whereas your example only works circumstantially (when there isn't anything before .pubs).

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • Thanks a lot for your explanation. I REALLY didn't now that I was looking for the first-child of the PARENT element. I always thought as the first occurrence of that element. This completely changes my view of this pseudo-selector. I wonder how many people still think the same way I used to. Thanks again! – Leonardo Ferreira Apr 29 '14 at 18:11
  • 2
    @LeonardoFerreira Check out this [cool game](http://flukeout.github.io/) for testing your knowledge on pseudo-selectors. It's short, fun, and invaluable! – TylerH Apr 29 '14 at 18:15
  • 1
    "The :first-of-type pseudo-selector will look for the first type of whichever class or ID or element you prepend it with." No, it looks for the first of its *type*, i.e. in this case div. It has nothing to do with class or ID - that it works is a coincidence because every `.pubs` is a div. See http://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class/8539107#8539107 – BoltClock Apr 30 '14 at 04:12
  • @BoltClock That is what I meant (I even said "type" in my answer); you can type `.pubs` or `#pubs` or `div` before the pseudo-selector, all would be valid for `
    `. I will edit my answer to make it clearer.
    – TylerH Apr 30 '14 at 13:16
3

You can use :first-of-type to avoid this.

Example Here

.pubs:first-of-type .newsdate {
    border:none;
}
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304