首先选中第一层级的<li>标签,而非嵌套的<li>标签。

72
我有以下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>

如何使用jQuery来定位第一层级的<li>元素?

例如,我需要在鼠标悬停时将字体加粗应用于字母A、B和C的<li>元素,但不要将该字体样式应用于嵌套的名为subsections<li>元素。

这里有一个初始的jsfiddle DEMO,如果您想使用它。

谢谢。

编辑--

解决方案:

子选择器,这就是答案。

不需要jQuery,可以使用CSS来完成此操作。

这是更新后的DEMO

编辑-- 这是一个更清晰的演示

谢谢。


7个回答

129

创建一个带有class属性的容器<div>,并使用>选择器。 假设您的容器div的类是"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.
}

注意: 当作为CSS选择器使用时,在IE6及以下版本中,>选择器无效。但在所有其他浏览器中都有效,包括IE7和IE8,并且在JQuery中使用时,在jQuery支持的所有浏览器中都有效,包括IE6。

1
或者不使用容器,直接使用 body$('body > ul > li').css('border', '1px solid red'); - ncuesta
1
是的,这就是解决方案,而且这也是我自己想出来的解决方案。我选择这个作为正确答案,因为它不需要使用JavaScript来实现,但在发布问题之前,我还没有意识到它可以只用CSS来完成。谢谢! - Ricardo Zea
3
请注意,某些CSS属性可能会继承,因此如果您设置了.myclass > ul > li {font-size: 2em;},则除非您将.myclass li {font-size: 1em;}作为默认值,否则所有的li仍然可能受到影响。 - Chris Beck

20

您可以这样做:

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

但最好给您的顶级 <ul> 元素指定一个ID,这样您就可以使用有效的CSS选择器来对其进行定位:

$('#topUL > li')

1
你的解决方案仅对页面中使用一个 ´ul´ 时有效,而不适用于多个 ´ul´ 的情况。尽管如此,你的解决方案对于这个具体的示例仍然有效。谢谢。 - Ricardo Zea
@Ricardo:你是指因为ID的原因吗?是的,你说得对,你需要使用类来同时针对多个顶级<ul>元素中的第一级<li>元素。或者使用multiple-selector和不同的ID。 - user113716
截至2023年3月,:has()现在是有效的并且大多数情况下可用的CSS选择器,但您的第一个解决方案选取了任何级别不含<ul><li> - EvgenKo423

11

子选择器,这就是答案。

不需要使用jQuery,可以使用CSS来完成。使用选择器定位一级 li 元素:

ul > li {
    font-weight: bold;
}

接着撤销更深层次的li元素的样式:

ul > li li {
    font-weight: normal;
}

这里是更新后的演示


这是我的问题,很难理解为什么如果你只有第一个CSS“ul> li {font-weight:bold;}”,粗体应用于第二级。 - Seabizkit
@Seabizkit 所有 li 中的字体都是加粗的,但由于我只想要第二级别的 li 加粗,所以我必须通过应用第二条规则 ul > li li { font-weight: normal; } 来“取消加粗”。明白了吗? - Ricardo Zea
@RicardoZea 我知道你必须这样做!我不明白的是 CLASS.UL > li 为什么会选中所有的 li,希望这能解决我的困惑。当你只是特别选中某个 li 的时候。 - Seabizkit
@Seabizkit 没有类选择器,我正在使用元素选择器。此外, ul > li {…}会定位文档中所有第一个子 <li> ,因为我们使用了子选择器>,实际上这与仅执行li {…}是一样的,毕竟所有的li都是第一个孩子。诀窍在于第二个规则否定了第一个规则所做的事情。但你已经知道了。这个回答解决了你的问题吗? - Ricardo Zea
我的代码有一个类选择器,但仍然无法正常工作。即:我可以理解为什么单独使用ul > li可能不起作用,但我不明白为什么CLASS.UL > li没有生效。也许我要找的正确写法是“CLASS > UL > li”。我会尝试这样写,应该就能行了,那样就有意义了。 - Seabizkit
显示剩余5条评论

2
我会设定一个规则来针对所有的li元素,然后另一个规则来覆盖这个规则,以针对嵌套的li元素。
li{font-weight:bold;}
ul ul li{font-weight:normal;}

嵌套的li元素将是普通字体,而顶级元素将是粗体。

1

我认为你的问题还没有完全解决(虽然已经有一些不错的尝试)。你的示例问题涉及将样式应用于父元素并防止子元素继承该样式——这是一个CSS问题。

你可以通过了解父元素来定位列表项(正如一些人所指出的那样)。然后在悬停时添加一个类。

$('div > ul > li').hover(function(){
    $(this).addClass('myHover');
},
function(){
    $(this).removeClass('myHover');
});

而你的CSS将为父元素设置类,对于子元素则设置否定样式:

.myHover { font-weight: bold; }
.myHover li { font-weight: normal; }

是的,这是非常好的解决方案。然而,我更喜欢不使用jQuery(尽管在提问时我还没有想出可以仅使用CSS完成)。不过我已经给你投了一票。 - Ricardo Zea
谢谢。我不确定您是否想在JavaScript中做其他事情,还是只是添加CSS样式。对于仅进行样式更改,:hover伪类绝对是正确的选择。 - typeof

1

这是用户@Spudley的答案的扩展版本 - 带有代码片段。

可能会节省一些人的时间。

/* this will affect all levels of li */
.myclass ul li {
  color: red;
}


/* this will only affect level 1 */
.myclass>ul>li {
  color: green;
}


/* this will only affect level 2 */
.myclass>ul>li>ul>li {
  color: blue;
}


/* this will only affect level 3 */
.myclass>ul>li>ul>li>ul>li {
  color: aqua;
}


* {
  font-family: arial;
}
<div class="myclass">
  <ul>
    <li>Level 1
      <ul>
        <li>Level 2
          <ul>
            <li>Level 3</li>
            <li>Level 3</li>
          </ul>
        </li>
        <li>Level 2</li>
        <li>Level 2
          <ul>
            <li>Level 3</li>
            <li>Level 3</li>
            <li>Level 3
              <ul>
                <li>Level 4</li>
                <li>Level 4</li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li>Level 1</li>
  </ul>
</div>


0

这可以使用jQuery或CSS3来完成,使用:not()选择器来检查列表的父级。
为了防止CSS属性继承,您可以使用<span><div>包装项目的内容。

:not(li) > ul > li > span {
  color: green;
}
<ul>
  <li><span>Level 1</span></li>
  <li><span>Level 1</span>
    <ul>
      <li><span>Level 2</span></li>
      <li><span>Level 2</span>
        <ul>
          <li><span>Level 3</span></li>
          <li><span>Level 3</span></li>
        </ul>
      </li>
      <li><span>Level 2</span></li>
    </ul>
  </li>
  <li><span>Level 1</span></li>
</ul>

请注意,此方法仅适用于元素直接嵌套的情况(即使用子级组合器(>)时),否则:not()将始终匹配随机祖先。

感谢您的回答。使用jQuery/JS可以实现,但显然并不必要。这是一种仅使用CSS的解决方案(我在我的编辑中提到了这一点:])。现在,使用:not()伪类是一个选项,但在我看来,它使解决方案过于冗长,因此不太可扩展。有一件事情我肯定不会推荐,那就是为了定位而使用额外的标记。说实话,看到那些列表项中的<span>让我感到非常不舒服><,哈哈 - Ricardo Zea
@RicardoZea 不确定您所说的“太冗长”是什么意思,但是它确切地检查了所需的内容,而不添加任何额外的类。在这种情况下,最终选择器看起来相当冗长,但是在我的情况下,我正在检查嵌套类,因此只添加了一个选择器。 至于额外的标记,我也不喜欢,但是您无法在CSS中选择裸文本。这就是<span>的作用,您接受的答案还添加了一个额外的<div>。另一方面,覆盖嵌套元素的样式对我来说看起来像是一个肮脏的技巧,并且会导致代码重复 - EvgenKo423
@EvgeKo423 看来你知道“verbose”的意思。你的解决方案使用了 :not(pseudo) 类和 span 选择器,这使得它很啰嗦。尤其是 span 选择器。我可以避免使用 :not(pseudo) 类,但是在 HTML 中使用 span 就没办法了,特别是 在每个 <li> 中都需要一个 <span> 的情况下。这也很啰嗦。重写样式不太美观,但它不是一个 hack。此外,它并不是原则的罕见用法。顺便说一下,那个通过的解决方案是合法的,而“hack”不是。 - Ricardo Zea
@RicardoZea,好的,我明白你的意思了。我只是想要通用地分享我的解决方案,我同意它在这个特定情况下运作得不是很好。 - EvgenKo423

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接