【问题标题】:CSS descendants and other selectorsCSS 后代和其他选择器
【发布时间】:2020-01-06 22:10:20
【问题描述】:

使用下面的 HTML,我的 CSS 是否按照我下面的规定显示?

HTML:

<ul>
<li>1</li>
<li>2</li>
   <ul>
<li>3</li>
   </ul>
<li>4</li>
</ul>

CSS:

ul + li   /* 1 and 3 */
ul > li   /* 1, 2 and 3 */
ul ~ li   /* 1, 2, 3 and 4 */

同样重要的是,我哪里做错了?

【问题讨论】:

  • 我看到的第一个问题是ul 应该只有lis 作为孩子。您可以将ul 放在li 中,但它不应该是ul 的直接子代。其次,+~ 都是兄弟选择器,所以ul + liul ~ li 永远不应该匹配任何东西。但是在您提供的代码中,两者都只会将 li 与内容 4 匹配。&gt; 是直接子选择器,因此它将匹配您的所有 lis。
  • 查看此内容以获得快速参考:techbrij.com/css-selector-adjacent-child-sibling
  • 为此使用 first-child、last-child 和 nth-child() 选择器。你的方法看起来太具体了。
  • shadymoses:感谢您的链接......尽管链接非常好,但我很难理解您的第一段。例如,第二个 ul 是 li(2) 的第一个孩子,但我想你说它是第一个 ul 的直接孩子。另一个例子... li(1) 是 ul(1) 的第一个兄弟,但你说 + 和 ~ 不应该匹配任何东西?原谅我的迟钝,但我真的遇到了麻烦。
  • @JohnLove shadymoses 是对的;第二个ul 是第一个ul 的子代,这是不正确的。您应该修复它,以便第二个 ulli 内。

标签: html css css-selectors html-lists


【解决方案1】:

这里发生了很多事情,所以我将尝试为您一一分解。这会很长,但请耐心等待。

让我们让缩进更加一致,这样我们就可以看到 HTML 发生了什么:

<ul>
  <li>1</li>
  <li>2</li>
  <ul>
    <li>3</li>
  </ul>
  <li>4</li>
</ul>

当您打开第一个ul 并开始向其中添加lis 时,那些li 元素是第一个ul子元素。它们出现在内部,或者更准确地说,出现在它的开始标签&lt;ul&gt; 和它的结束标签&lt;/ul&gt; 之间。

当您打开第二个ul 时,您已经用自己的结束标记关闭了第二个li。第二个ul 不是li 的子代,因为它出现在之后 结束标记&lt;/li&gt;。所以第二个ul——如果你愿意的话,是内部的——是第二个li兄弟,因此是第一个(外部)ul的孩子。同样,第四个li 是第二个ul 的兄弟,也是第一个ul 的子代。

第三个li 是第二个(内部)ul 的子代。它既不是任何其他元素的子元素,也不是兄弟元素。它是第一个(外部)ulgrand子代,但为了回答您的问题,这并不重要。

如果标记在视觉上类似于家谱,那么它对您来说应该是有意义的。在家谱中,孩子出现在父母之下。 (只是,在一棵家谱中,通常有两个父母;在 HTML 中,每个孩子只有一个父母。)作为兄弟姐妹的孩子并排出现,连接到同一个父母。此标记的结构类似,除了子项从上到下而不是从左到右列出。但从逻辑上讲,它们仍然是“并排”的。

回想一下以下选择器的作用:

  • ul + li 匹配 li,这是紧跟在 ul 之后出现的兄弟。
  • ul &gt; li 匹配 li,它是 ul 的子代。
  • ul ~ li 匹配 li 之后的 ul 作为兄弟,但与 + 不同,它不必立即出现,只要它们位于同一组开始和结束标签之间(这称为“具有相同的父元素”)。任何ul + li 都会自动成为ul ~ li

这是带有一些注释的标记:

<ul>
  <li>1</li>   <!-- ul > li -->
  <li>2</li>   <!-- ul > li -->
  <ul>
    <li>3</li> <!-- ul > li -->
  </ul>
  <li>4</li>   <!-- ul > li, ul + li, ul ~ li -->
</ul>

确实,前三个li 元素中没有 是任何ul 的兄弟。只有最后一个是,它匹配两个兄弟选择器。

那么如何使内部ul 成为第二个li 的子级?为此,您可以移动 &lt;/li&gt;,使其出现在 &lt;/ul&gt; 之后,如下所示:

<ul>
  <li>1</li>     <!-- ul > li -->
  <li>2          <!-- ul > li -->
    <ul>
      <li>3</li> <!-- ul > li -->
    </ul>
  </li>
  <li>4</li>     <!-- ul > li, ul + li, ul ~ li -->
</ul>

关键的是,内部ul 现在将匹配不同的选择器:li &gt; ul。此外,您的标记现在将得到验证,因为您一开始就不允许将 ul 作为另一个 ul 的子代。

最后,您的一些规定需要更复杂的选择器,因为它们匹配得非常具体。我会逐个介绍:

  1. 要匹配 1 和 3,请使用 ul &gt; li:first-child。这是因为 1 和 3 是它们各自父级 uls 的第一个子级。您通常可以判断一个元素是否是另一个元素的第一个子元素,因为它的开始标记是出现在父级开始标记之后的第一个元素,忽略任何文本或空格。

  2. 要匹配 1、2 和 3,请使用 ul &gt; li:first-child, ul &gt; li:nth-child(2)。额外的:nth-child(2) 专门针对第 2 项。

  3. 要匹配 1、2、3 和 4,使用 ul &gt; li 就足够了,因为您只是匹配所有这些。如果您的标记中只有ul,您可能只使用li 就可以逃脱惩罚,但这种情况不太可能发生,所以我犯了错误,倾向于更具体而不是必要,而不是不够具体.

需要考虑的内容很多,所以如果其中有任何令人困惑或不知所措,请告诉我,我会尽力解决您的疑虑。

【讨论】:

  • 恰恰相反。你的回答说“什么”和“为什么”。我不是在寻找“这是错误的,句号!”。我正在寻找“由于这些原因这是错误的,这是正确的方法”。你是一位优秀的老师,谢谢你。
  • @John Love:谢谢,很荣幸 :)
  • 现在只有一个问题。 WRT 你重做我的原始标记,li-4 是第一个 ul 的几个兄弟姐妹之一,所以 ul>li 有效。 ul~li也是。但不是 ??? ul+li 因为 li-4 没有 ???立即跟随其父级 = 第一个 ul。
  • 它是第一个 ul 的几个 孩子 之一,而不是兄弟姐妹。但你是对的,我犯了一个错误;因为第 2 个 ul 在 li-3 中,所以第 2 个 ul 不再是任何 li 项目的兄弟,因为它现在是其中一个项目的孩子。所以 li+li 最终匹配了包括 li-4 在内的所有内容。我会修改我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多