:last-child Y U NO WORK!

The :last-child in my code only works when I remove the inline js or wrap it within a div. Why is this? Shouldn’t it work regardless of the inline js? I mean clearly I’m targeting the p element and not the script element.


<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>><html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width">
        <script src="js/vendor/modernizr-2.6.2.min.js"></script>
        <link rel="stylesheet" href="css/mastersheet.css">
    </head>
    <body>
       
        
    <p>one</p>
    <p>one</p>
    <p>one</p>
    <p>p tag! Y U NO RED!!!!!</p>
 

        

    <!-- le google analytics -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
    <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.js"><\\/script>')</script>
    <!-- le javascript -->

    <script>
            var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
            (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
            g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
            s.parentNode.insertBefore(g,s)}(document,'script'));
    </script>
    </body>
</html>



* {
  margin: 0;
  padding: 0;
}
body p:last-child {
  color: red;
}

That is the expected behavior the :last-child pseudo selector, regard of what element you have picked in your CSS the context of which it has been picked in will always refer to the <script> tag since its the last child within the <body>, wrapping the <p> elements within a parent <div> element changes the context of the selector which inherently tells the browser to find any child element within its given context that is the last one in the node list.

Personally I found this to be quite confusing at first but after reading the spec for it over at W3C it made more sense as to why it works the way it does.

I read the specification on this psuedo element but I still don’t understand why it is this way.

To put it in other words, none of those <p> elements is the last-child of the body element, so the rule does not apply to any of them. What you really want is a selector like :last-p, but it doesn’t exist, of course. :slight_smile:

As said, you’d have to wrap the <p>s in another element, and then the last <p> would actually be a last-child.

You could use something like

body p:last-of-type {
  color: red;
}

but I don’t know how well that’s supported yet.

Ahhh I get it now, that makes more sense. I think the selector itself can easily through anyone off at first. In regards to “last-of-type”, that was a work around that I tried, but it is only supported in updated browsers. Thanks @ralph.m and @chrisupjohn.