关于css:是否有“前兄弟”选择器?

Is there a “previous sibling” selector?

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

以前的兄弟姐妹是否有同等效力?


不,没有"以前的兄弟"选择器。

在相关的说明中,~用于一般后继兄弟(意思是该元素在此之后,但不一定紧接在之后)并且是CSS3选择器。 +用于下一个兄弟,是CSS2.1。

请参阅级联样式表级别2修订版1(CSS 2.1)规范中的选择器级别3和5.7相邻同级选择器的相邻同级组合器。


我找到了一种方法来设置所有以前的兄弟姐妹(与~相对)的风格,这取决于你需要什么。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 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;
}
1
2
3
4
5
  link
  link
  link
  link
  link


选择器级别4引入:has()(以前是主题指示符!),这将允许您选择以前的兄弟:

1
previous:has(+ next) {}

...但在撰写本文时,浏览器支持已超出前沿。


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

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

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

特别是,flex order属性可以在屏幕周围移动元素。

这是一个例子:

You want element A to turn red when element B is hovered.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul>

   
<li>
A
</li>

   
<li>
B
</li>


</ul>

脚步

  • 使ul成为一个flex容器。

    1
    ul { display: flex; }
  • 在标记中反转兄弟姐妹的顺序。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <ul>

       
    <li>
    B
    </li>

       
    <li>
    A
    </li>


    </ul>
  • 使用同级选择器来定位元素A(~+将执行)。

    1
    li:hover + li { background-color: red; }
  • 使用flex order属性可以在可视显示上恢复兄弟节点的顺序。

    1
    li:last-child { order: -1; }
  • ......瞧!先前的兄弟选择器诞生(或至少模拟)。

    这是完整的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <ul>

       
    <li>
    B
    </li>

       
    <li>
    A
    </li>


    </ul>

    来自flexbox规范:

    5.4. Display Order: the order property

    Flex items are, by default, displayed and laid out in the same order as they appear in the source document. The
    order property can be used to change this ordering.

    The order property controls the order in which flex items appear within the flex container, by assigning them to ordinal groups. It takes a single value, which specifies which ordinal group the flex item
    belongs to.

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

    另请参阅CSS网格布局规范中的order

    使用flex order属性创建的"previous sibling selectors"的示例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    .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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <p>

    Using the flex <wyn>order</wyn> property to construct a previous sibling selector

    </p>


        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>HOVER ME</span>
        <span>4</span>





        <span>HOVER ME</span>
        <span>HOVER ME</span>
        <span>6</span>
        <span>7</span>
        <span>8</span>
        <span>10</span>
        <span>11</span>





        <span>HOVER ME</span>
        <span>13</span>
        <span>14</span>
        <span>15</span>
        <span>16</span>
        <span>17</span>
        <span>18</span>
        <span>19</span>
        <span>20</span>

    的jsfiddle

    一个侧面注意关于CSS的两个过时的信念

    Flexbox打破了人们对CSS的长期信念。

    一个这样的信念是CSS中不可能使用先前的兄弟选择器。

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

    • 使用选择器在CSS中选择元素的前一个兄弟
    • CSS:选择以前的兄弟姐妹
    • CSS选择以前的兄弟姐妹
    • CSS中的上一个相邻选择器
    • 在悬停时选择以前的兄弟姐妹
    • 获得前面兄弟的CSS选择器
    • 使用CSS更改悬停时兄弟元素的颜色
    • 如何使用selenium css语法选择以前的兄弟
    • CSS Selector用于选择另一个元素之前的元素?
    • 如何仅使用CSS将样式添加到活动输入上一个兄弟
    • 下一个和前一个元素的CSS选择器
    • 当div悬停时如何影响其他元素

    如上所述,这种看法并不完全正确。可以使用flex order属性在CSS中模拟先前的兄弟选择器。

    z-index神话

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

    实际上,W3C编辑器草案的最新版规范仍然断言这是真的:

    9.9.1 Specifying the stack level: the z-index
    property

    z-index

    • Value: auto | | inherit
    • Initial: auto
    • Applies to: positioned elements
    • Inherited: no
    • Percentages: N/A
    • Media: visual
    • Computed value: as specified

    (emphasis added)

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

    即使positionstatic,作为弹性项目或网格项目的元素也可以创建堆叠上下文。

    4.3. Flex Item Z-Ordering

    Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw
    document order, and z-index values other than auto create a stacking context even if position is static.

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

    The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is
    used in place of raw document order, and z-index values other than auto create a stacking context even if
    position is static.

    以下是z-index对非定位弹性项目的演示:https://jsfiddle.net/m0wddwxs/


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

    1
    x ~ y

    1
    y ~ x

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

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


    两招。基本上反转HTML中所需元素的HTML顺序并使用
    ~下一个兄弟姐妹运营商:

    float-right +逆转HTML元素的顺序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    div{ /* Do with the parent whatever you know just to make the
      inner float-right elements appear where desired */

      display:inline-block;
    }
    span{
      float:right;  /* float-right the elements! */
    }
    span:hover ~ span{ /* On hover target it's"previous";) elements */
      background:red;
    }
    1
    2
    3
    4
    5
    6
      <!-- Reverse the order of inner elements -->
      <span>5</span>
      <span>4</span>
      <span>3</span>
      <span>2</span>
      <span>1</span>

    direction: rtl; +逆内元素的顺序

    1
    2
    3
    4
    5
    6
    7
    .inverse{
      direction: rtl;
      display: inline-block; /* inline-block to keep parent at the left of window */
    }
    span:hover ~ span{ /* On hover target it's"previous";) elements */
      background:gold;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Hover one span and see the previous elements being targeted!


      <!-- Reverse the order of inner elements -->
      <span>5</span>
      <span>4</span>
      <span>3</span>
      <span>2</span>
      <span>1</span>


    + is for the next sibling. Is there an equivalent for the previous
    sibling?

    您可以使用两个轴选择器:!?

    常规CSS中有2个后续兄弟选择器:

    • +是紧接着的后续兄弟选择器
    • ~是任何后续的兄弟选择器

    在传统的CSS中,没有先前的兄弟选择器。

    但是,在ax CSS后处理器库中,有2个先前的兄弟选择器:

    • ?是前一个兄弟选择器(与+相对)
    • !是任何先前的兄弟选择器(与~相对)

    工作实例:

    在下面的示例中:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Hover over any of the blocks below




    Hover for <wyn>?</wyn> selector
    Hover for <wyn>!</wyn> selector
    Hover for <wyn>~</wyn> selector
    Hover for <wyn>+</wyn> selector




    <script src="https://rouninmedia.github.io/axe/axe.js">


    另一个flexbox解决方案

    您可以使用HTML中的元素顺序。然后除了在Michael_B的答案中使用order之外,您可以使用flex-direction: row-reverse;flex-direction: column-reverse;,具体取决于您的布局。

    工作样本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    .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%;
    }
    1
    2
    3
    4
    5
      5
      4
      3
      2
      1


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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #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;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <p>
    The oranges elements are the previous sibling li selected using li:nth-child(-n+4)
    </p>


      <span>1</span><!-- this will be selected -->
      <p>
    2
    </p><!-- this will be selected -->
      <p>
    3
    </p><!-- this will be selected -->
      4<!-- this will be selected -->
      5
      <p>
    6
    </p>
      <p>
    7
    </p>
      <p>
    8
    </p>
      <p>
    9
    </p>

    限制

    • 您无法根据下一个元素的类选择以前的元素
    • 伪类也是如此


    如果你知道确切的位置,那么基于:nth-child()的所有兄弟姐妹的排除都会起作用。

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

    哪个会在第3个之前选择所有li(例如第1个和第2个)。但是,在我看来,这看起来很丑陋并且使用非常紧凑。

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

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

    哪个也一样。


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

    在我的情况下,我想要一个主要的CSS 5星评级系统。我需要为之前的星星着色(或交换图标)。通过向右浮动每个元素,我基本上得到了相同的效果(因此必须将'html代表星''向后'写入。

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

    CSS:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    .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/


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

    说我们有:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <ul>

       
    <li>
    Pants
    </li>

       
    <li>
    Socks
    </li>

       
    <ul>

         
    <li>
    White socks
    </li>

         
    <li>
    Blue socks
    </li>

       
    </ul>

     
    </ul>

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

    什么会好但不存在:

    1
    2
    3
    4
    ul li ul:parent {
      margin-top: 15px;
      margin-bottom: 15px;
    }

    存在什么:

    1
    2
    3
    4
    5
    6
    7
    li > a {
      margin-top: 15px;
      display: block;
    }
    li > a:only-child {
      margin-top: 0px;
    }

    这将所有锚链接设置为在顶部具有15px边距,并且对于在LI内没有UL元素(或其他标记)的那些将其重置为0。


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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    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;
        }
    `;

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

  • 给你所有的项目一个风格。
  • 为您选择的项目添加样式。
  • 使用+或?为下一个项目添加样式。
  • 这样你就可以设置当前的前一个项目(所有被当前和下一个项目覆盖的项目)和下一个项目的样式。

    例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    /* 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>

    希望它可以帮助某人。


    不可以。通过CSS无法实现。它需要"级联";-)。

    但是,如果您能够在页面中添加JavaScript,那么一些jQuery可以帮助您实现最终目标。
    您可以使用jQuery的find对目标元素/ class / id执行"预见",然后回溯以选择目标。
    然后使用jQuery重新编写元素的DOM(CSS)。

    根据Mike Brant的回答,
    以下jQuery代码段可以提供帮助。

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

    这首先选择紧跟

    的所有


      然后它"回溯"以从该组

        中选择所有先前的

        实际上,已经通过jQuery选择了"以前的兄弟姐妹"。
        现在,使用.css函数传递该元素的CSS新值。

        在我的情况下,我希望找到一种方法来选择ID为#full-width的DIV,但只有它有一个(间接的)后代DIV,其类为.companies

        我控制了.companies下的所有HTML,但无法改变它上面的任何HTML。
        级联仅向一个方向发展:向下。

        因此我可以选择ALL #full-width s。
        或者我可以选择只跟随#full-width.companies
        但我不能只选择继续.companies#full-width

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

        但是使用jQuery,我可以选择所需的#full-width,然后分配合适的样式:

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

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

        1
        $(".parent").find(".change-parent").parents(".parent").css("background-color","darkred");
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        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;
        }
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
        <html>


         
           "parent" turns red
           
            descendant:"change-parent"
           
         
         
         
           "parent" stays green
           
            descendant:"nope"
           
         
         

        Target"<span style="color:darkgreen">parent</span>" to turn <span style="color:red">red</span>.
        Only if it has a descendant of"change-parent".

        (reverse cascade, look ahead, parent un-descendant)
        </html>

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