71

I have the following HTML:

<ul>
  <li>A
    <ul>
      <li>subsection</li>
    </ul>
  </li>
  <li>B
    <ul>
      <li>subsection</li>
    </ul>
  </li>
  <li>C
    <ul>
      <li>subsection</li>
    </ul>
  </li>
</ul>

With jQuery, how do I target the FIRST level of <li>s?

For example, I need to make the font bold on hover to the <li>s with the letters A, B and C, but NOT have that font style applied to the nested <li>s (with the name subsections).

Here's an initial jsfiddle DEMO if you'd like to use it.

Thanks.

EDIT--

Solution:

CHILD SELECTORS, that's the answer.

No need for jQuery, this can be done using CSS.

Here's the updated DEMO

EDIT-- Here's a more clear demo

Thanks,

Ricardo Zea
  • 10,053
  • 13
  • 76
  • 79
  • 1
    possible duplicate of [Selecting only first-level elements in jquery](http://stackoverflow.com/questions/977883/selecting-only-first-level-elements-in-jquery) – Felix Kling Jan 28 '11 at 16:35

7 Answers7

128

Have a container <div> with a class, and use the > selector. Lets say your container div's class is "myclass":

.myclass ul li {
   ...this will affect both levels of li.
}

.myclass > ul > li {
   ...this will only affect the first level.
}

.myclass > ul > li > ul > li {
   ...this will only affect the second level.
}

Note: the > selector does not work in IE6 and below when used as a CSS selector. It does work in all other browsers though, including IE7 and IE8, and when used in JQuery, it works in all browsers supported by jQuery, including IE6.

rick schott
  • 21,012
  • 5
  • 52
  • 81
Spudley
  • 166,037
  • 39
  • 233
  • 307
  • 1
    Or without adding that container, use `body`: `$('body > ul > li').css('border', '1px solid red');` – ncuesta Jan 28 '11 at 16:37
  • 1
    Yes, this is the solution, and the same solution I came up with on my own. I selected this solution as the right answer because it doesn't need to use JavaScript to accomplish that, but I hadn't figured out it could be done with CSS only before posting the question. Thanks! – Ricardo Zea Jan 28 '11 at 16:57
  • 3
    Be aware that some CSS attributes may `inherit` so if you set the `.myclass > ul > li {font-size: 2em;}` then all your `li`s may still be affected unless you `.myclass li {font-size: 1em;}` as your default – Chris Beck Sep 09 '15 at 16:51
20

You could do this:

$('ul > li:not(:has(ul))');

But it would be better to give your top level <ul> an ID so you can target it with a valid CSS selector:

$('#topUL > li')
user113716
  • 318,772
  • 63
  • 451
  • 440
  • 1
    Your solution would only work if only one ´ul´ was used in the page and not if you would have several ´ul´s. Yet, your solution works nevertheless for this specific example. Thanks. – Ricardo Zea Jan 28 '11 at 16:52
  • @Ricardo: Do you mean because of the ID? Yes you're right, you'd need to use a class instead to target the first level `
  • ` elements across several top level `
      ` elements at the same time. Or use the [`multiple-selector`](http://api.jquery.com/multiple-selector/) with the different IDs.
  • – user113716 Jan 28 '11 at 16:54
  • As of Mar 2023, `:has()` is now [valid and mostly available CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:has#specifications), but your first solution selects `
  • `s of any level which do not contain `
      `s.
  • – EvgenKo423 Mar 16 '23 at 12:50