【问题标题】:Is there a "previous sibling" selector?是否有“上一个兄弟姐妹”选择器?
【发布时间】:2022-05-30 05:45:27
【问题描述】:

加号 (+) 用于选择下一个兄弟。

是否有前一个兄弟姐妹的等价物?

  • 您不需要它,因为您可以使用通用选择器和下一个兄弟选择器的组合来完成所有操作。
  • 我不确定您是否在所有情况下都可以,即使是这样 - 它很难阅读和推理,因此应该添加为方便 imo
  • 哪个组合器可以用于父选择器?,@GabrielLinassi
  • 这可以通过以下方式实现: display: flex; flex-direction:行反向;

标签: css css-selectors siblings


【解决方案1】:

不,没有“前一个兄弟”选择器。

在相关的注释中,~ 用于一般后继兄弟(意味着元素在此之后,但不一定紧随其后)并且是 CSS3 选择器。 + 是下一个兄弟姐妹,是 CSS2.1。

参见Adjacent sibling combinator 来自Selectors Level 35.7 Adjacent sibling selectors 来自Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification

【讨论】:

  • 来自 CSS3 标准:两个序列表示的元素共享同一个父级在文档树和第一个序列表示的元素中先于(不一定立即)第二个表示的元素。
  • @Lie Ryan:是的,但是 cletus 在他的回答中的意思是你没有选择前面的元素。
  • 这是我做的一个例子,看看它可以做什么,不能做什么。 jsfiddle.net/NuuHy/1
  • 对此有用的 jquery 函数是 prev()。例如 $("#the_element").prev().css("background-color", "red")
【解决方案2】:

我找到了一种方法来设计所有以前的兄弟姐妹(与~ 相反),这可能取决于您的需要。

假设您有一个链接列表,当悬停在一个链接上时,之前的所有链接都应该变成红色。你可以这样做:

/* default link color is blue */
.parent a {
  color: blue;
}

/* prev siblings should be red */
.parent:hover a {
  color: red;
}
.parent a:hover,
.parent a:hover ~ a {
  color: blue;
}
<div class="parent">
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
</div>

【讨论】:

  • 您可以添加对其工作原理的说明。 (似乎您将样式应用于所有项目和以下项目,但可以明确描述)
  • 是的,但大多数时候需要一个以前的而不是所有以前的!
  • 对我来说,如果我将鼠标悬停在它们之间的空间上,链接都会变成红色。
  • 由于.parent:hover a 样式,所有标签在悬停在父标签上时都会变成红色 - 但同时不会悬停在任何子标签上。
  • @Lynn @JoeVanLeeuwen 是的,此示例仅包含针对先前兄弟姐妹的最少规则。要删除间距,您需要添加更多规则,可能会更改竞争者的 display
【解决方案3】:

Selectors level 4 proposes :has()(以前的主题指示符!)有一天,它允许您选择以前的兄弟姐妹:

previous:has(+ next) {}

…但在撰写本文时browser support 实际上是不存在的.


多年来,这个答案吸引了数十个“仍然不支持”的 cmets(现已删除)。请不要再添加了。答案中有一个指向最新浏览器支持图表的链接。

【讨论】:

    【解决方案4】:

    考虑弹性和网格布局的order 属性。

    在下面的示例中,我将重点关注 flexbox,但同样的概念也适用于 Grid。


    使用 flexbox,可以模拟先前的兄弟选择器。

    特别是,flexorder 属性可以在屏幕上移动元素。

    这是一个例子:

    当元素 B 悬停时,您希望元素 A 变为红色。

    <ul>
        <li>A</li>
        <li>B</li>
    </ul>
    

    脚步

    1. 使 ul 成为弹性容器。

      ul { display: flex; }
      

      1. 颠倒标记中同级的顺序。

        <ul>
           <li>B</li>
           <li>A</li>
        </ul>
        

      1. 使用同级选择器来定位元素 A(~+ 可以)。

        li:hover + li { background-color: red; }
        

      1. 使用 flex order 属性来恢复视觉显示上的兄弟姐妹的顺序。

        li:last-child { order: -1; }
        

      ……瞧!先前的兄弟选择器诞生(或至少模拟)。

      这是完整的代码:

      ul {
          display: flex;
      }
      
      li:hover + li {
          background-color: red;
      }
      
      li:last-child {
          order: -1;
      }
      
      /* non-essential decorative styles */
      li {
          height: 200px;
          width: 200px;
          background-color: aqua;
          margin: 5px;
          list-style-type: none;
          cursor: pointer;
      }
      <ul>
          <li>B</li>
          <li>A</li>
      </ul>

      来自 flexbox 规范:

      5.4. Display Order: the order property

      默认情况下,Flex 项目的显示和布局顺序与它们在源文档中的显示顺序相同。这 order 属性可用于更改此排序。

      order 属性通过将弹性项目分配给有序组来控制弹性项目在弹性容器中出现的顺序。它需要一个 &lt;integer&gt; 值,它指定弹性项目的序数组 属于。

      所有弹性项目的初始 order 值为 0。

      另见order in the CSS Grid Layout spec


      使用 flex order 属性创建的“前一个兄弟选择器”示例。

      .container { display: flex; }
      
      .box5 { order: 1; }    
      .box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }
      
      .box6 { order: -4; }
      .box7 { order: -3; }
      .box8 { order: -2; }
      .box9 { order: -1; }
      .box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;
                                                    font-size: 1.5em; }
      .box12 { order: 2; }
      .box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;
                                              font-size: 1.5em; }
      .box21 { order: 1; }
      .box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }
      
      /* non-essential decorative styles */
      .container {
          padding: 5px;
          background-color: #888;
      }
      .box {
          height: 50px;
          width: 75px;
          margin: 5px;
          background-color: lightgreen;
          display: flex;
          justify-content: center;
          align-items: center;
          text-align: center;
          cursor: pointer;
      }
      <p>
      Using the flex <code>order</code> property to construct a previous sibling selector
      </p>
      
      <div class="container">
          <div class="box box1"><span>1</span></div>
          <div class="box box2"><span>2</span></div>
          <div class="box box3"><span>3</span></div>
          <div class="box box5"><span>HOVER ME</span></div>
          <div class="box box4"><span>4</span></div>
      </div>
      
      <br>
      
      <div class="container">
          <div class="box box9"><span>HOVER ME</span></div>
          <div class="box box12"><span>HOVER ME</span></div>
          <div class="box box6"><span>6</span></div>
          <div class="box box7"><span>7</span></div>
          <div class="box box8"><span>8</span></div>
          <div class="box box10"><span>10</span></div>
          <div class="box box11"><span>11</span></div>
      </div>
      
      <br>
      
      <div class="container">
          <div class="box box21"><span>HOVER ME</span></div>
          <div class="box box13"><span>13</span></div>
          <div class="box box14"><span>14</span></div>
          <div class="box box15"><span>15</span></div>
          <div class="box box16"><span>16</span></div>
          <div class="box box17"><span>17</span></div>
          <div class="box box18"><span>18</span></div>
          <div class="box box19"><span>19</span></div>
          <div class="box box20"><span>20</span></div>
      </div>

      jsFiddle


      旁注——关于 CSS 的两个过时的信念

      Flexbox 正在打破长期以来对 CSS 的看法。

      一种这样的信念是a previous sibling selector is not possible in CSS

      说这种信念是普遍存在的将是轻描淡写。以下是有关 Stack Overflow 的相关问题示例:

      如上所述,这种信念并不完全正确。可以使用 flex order 属性在 CSS 中模拟以前的同级选择器。

      z-index 神话

      另一个长期存在的信念是z-index 仅适用于定位元素。

      事实上,最新版本的规范——W3C Editor's Draft——仍然断言这是真的:

      9.9.1 Specifying the stack level: the z-index property

      z-index

      • 值:自动 | |继承
      • 初始:自动
      • 适用于:定位元素
      • 继承:否
      • 百分比:不适用
      • 媒体:视觉
      • 计算值:如指定

      (重点补充)

      然而,实际上,这些信息已经过时且不准确。

      即使positionstaticflex itemsgrid items 的元素也可以创建堆叠上下文。

      4.3. Flex Item Z-Ordering

      Flex 项目的绘制与内联块完全相同,除了使用 order-modified 文档 order 代替 raw 文档顺序和z-index 以外的auto 值创建一个堆叠上下文,即使positionstatic

      5.4. Z-axis Ordering: the z-index property

      网格项的绘制顺序与内联块完全一样,只是 order-modified 文档顺序是 用于代替原始文档顺序,并且 z-index 以外的 auto 值创建一个堆叠上下文,即使 positionstatic

      这是z-index 处理非定位弹性项目的演示:https://jsfiddle.net/m0wddwxs/

    【讨论】:

    • order 属性不是解决方案,因为它仅用于更改视觉的订购,所以它确实不是恢复原来的语义的为了使此解决方法起作用,您必须强制更改 HTML。
    • 请记住,您引用的 CSS2.2 ED 本质上仍然是 CSS2。并且 CSS2 中不存在 flexbox 和网格布局,因此就 CSS2 而言,这些信息肯定是正确的。至少,可以更新文本以提及 z-index 可能适用于未来级别的 CSS 中的其他类型的元素,就像它说其他属性可能建立堆叠上下文一样,例如不透明度。
    • @BoltClock 我的评论与浏览器支持无关。该技术打破了语义,有利于呈现。我相信在服务器端添加一个普通的常规类到以前的兄弟元素中要合理得多。
    • 如果有人无法理解z-index 何时起作用,即使“天哪,没有指定position!”,规范中提到了堆叠上下文this article on MDN 很好地解释了这一点
    • @Michael_B 不客气!我已经处理了很多没有意识到这一点的前端。我想提一提的另一件事,伪造的上一个兄弟选择器也可以很好地与float: right 一起使用(或任何其他反转排序的方法,其中flex/order 几乎没有(最少?)副作用)。掀起了两个小提琴:demonstrating the float: right approach,和demonstrating direction: rtl
    【解决方案5】:

    我有同样的问题,但后来我有一个“呃”的时刻。而不是写

    x ~ y
    

    y ~ x
    

    显然这匹配“x”而不是“y”,但它回答“有匹配吗?”问题,简单的 DOM 遍历可能比在 javascript 中循环更有效地让您找到正确的元素。

    我意识到最初的问题是一个 CSS 问题,所以这个答案可能完全无关紧要,但其他 Javascript 用户可能会像我一样通过搜索偶然发现这个问题。

    【讨论】:

    • 我相信当 y 可以很容易地找到时,它会起作用。问题是如果 y 只能相对于 x 找到,并且在反转它时,您找不到 y,因为您必须先找到 x。这当然是指 y 是前面的兄弟而不是下一个的问题,但也可能适用于 y 是后面的兄弟。
    • 你有点苛刻,哈什。 (对不起,无法抗拒。)关键是有时你只需要知道“你存在吗?”。其他时候你可以使用 ":before" 在两个元素之间放置一些东西。最后,如果您必须使用 jQuery,使用 find("y ~ x").prev() 比许多替代方法更容易。
    • 前一个兄弟选择器的想法是它将选择前一个元素。不幸的是,如此处所述,反转它不提供此功能。
    • 感谢@Zenexer 澄清这个答案并没有为原始问题提供实际的解决方案,我开始觉得自己愚蠢地思考y ~ x 如何解决我的问题
    • 我理解这个答案背后的想法,但是答案中给出的推理并不完全有意义。选择器y ~ x 没有回答“有匹配项吗?”问题,因为这里给出的两个选择器意味着完全不同的东西。例如,给定子树&lt;root&gt;&lt;x/&gt;&lt;y/&gt;&lt;/root&gt;y ~ x 不可能产生匹配。如果问题是“你存在吗?”那么选择器就是y。如果问题是“给定任意位置的同级 x,y 是否存在?”那么你需要两个都选择器。 (虽然也许我现在只是在吹毛求疵......)
    【解决方案6】:

    没有“前一个选择器”,但您可以使用:not~ 的组合(“后选择器”)。没有逆序,没有javascript。

    .parent a{
      color: blue
    }
    
    .parent a.active{
      color: red
    }
    
    .parent a:not(.parent a.active ~ a){
      color: red
    }
    <div class="parent">
      <a href="">link</a>
      <a href="">link</a>
      <a href="" class="active">link</a>
      <a href="">link</a>
      <a href="">link</a>
    </div>

    我认为我的方法比“设置所有 div 的样式,而不是删除后 div 的样式”、使用 javascript 或使用相反的顺序更直接。

    【讨论】:

    • 读者注意事项:请注意,这不是先前的兄弟选择器,而是“一般的先前兄弟”选择器,因为它将匹配任何匹配的元素,而不仅仅是前一个元素(但不会从解决方案中删除,这很有创意)。
    • 我用.parent a:not(.parent a.active ~ a, a.active, .parent :first-child) { color: red } 只为第二个孩子着色。
    • 这个答案就像mantish做2015年答案的复杂方式
    【解决方案7】:

    技巧
    基本上,颠倒 HTML 中元素的 HTML 顺序,
    并使用~下一个兄弟姐妹操作员:

    1. 使用 CSS Flex 和 row-reverse

    .reverse {
      display: inline-flex;
      flex-direction: row-reverse;
    }
    .reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
      background:gold;
    }
    Hover a SPAN and see the previous elements being styled!<br>
    
    <div class="reverse">
      <!-- Reverse the order of inner elements -->
      <span>5</span>
      <span>4</span>
      <span>3</span>
      <span>2</span>
      <span>1</span>
    </div>

    2.使用带方向的Flex:RTL

    .reverse {
      display: inline-flex;
      direction: rtl;
    }
    .reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
      background: red;
    }
    Hover a SPAN and see the previous elements being styled!<br>
    
    <div class="reverse">
      <!-- Reverse the order of inner elements -->
      <span>5</span>
      <span>4</span>
      <span>3</span>
      <span>2</span>
      <span>1</span>
    </div>

    3. 使用浮动权

    .reverse { 
      display: inline-block;
    }
    .reverse span{
      float: right; 
    }
    .reverse span:hover ~ span { /* On SPAN hover target its "previous" elements */
      background: red;
    }
    Hover a SPAN and see the previous elements being styled!<br>
    
    <div class="reverse">
      <!-- Reverse the order of inner elements -->
      <span>5</span>
      <span>4</span>
      <span>3</span>
      <span>2</span>
      <span>1</span>
    </div>

    【讨论】:

      【解决方案8】:

      + 用于下一个兄弟姐妹。前一个有没有等价物 兄弟?

      你可以使用这两个斧头选择器:!?

      2传统 CSS 中的后续兄弟选择器:

      • +即时后续兄弟选择器
      • ~任何后续兄弟选择器

      在传统的 CSS 中,有没有前一个兄弟选择器.

      然而,在斧头CSS后处理器库,有2以前的兄弟选择器:

      • ?即时上一个兄弟选择器(与 + 相对)
      • !任何上一个兄弟选择器(~ 的对面)

      工作示例:

      在下面的示例中:

      • .any-subsequent:hover ~ div 选择任何后续 div
      • .immediate-subsequent:hover + div 选择紧随其后的div
      • .any-previous:hover ! div 选择任何以前的 div
      • .immediate-previous:hover ? div 选择前一个 div

      div {
        display: inline-block;
        width: 60px;
        height: 100px;
        color: rgb(255, 255, 255);
        background-color: rgb(255, 0, 0);
        text-align: center;
        vertical-align: top;
        cursor: pointer;
        opacity: 0;
        transition: opacity 0.6s ease-out;
      }
      
      code {
        display: block;
        margin: 4px;
        font-size: 24px;
        line-height: 24px;
        background-color: rgba(0, 0, 0, 0.5);
      }
      
      div:nth-of-type(-n+4) {
        background-color: rgb(0, 0, 255);
      }
      
      div:nth-of-type(n+3):nth-of-type(-n+6) {
        opacity: 1;
      }
      
      .any-subsequent:hover ~ div,
      .immediate-subsequent:hover + div,
      .any-previous:hover ! div,
      .immediate-previous:hover ? div {
        opacity: 1;
      }
      <h2>Hover over any of the blocks below</h2>
      
      <div></div>
      <div></div>
      
      <div class="immediate-previous">Hover for <code>?</code> selector</div>
      <div class="any-previous">Hover for <code>!</code> selector</div>
      <div class="any-subsequent">Hover for <code>~</code> selector</div>
      <div class="immediate-subsequent">Hover for <code>+</code> selector</div>
      
      <div></div>
      <div></div>
      
      <script src="https://rouninmedia.github.io/axe/axe.js"></script>

      【讨论】:

      • 当我尝试在 Rails 项目中的 sass 上实现它时,这给了我一个语法错误。
      • 斧头是一个 CSS 后处理器。它不使用与 Sass、Less 或 Stylus 等 CSS 预处理器相同的语法。
      • @Rounin 您介意添加一些文档链接吗?我找不到斧头后处理器。
      • @Dionys - 感谢您的关注。斧头是我在 2016 年底开始的一个项目,当时我还不知道 ES2015,甚至 JS 中的对象对我来说都是非常新的。 GitHub 存储库在这里:github.com/RouninMedia/axe。我非常想在某个时候回到这个问题(我还开发了一种叫做斧刃这是javascript事件的CSS等价物),但我需要完成另一个项目的工作(代号湿婆神) 第一的。
      【解决方案9】:

      另一个 flexbox 解决方案

      您可以在 HTML 中使用反转元素的顺序。然后除了使用orderMichael_B's answer 一样,您还可以使用flex-direction: row-reverse;flex-direction: column-reverse;,具体取决于您的布局。

      工作样本:

      .flex {
        display: flex;
        flex-direction: row-reverse;
         /* Align content at the "reversed" end i.e. beginning */
        justify-content: flex-end;
      }
      
      /* On hover target its "previous" elements */
      .flex-item:hover ~ .flex-item {
        background-color: lime;
      }
      
      /* styles just for demo */
      .flex-item {
        background-color: orange;
        color: white;
        padding: 20px;
        font-size: 3rem;
        border-radius: 50%;
      }
      <div class="flex">
        <div class="flex-item">5</div>
        <div class="flex-item">4</div>
        <div class="flex-item">3</div>
        <div class="flex-item">2</div>
        <div class="flex-item">1</div>
      </div>

      【讨论】:

        【解决方案10】:

        目前没有官方方法可以做到这一点,但你可以使用一个小技巧来实现这一点!请记住,它是实验性的,它有一些限制...... (如果您担心导航器的兼容性,请查看this link

        您可以做的是使用 CSS3 选择器:名为 nth-child() 的伪类

        #list>* {
          display: inline-block;
          padding: 20px 28px;
          margin-right: 5px;
          border: 1px solid #bbb;
          background: #ddd;
          color: #444;
          margin: 0.4em 0;
        }
        
        #list :nth-child(-n+4) {
          color: #600b90;
          border: 1px dashed red;
          background: orange;
        }
        <p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>
        
        <div id="list">
          <span>1</span><!-- this will be selected -->
          <p>2</p><!-- this will be selected -->
          <p>3</p><!-- this will be selected -->
          <div>4</div><!-- this will be selected -->
          <div>5</div>
          <p>6</p>
          <p>7</p>
          <p>8</p>
          <p>9</p>
        </div>

        限制

        • 您不能根据下一个元素的类选择上一个元素
        • 这与伪类相同

        【讨论】:

        • 为什么它们必须是同一个节点?为什么不直接使用:nth-child(-n+4)
        • @Ian 因为:nth-child(-n+4) 是一个伪类,需要应用于选择器才能正常工作。如果您不相信,请尝试使用我的小提琴叉子进行实验,您会发现它无法正常工作
        • 实际上,您可以使用* 选择器独立于节点类型,但这是非常糟糕的做法。
        • 实际上,它适用于不同的节点:jsfiddle.net/aLhv9r1w/316。请更新您的答案:)
        • 我有一个复杂的选择器,但假设它是li#someListItem,我想要它之前的节点(这就是我解释“上一个”的方式) - 我看不出您提供的信息如何帮助我表达通过 CSS。您只是选择前 n 个兄弟姐妹,并假设我知道 n。基于这个逻辑,任何选择器都可以解决问题并选择我需要的元素(例如 :not() )。
        【解决方案11】:

        你可以使用双重否定

        SELECTOR:not([SELECTOR]FILTER):not([SELECTOR]FILTER + SELECTOR) { ... }
        

        SELECTOR 替换为TAG.CLASS(使用#ID 可能过于具体)。 将FILTER 替换为其他:PSUEDO-SELECTOR(我只尝试过:hover)或.CLASS(更多用于通过Javascript 切换)。

        由于典型用法可能依赖于悬停(参见下面的示例)

        /* Effect only limited when hovering */
        TAG.CLASS:not(TAG.CLASS:hover):not(TAG.CLASS:hover + TAG.CLASS) {}
        /* Effect only applied when hovering */
        PARENT.CLASS:hover > CHILD.CLASS:not(CHILD.CLASS:hover):not(CHILD.CLASS:hover + CHILD.CLASS) {}
        

        /* Solution */
        div.parent:hover > div.child:not(:hover):not(:hover ~ .child)  {
            background-color:red;
            border-radius:1.5em;
        }
        div.parent:hover > div.child:not(:hover):not(:hover ~ .child) > div {
            background-color:yellow;
        }
        
        /* Make pretty (kinda) */
        div.parent {
          width:9em;
          height:9em;
          /* Layout */
          display:grid;
          grid-template-columns : auto auto auto;
          grid-template-rows : auto auto auto;
        }
        div.child {
          /* Dimensions */
          height:3em;
          width:3em;
          /* Layout */
          position:relative;
          /* Cursor */
          cursor: pointer;
          /* Presentation */
          border: 1px black solid;
          border-radius:1.5em;
        }
        .star {
          /* Dimensions */
          width: 2.5em;
          height: 2.5em;
          /* Placement */
          position:absolute;
          top: 50%;
          left: 50%;
          transform:translate(-50%,-50%);
          /* Geometry */
          -webkit-clip-path: polygon(
            50% 0%,
            63% 38%,
            100% 38%,
            69% 59%,
            82% 100%,
            50% 75%,
            18% 100%,
            31% 59%,
            0% 38%,
            37% 38%
          );
          clip-path: polygon(
            50% 0%,
            63% 38%,
            100% 38%,
            69% 59%,
            82% 100%,
            50% 75%,
            18% 100%,
            31% 59%,
            0% 38%,
            37% 38%
          );
          /* Presentation */
          background-color: lightgrey;
        }
        div.child:hover {
            /* Presentation */
            background-color:yellow;
            border-radius:1.5em;
        }
        div.child:hover > div.star {
            /* Presentation */
            background-color:red;
        }
        <div class="parent">
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
          <div class="child" href="#"><div class="star"></div></div>
         </div>

        【讨论】:

          【解决方案12】:

          不,通过 CSS 是不可能的。它需要“级联”;-)。


          但是,如果您能够添加JavaScript到你的页面,一点点jQuery可以让你达到你的最终目标。
          您可以使用 jQuery 的 find 对您的目标元素/类/id 执行“前瞻”,然后回溯以选择您的目标。
          然后,您使用 jQuery 为您的元素重新编写 DOM (CSS)。

          基于this answer by Mike Brant, 以下 jQuery sn-p 可能会有所帮助。

          $('p + ul').prev('p')
          

          这首先选择紧跟&lt;p&gt; 的所有&lt;ul&gt;s。
          然后它“回溯”以从那组&lt;ul&gt;s 中选择所有以前的&lt;p&gt;s。

          实际上,已经通过 jQuery 选择了“前一个兄弟姐妹”。
          现在,使用 .css 函数为该元素传入 CSS 新值。


          就我而言,我正在寻找一种方法来选择一个 ID 为 #full-width 的 DIV,但前提是它有一个类为 .companies 的(间接)后代 DIV。

          我可以控制.companies 下的所有 HTML,但无法更改它上面的任何 HTML。
          级联只有一个方向:向下。

          因此我可以选择所有#full-widths。
          或者我可以选择只跟在#full-width 后面的.companies
          但我可以不是只选择#full-widths进行.companies

          而且,我无法在 HTML 的任何更高位置添加.companies。 HTML 的那部分是在外部编写的,并包装了我们的代码。

          但是使用 jQuery,我能够选择所需的#full-widths,然后分配适当的样式:

          $("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );
          

          这将找到所有#full-width .companies,并仅选择那些.companies,类似于如何使用选择器来定位 CSS 标准中的特定元素。
          然后它使用.parents“回溯”并选择.companies的所有父母,
          但过滤这些结果以仅保留 #fill-width 元素,这样最后,
          如果它有一个.companies 类后代,它只会选择一个#full-width 元素。
          最后,它为结果元素分配一个新的 CSS (width) 值。

          $(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
          div {
            background-color: lightblue;
            width: 120px;
            height: 40px;
            border: 1px solid gray;
            padding: 5px;
          }
          .wrapper {
            background-color: blue;
            width: 250px;
            height: 165px;
          }
          .parent {
            background-color: green;
            width: 200px;
            height: 70px;
          }
          <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
          <html>
          <div class="wrapper">
          
            <div class="parent">
              "parent" turns red
              <div class="change-parent">
              descendant: "change-parent"
              </div>
            </div>
            
            <div class="parent">
              "parent" stays green
              <div class="nope">
              descendant: "nope"
              </div>
            </div>
            
          </div>
          Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>
          <b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>
          <br>
          (reverse cascade, look ahead, parent un-descendant)
          </html>

          jQuery 参考文档:
          $() or jQuery():DOM 元素。
          .find:获取当前匹配元素集中每个元素的后代,由选择器、jQuery 对象或元素过滤。
          .parents:获取匹配元素集中每个元素的前一个兄弟。如果提供了选择器,则仅当它与该选择器匹配时才检索前一个同级(过滤结果以仅包含列出的元素/选择器)。
          .css:为匹配的元素集设置一个或多个 CSS 属性。

          【讨论】:

          • 这与问题无关。当然也可以使用 JS,你甚至不需要 jQuery (previousElementSibling)。
          • @FabianvonEllerts 我在回复的第一行直接回答了 OP 的问题。正如我的回答所说,字面上是无法通过 CSS.然后我提供1 可能的前进道路为了实现这个目标,使用 CSS 用户可能熟悉并可以使用的技术(JS | JQuery)。例如,许多 WordPress 网站也有 JQuery,因此它是一个简单的入口点:易于使用、记忆和扩展。简单回答是不负责任的,而没有提供实现目标的替代方法。当我有同样的问题时,我分享了我学到和使用的东西。
          • previousElementSibling() 对于那些更熟悉原生 JS DOM 功能的人可以提供其他非 CSS 路径向前。
          • 我发现其他 CSS HACKS 非常有趣,但对于我的特定用例,它们要么不起作用(属于警告类别),要么过于复杂。对于其他处于相同情况的人,在上述解决方案失败或难以实施/维护的情况下,分享这种可行的易于使用的方法是公平的。共享了许多 CSS HACK。未涵盖此解决方法。没有一个答案使用 OP 特别要求的+(不存在)选择器。将此答案视为 JS “hack”。这是为了节省我花在寻找解决方案上的时间。
          • "它将“级联”牢记在心;-)。“说得好。你可能就停在那里了。;^D
          【解决方案13】:

          如果您知道确切位置,则基于:nth-child() 的所有以下兄弟姐妹的排除将起作用。

          ul li:not(:nth-child(n+3))
          

          这将选择第三个之前的所有lis(例如第一个和第二个)。但是,在我看来,这看起来很难看,而且用例非常紧凑。

          您还可以从右到左选择第 n 个子项:

          ul li:nth-child(-n+2)
          

          哪个也一样。

          【讨论】:

            【解决方案14】:

            在悬停时覆盖下一个兄弟姐妹的样式,以便看起来只有以前的兄弟姐妹在悬停时添加了样式。

            ul li {
              color: red;
            }
            
            ul:hover li {
              color: blue;
            }
            
            ul:hover li:hover ~ li{
              color: red;
            }
            <ul>
                <li>item 1</li>
                <li>item 2</li>
                <li>item 3</li>
            </ul>

            【讨论】:

              【解决方案15】:

              根据您的确切目标,有一种方法可以在不使用父选择器的情况下实现父选择器的有用性(即使存在父选择器)......

              假设我们有:

              <div>
                <ul>
                  <li><a>Pants</a></li>
                  <li><a>Socks</a></li>
                  <ul>
                    <li><a>White socks</a></li>
                    <li><a>Blue socks</a></li>
                  </ul>
                </ul>
              </div>
              

              我们可以做些什么来使用间距使 Socks 块(包括袜子颜色)在视觉上突出?

              什么会很好但不存在:

              ul li ul:parent {
                margin-top: 15px;
                margin-bottom: 15px;
              }
              

              存在什么:

              li > a {
                margin-top: 15px;
                display: block;
              }
              li > a:only-child {
                margin-top: 0px;
              }
              

              这会将所有锚链接设置为在顶部具有 15px 的边距,并将其重置为 0,以便在 LI 中没有 UL 元素(或其他标签)的链接。

              【讨论】:

                【解决方案16】:

                /* Add a style to all the children, then undo the style to the target 
                and sibling children of your target. */
                
                ul>li {
                  color: red;
                }
                
                ul>li.target,
                ul>li.target~li {
                  color: inherit;
                }
                <ul>
                  <li>before</li>
                  <li class="target">target</li>
                  <li>after</li>
                  <li>after</li>
                </ul>

                【讨论】:

                • 我认为stackoverflow.com/a/48952456/1347604 有点相同的方法,但是这个方法使用继承来表示其他元素,这可能有助于将注意力集中在问题的字面要求上一个兄弟的等价性
                【解决方案17】:

                不幸的是,没有“以前的”兄弟选择器,但你可以可能通过使用定位(例如向右浮动)仍然可以获得相同的效果。这取决于你想要做什么。

                就我而言,我想要一个主要是 CSS 5 星评级系统。我需要为以前的星星着色(或交换图标)。通过向右浮动每个元素,我基本上得到了相同的效果(因此,星星的 html 必须写为“向后”)。

                我在这个例子中使用 FontAwesome 并在 fa-star-o 和 fa-star 的 unicodes 之间交换 http://fortawesome.github.io/Font-Awesome/

                CSS:

                .fa {
                    display: inline-block;
                    font-family: FontAwesome;
                    font-style: normal;
                    font-weight: normal;
                    line-height: 1;
                    -webkit-font-smoothing: antialiased;
                    -moz-osx-font-smoothing: grayscale;
                }
                
                /* set all stars to 'empty star' */
                .stars-container {
                    display: inline-block;      
                }   
                
                /* set all stars to 'empty star' */
                .stars-container .star {
                    float: right;
                    display: inline-block;
                    padding: 2px;
                    color: orange;
                    cursor: pointer;
                
                }
                
                .stars-container .star:before {
                    content: "\f006"; /* fontAwesome empty star code */
                }
                
                /* set hovered star to 'filled star' */
                .star:hover:before{
                    content: "\f005"; /* fontAwesome filled star code */
                }
                
                /* set all stars after hovered to'filled star' 
                ** it will appear that it selects all after due to positioning */
                .star:hover ~ .star:before {
                    content: "\f005"; /* fontAwesome filled star code */
                }
                

                HTML: (40)

                JSFiddle:http://jsfiddle.net/andrewleyva/88j0105g/

                【讨论】:

                • 向右浮动,+~ 选择器让我觉得是最干净的工作。
                【解决方案18】:

                我需要一个解决方案来选择前一个兄弟 tr。我使用 React 和 Styled-components 提出了这个解决方案。这不是我的确切解决方案(这是几个小时后的记忆)。我知道 setHighlighterRow 函数存在缺陷。

                OnMouseOver 一行会将行索引设置为状态,并使用新的背景颜色重新渲染上一行

                class ReactClass extends Component {
                  constructor() {
                    this.state = {
                       highlightRowIndex: null
                    }
                  }
                
                  setHighlightedRow = (index) => {
                    const highlightRowIndex = index === null ? null : index - 1;
                    this.setState({highlightRowIndex});
                  }
                
                  render() {
                    return (
                       <Table>
                        <Tbody>
                           {arr.map((row, index) => {
                                const isHighlighted = index === this.state.highlightRowIndex
                                return {
                                    <Trow 
                                        isHighlighted={isHighlighted}
                                        onMouseOver={() => this.setHighlightedRow(index)}
                                        onMouseOut={() => this.setHighlightedRow(null)}
                                        >
                                        ...
                                    </Trow>
                                }
                           })}  
                        </Tbody>   
                       </Table>
                    )
                  }
                }
                
                const Trow = styled.tr`
                    & td {
                        background-color: ${p => p.isHighlighted ? 'red' : 'white'};
                    }
                
                    &:hover {
                        background-color: red;
                    }
                `;
                

                【讨论】:

                  【解决方案19】:

                  没有,而且.

                  如果您必须将标签之前输入,只需将标签之后输入并保持两者标签& 这输入在一个里面div,并设置样式div如下:

                  .input-box {
                    display: flex;
                    flex-direction: column-reverse;
                  }
                  <div class="input-box">
                    <input
                     id="email"
                     class="form-item"           
                     />
                  
                     <label for="email" class="form-item-header">                  
                     E-Mail*                  
                     </label>
                  </div>

                  现在您可以应用 css 中可用的标准下一个兄弟样式选项,并且看起来您正在使用以前的兄弟样式。

                  【讨论】:

                    【解决方案20】:

                    没有这样的选择器,但是在 DOM API 中有一个漂亮的只读属性

                    Node.previousSibling

                    【讨论】:

                      【解决方案21】:

                      我找到了最简单的解决方案。它可能仅适用于您正在做的事情。

                      假设您想将鼠标悬停在“sibling_2”上以更改以下示例中的“sibling_1”:

                      <div class='parent'>
                        <div class='sibling_1'></div>
                        <div class='sibling_2'></div>
                      </div>

                      由于没有先前的元素选择器,您可以简单地切换“sibling_1”和“sibling_2”并应用,因此它们看起来相同。

                      .parent {
                        display: flex;
                        flex-direction: row-reverse;
                      }

                      现在您可以像这样选择它们。

                      .sibling_1:hover ~ .sibling_2 {
                        #your CSS
                      }

                      【讨论】:

                      • 简单又好看,谢谢大哥!
                      【解决方案22】:

                      我有一个类似的问题,发现所有这种性质的问题都可以解决如下:

                      1. 为您的所有物品赋予一种风格。
                      2. 为您选择的项目指定样式。
                      3. 使用 + 或 ~ 为下一个项目指定样式。

                        这样,您就可以设置当前、以前的项目(所有项目都被当前和下一个项目覆盖)和下一个项目的样式。

                        例子:

                        /* all items (will be styled as previous) */
                        li {
                          color: blue;
                        }
                        
                        /* the item i want to distinguish */
                        li.milk {
                          color: red;
                        }
                        
                        /* next items */
                        li ~ li  {
                          color: green;
                        }
                        
                        
                        <ul>
                          <li>Tea</li>
                          <li class="milk">Milk</li>
                          <li>Juice</li>
                          <li>others</li>
                        </ul>
                        

                        希望它可以帮助某人。

                      【讨论】:

                      • 这与来自同一线程的旧答案基本相同:stackoverflow.com/a/27993987/717732
                      • 但与另一个不同,这个麻烦解释它在做什么。
                      • @Teepeemm,我同意。我看到了那个答案,我跳过了它,因为没有很好的解释。只是“看看我做了什么,然后复制我!”
                      【解决方案23】:

                      这是类似问题的链接

                      CSS select all previous siblings for a star rating

                      因此,我使用每个人的回复发布我的解决方案,任何人都可以将其用作参考并可能提出改进建议。

                      // Just to check input value
                      // Consts
                      const starRadios = document.querySelectorAll('input[name="rating"]');
                      
                      // EventListeners
                      starRadios.forEach((radio) => radio.addEventListener('change', getStarRadioValue));
                      
                      // Get star radio value
                      function getStarRadioValue(event) { 
                          alert(event.target.value) 
                          // Do something with it
                      };
                      .star-rating {
                        font-size: 1.5rem;
                        unicode-bidi: bidi-override;
                        direction: rtl;
                        text-align: left;
                      }
                      .star-rating.editable label:hover {
                        cursor: pointer;
                      }
                      .star-rating.editable .icon-star:hover,
                      .star-rating.editable .icon-star:hover ~ .icon-star {
                        background-color: #fb2727 !important;
                      }
                      
                      .icon-star {
                        position: relative;
                        background-color: #72747d;
                        width: 32px;
                        height: 32px;
                        display: inline-block;
                        transition: background-color 0.3s ease;
                      }
                      .icon-star.filled {
                        background-color: #fb2727;
                      }
                      
                      .icon-star > label {
                        display: inline-block;
                        width: 100%;
                        height: 100%;
                        left: 0;
                        top: 0;
                        position: absolute;
                      }
                      
                      .icon-star > label > input[type="radio"] {
                        position: absolute;
                        top: 0;
                        left: 0;
                        transform: translateY(50%) translateX(50%);
                        display: none;
                      }
                      <div class="star-rating editable">
                        <span class="icon-star">
                          <label>
                            <input type="radio" name="rating"  value="5" />
                          </label>
                        </span>
                        <span class="icon-star">
                          <label>
                            <input type="radio" name="rating" value="4" />
                          </label>
                        </span>
                        <span class="icon-star">
                          <label>
                            <input type="radio" name="rating" value="3" />
                          </label>
                        </span>
                        <span class="icon-star">
                          <label>
                            <input type="radio" name="rating" value="2" />
                          </label>
                        </span>
                        <span class="icon-star">
                          <label>
                            <input type="radio" name="rating"  value="1" />
                          </label>
                        </span>
                      </div>

                      【讨论】:

                        【解决方案24】:

                        对于我的用例,需要在焦点上更改以前的元素样式并悬停在父元素中只有 2 个项目。这样做使用了:focus-within:hover 伪类。

                        就像这样在发生焦点/悬停事件时选择

                        .root-element:hover .element-to-style { background-color: red;} 
                        .root-element:focus-within .element-to-style { background-color: green;} 
                        <div class="root-element">
                        <span class="element-to-style"> TextFocused</span>
                        <input type="text" placeholder="type To Style"/>
                        
                        </div>

                        【讨论】:

                        • 这个答案对我来说是行不通的!
                        【解决方案25】:

                        我遇到了同样的问题,当我尝试更改输入焦点上的前置图标填充颜色时,我的代码看起来像这样:

                        <template #append>
                            <b-input-group-text><strong class="text-danger">!</strong></b-input-group-text>
                        </template>
                        <b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />
                        

                        问题是我正在使用vue-bootstrap 投币口注入前置,所以即使我改变位置仍然会在输入后呈现

                        好吧,我的解决方案是滑动他们的位置,并添加自定义前置和使用 ~ 符号,因为 css 不支持以前的兄弟姐妹。

                        <div class="form-input-prepend">
                            <svg-vue icon="common.lock" />
                        </div>
                        <b-form-input id="password_confirmation" v-model="form.password_confirmation" type="password" placeholder="Repeat password" autocomplete="new-password" />
                        

                        样式

                        .form-control:focus ~ .form-input-prepend {
                            svg path {
                                fill: $accent;
                            }
                        }
                        

                        所以只是尝试改变它的位置,如果有必要使用 css命令或者位置:绝对;实现你想要的,并避免使用 javascript 来满足这种需求。

                        【讨论】:

                          【解决方案26】:

                          我通过将元素放入 flexbox 中然后使用flex-direction: column-reverse 解决了这个问题。

                          然后我不得不手动反转 HTML 中的元素(以相反的顺序放置它们),它看起来很正常并且有效!

                          <div style="display: flex; flex-direction: column-reverse">
                            <a class="element2">Element 2</a>
                            <a class="element1">Element 1</a>
                          </div>
                          ...
                          <style>
                            .element2:hover + element1 {
                              ...
                            }
                          </style>
                          

                          【讨论】:

                            猜你喜欢
                            • 2022-05-30
                            • 2011-01-09
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多