是否有一个 “以前的兄弟” 选择器?

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

以前的兄弟姐妹有同等学历吗?

答案

不,没有 “先前的兄弟” 选择器。

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

看到相邻的兄弟组合子选择器 3 级5.7 相邻同胞选择层叠样式表级别 2 版本 1(CSS 2.1)规范

我找到了一种样式来设置所有以前的兄弟姐妹(与~相对)的方法,具体取决于您的需要。

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

/* 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>

选择器级别 4 引入了:has() (以前是主题指示器! ),它允许您使用以下选项选择先前的同级:

previous:has(+ next) {}

… 但是在撰写本文时,它离浏览器支持的极限还有一段距离。

考虑 flex 和 grid 布局的order属性。

在下面的示例中,我将重点介绍 flexbox,但是相同的概念也适用于 Grid。


使用 flexbox,可以模拟先前的同级选择器。

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

这是一个例子:

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

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

脚步

  1. 使ul为 flex 容器。

    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。显示订单: order属性

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

order属性通过将弹性项目分配给顺序组来控制其在弹性容器中的显示顺序。它采用单个<integer>值,该值指定弹性项目所属的顺序组。

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

另请参阅CSS Grid Layout 规范中的order


使用 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 的信念。

一种这样的信念是, 在 CSS 中不可能有以前的兄弟选择器

要说这种信念很普遍,那就轻描淡写了。这是仅有关堆栈溢出的相关问题的样本:

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

z-index神话

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

实际上,该规范的最新版本– W3C 编辑器的草案 –仍然认为这是正确的:

9.9.1 指定堆栈级别: z-index属性

z-index

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

(强调)

但是,实际上,此信息已过时且不准确。

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

4.3。弹性项目 Z 排序

Flex 项的绘制与内联块完全相同,不同之处在于,使用经顺序修改的文档顺序代替原始文档顺序,并且即使positionstaticz-index值( auto创建以外的其他z-index值)也会创建堆叠上下文。

5.4。 Z 轴排序: z-index属性

网格项目的绘制顺序与嵌入式块完全相同,不同之处在于,使用顺序修改后的文档顺序代替原始文档顺序,并且即使positionstaticz-index值也会auto创建堆叠上下文,而不是auto创建堆叠上下文。

这是z-index在未定位的弹性项目上工作的演示: https : //jsfiddle.net/m0wddwxs/

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

x ~ y

y ~ x

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

我意识到原来的问题是 CSS 问题,因此该答案可能完全不相关,但是其他 Javascript 用户可能会像我一样通过搜索偶然发现该问题。

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

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

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;
}
<div>
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>


家长direction: rtl; + 反转内部元素的顺序

.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;
}
Hover one span and see the previous elements being targeted!<br>

<div class="inverse">
  <!-- Reverse the order of inner elements -->
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>

+是下一个兄弟姐妹。以前的兄弟姐妹有同等学历吗?

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

常规 CSS 中有2 个 后续的同级选择器

  • +紧邻的后续兄弟选择
  • ~任何后续的同级选择器

在常规 CSS 中, 没有先前的兄弟选择器

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

  • ?立即前一个兄弟选择器(的相对+
  • !任何先前的同级选择器( ~对面)

工作示例:

在下面的示例中:

  • .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>

另一种 flexbox 解决方案

您可以使用相反的 HTML 元素顺序。然后除了像Michael_B 的答案那样使用order之外,还可以使用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>

目前尚无官方方法可以执行此操作,但是您可以使用一些技巧来实现此目的!请记住,这是实验性的,并且有一定的局限性...(如果您担心导航器的兼容性,请查看此链接

您可以做的是使用 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()的方式排除以下所有同级物品。

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

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

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

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

哪个也一样。