tags:

views:

6059

answers:

8

Hi Everyone:

I am wondering if there is some way to change a css attribute for the last li in a list using CSS. I have looked into using :last-child, but this seems really buggy and I can't get it to work for me. I will use Javascript to do this if necessary, but I want to know if anyone can think up a solution in CSS.

Thanks for any help!

+5  A: 

:last-child is really the only way to do it without modifying the HTML - but assuming you can do that, the main option is just to give it a class="last-item", then do:

li.last-item { /* ... */ }

Obviously, you can automate this in the dynamic page generation language of your choice. Also, there is a lastChild JavaScript property in the W3C DOM.

Here's an example of doing what you want in Prototype:

$$("ul").each(function(x) { $(x.lastChild).addClassName("last-item"); });

Or even more simply:

$$("ul li:last-child").each(function(x) { x.addClassName("last-item"); });

In JQuery, you just replace the double $$ with a single $. So

$$("ul li:last-child")

Becomes:

$("ul li:last-child")

Also note that this should work without using the actual last-child CSS selector - rather, a JavaScript implementation of it - so it should be less buggy. I may, of course, be completely wrong.

Lucas Jones
Nice that you incorporated my answer into yours after I posted it.
Nissan Fan
Sorry - I was in the middle of posting the JQuery equivalent of the Prototype code I had already posted. If you would like, I can edit the JQuery part out.
Lucas Jones
No problem. I was actually saying that it validates at least part of how I've done this.
Nissan Fan
Sorry again for misunderstanding :). Technically, your code is 10x better - it actually works! (Typo will be fixed in 10..9..)
Lucas Jones
+1  A: 

You could use jQuery and do it as such:

$("li:last-child").addClass("someClass");

Nissan Fan
+4  A: 

I usually combine CSS and JavaScript approaches, so that it works without JavaScript in all browsers but IE6/7, and in IE6/7 with JavaScript on (but not off), since they does not support the :last-child pseudo-class.

$("li:last-child").addClass("last-child");

li:last-child,li.last-child{ /* ... */ }
cpharmston
Just a minor correction, :last-child doesn't work on IE7 as well.
vise
Oops, thanks! Updated accordingly for posterity.
cpharmston
A: 

If you know there are three li's in the list you're looking at, for example, you could do this:

li + li + li { /* Selects third to last li */
}

In IE6 you can use expressions:

li {
    color: expression(this.previousSibling ? 'red' : 'green'); /* 'green' if last child */
}

I would recommend using a specialized class or Javascript (not IE6 expressions), though, until the :last-child selector gets better support.

strager
+1  A: 

I usually do this by creating a htc file (ex. last-child.htc):

<attach event="ondocumentready" handler="initializeBehaviours" />
<script type="text/javascript">
function initializeBehaviours() {
  this.lastChild.className += ' last-child';
}
</script>

And call it from my IE conditional css file with:

ul { behavior: url("/javascripts/htc/last-child.htc"); }

Whereas in my main css file I got:

ul li:last-child,
ul li.last-child {
  /* some code */
}

Another solution (albeit slower) that uses your existent css markup without defining any .last-child class would be Dean Edwards ie7.js library.

vise
+1 for the IE7.js thing!
strager
A: 

One alternative for IE7+ and other browsers may be to use :first-child instead, and invert your styles.

For example, if you're setting the margin on each li:

ul li {
  margin-bottom: 1em;
}
ul li:last-child {
  margin-bottom: 0;
}

You could replace it with this:

ul li {
  margin-top: 1em;
}
ul li:first-child {
  margin-top: 0;
}

This will work well for some other cases like borders.

According to sitepoint, :first-child buggy, but only to the extent that it will select some root elements (the doctype or html), and may not change styles if other elements are inserted.

DisgruntledGoat
A: 

:last-child is CSS3 and has no IE support while :first-child is CSS2, I believe the following is the safe way to implement it using jquery

$('li').last().addClass('someClass');
Lawrence
A: 
jaeson