Ryenski
Ryenski

Reputation: 9692

CSS: Select all first generation elements (children), but not grandchildren

Given this unordered list:

<ul>
  <li>Level One Item One
    <ul>
      <li>Level One Item One</li>
      <li>Level One Item Two</li>
    </ul>
  </li>
  <li>Level One Item Two
    <ul>
      <li>Level Two Item One</li>
      <li>Level Two Item Two</li>
    </ul>
  </li>
</ul>

... I would like to apply a style to all immediate <li> children of an <ul>, without having that style applied to nested list items.

I thought this CSS selector would do the trick, but it has no effect:

ul>li:not(li>ul>li) {
  border: 1px solid red;
}

Here is a fiddle:

Picture of a fiddle

Just kidding, here is the fiddle: https://jsfiddle.net/nz5fdnd0/1/

Here is a picture of the desired outcome:

Screen shot of desired outcome

The desired solution would avoid using explicit class or id attributes in the HTML.

Upvotes: 2

Views: 2994

Answers (4)

Ricky Ruiz
Ricky Ruiz

Reputation: 26791

You could also use

ul:not(:only-child) > li {
  border: 1px solid red;
}

This will work if your parent <ul> element has siblings.


ul:not(:only-child) > li {
  border: 1px solid red;
}
<ul>
  <li>Level One Item One
    <ul>
      <li>Level One Item One</li>
      <li>Level One Item Two</li>
    </ul>
  </li>
  <li>Level One Item Two
    <ul>
      <li>Level Two Item One</li>
      <li>Level Two Item Two</li>
    </ul>
  </li>
</ul>

Upvotes: 1

Ryenski
Ryenski

Reputation: 9692

One solution I found is to add an outer <div> and then target the first child of that:

div > ul > li {
  border: 1px solid red;
}
<div>
  <ul>
    <li>Level One Item One
      <ul>
        <li>Level One Item One</li>
        <li>Level One Item Two</li>
      </ul>
    </li>
    <li>Level One Item Two
      <ul>
        <li>Level Two Item One</li>
        <li>Level Two Item Two</li>
      </ul>
    </li>
  </ul>
</div>

Unfortunately, it doesn't use any fancy :not selectors, ah well such is life.

Upvotes: 1

oleeeee
oleeeee

Reputation: 11

ul li {
  border: 1px solid red;
}   
 ul:first-child ul li{
   border: none;
 }

Upvotes: -1

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196187

You could use

:not(li) > ul > li {
  border: 1px solid red;
}

which means target the li in a ul that is not contained (directly) in a li.

So keep in mind that if inside a li you add a div and in that a ul li it will get styled.


:not(li) > ul > li {
  border: 1px solid red;
}
<ul>
  <li>Level One Item One
    <ul>
      <li>Level One Item One</li>
      <li>Level One Item Two</li>
    </ul>
  </li>
  <li>Level One Item Two
    <ul>
      <li>Level Two Item One</li>
      <li>Level Two Item Two</li>
    </ul>
  </li>
</ul>

Upvotes: 5

Related Questions