web-dev-qa-db-ja.com

「前の兄弟」CSSセレクターはありますか?

プラス記号(+)は次の兄弟のためのものです。前の兄弟のための同等物はありますか?

1177
Jourkey

いいえ、「前の兄弟」セレクターはありません。

これに関連して、~は一般的な後継兄弟のためのもので(この要素の後に来ることを意味しますが、必ずしも直後ではありません)、CSS3セレクターです。 +は次の兄弟のためのもので、CSS2.1です。

隣接兄弟コンビネータ from セレクタレベル3 および 5.7隣接兄弟セレクタ from カスケードスタイルシートレベル2リビジョン1(CSS 2.1)仕様 を参照。

740
cletus

私はあなたが必要とするものに依存して動作するかもしれない(~の反対)すべての以前の兄弟をスタイルする方法を見つけました。

あなたがリンクのリストを持っていて、その上にホバリングすると、前のリンクはすべて赤に変わるはずです。あなたはこれのようにそれをすることができます:

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

セレクタレベル4では:has() (以前はサブジェクトインジケータ!)が導入されました。これを使うと以前の兄弟を選択することができます。

previous:has(+ next) {}

…しかし、これを書いている時点では、ブラウザサポートに関しては最先端のEdgeを超える距離があります。

141
Quentin

Flexおよびgridレイアウトのorderプロパティを検討してください。

以下の例ではflexboxに焦点を当てますが、同じ概念がグリッドに適用されます。


フレックスボックスを使用すると、以前の兄弟セレクターをシミュレートできます。

特に、flex orderプロパティは、画面内で要素を移動できます。

以下に例を示します。

要素Bをホバーすると、要素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プロパティ

デフォルトでは、Flexアイテムは、ソースドキュメントに表示されるのと同じ順序で表示およびレイアウトされます。 orderプロパティを使用して、この順序を変更できます。

orderプロパティは、フレックスアイテムを順序グループ​​に割り当てることにより、フレックスコンテナ内に表示されるフレックスアイテムの順序を制御します。単一の<integer>値を取ります。これは、Flexアイテムが属する順序グループ​​を指定します。

すべてのflexアイテムのorderの初期値は0です。

CSSグリッドレイアウト仕様の 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に関する2つの古い信念

Flexboxは、CSSに関する長年の信念を打ち砕いています。

そのような考えの1つは、 CSS で以前の兄弟セレクターを使用できないことです。

この信念が広まっていると言うのは控えめな表現です。 Stack Overflowのみに関連する質問のサンプルを次に示します。

上記のように、この信念は完全に真実ではありません。以前の兄弟セレクターは、CSSでflex orderプロパティを使用してシミュレートできます。

z-index神話

もう1つの長年の信念は、z-indexは配置された要素に対してのみ機能するというものです。

実際、最新バージョンの仕様である W3C Editor's Draft は、これが真実であることを主張しています。

9.9.1スタックレベルの指定:z-indexプロパティ

z-index

  • 値:auto | |受け継ぐ
  • 初期:自動
  • 適用対象:配置された要素
  • 継承:no
  • パーセンテージ:N/A
  • メディア:ビジュアル
  • 計算値:指定どおり

(強調を追加)

しかし、実際には、この情報は時代遅れで不正確です。

flex items または グリッド項目 は、positionstaticの場合でもスタッキングコンテキストを作成できます。

4.3。FlexアイテムのZオーダー

Flexアイテムは、インラインブロックとまったく同じようにペイントします。ただし、未処理のドキュメント順序の代わりに順序が変更されたドキュメント順序が使用され、auto以外のz-index値は、positionstaticであってもスタックコンテキストを作成します。

5.4。Z軸の順序:z-indexプロパティ

グリッド項目の描画順序はインラインブロックとまったく同じです。ただし、未処理の文書順序の代わりに順序が変更された文書順序が使用され、auto以外のz-index値はpositionstaticであってもスタックコンテキストを作成します。

以下は、z-indexが非位置指定フレックスアイテムで動作するデモです。 https://jsfiddle.net/m0wddwxs/

134
Michael_B

私は同じ質問をしましたが、それから私は「当たり前」の瞬間を過ごしました。書く代わりに

x ~ y

書きます

y ~ x

明らかにこれは "y"ではなく "x"と一致しますが、 "一致はありますか?"と答えます。単純なDOMトラバーサルは、JavaScriptでループするよりも効率的に正しい要素にたどり着く可能性があります。

元の質問はCSSの質問であったため、この回答はおそらくまったく無関係ですが、他のJavascriptユーザーは私が行ったように検索を介して質問に出くわすかもしれません。

66
Bryan Larsen

2つの トリック 。基本的に、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>
24
Roko C. Buljan

+は次の兄弟のためのものです。前の兄弟のための同等物はありますか?

!?の2つの ax セレクターを使用できます。

従来のCSSでは、 2 後続の兄弟セレクタ があります。

  • + すぐ近くの に続く兄弟セレクタです
  • ~ any 後続の兄弟セレクタです

従来のCSSでは、 以前の兄弟セレクタはありません

ただし、 ax CSSポストプロセッサライブラリには、 2 以前の兄弟セレクタ があります。

  • ? immediate 前の兄弟セレクタです(+の反対)
  • ! any 前の兄弟セレクタです(~の反対)

作業例:

以下の例では:

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

別のフレックスボックスソリューション

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>
15

現時点ではそれを行うための公式の方法はありませんが、これを達成するために少しトリックを使うことができます!これは実験的なものであり、いくつかの制限があります...(ナビゲーターの互換性が心配な場合は このリンク を確認してください)

あなたができることは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>

制限事項

  • 次の要素のクラスに基づいて前の要素を選択することはできません
  • これは疑似クラスでも同じです
14
0x1gene

正確な位置を知っていれば、後続のすべての兄弟を:nth-child()ベースで除外することでうまくいきます。

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

これは、3番目より前のすべてのliを選択します(例:1と2)。しかし、私の意見ではこれは醜く見え、非常に狭い使用例があります。

右から左にn番目の子を選択することもできます。

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

どちらも同じです。

4
kernel

残念ながら「以前の」兄弟セレクタはありませんが、 おそらく を使用しても同じ効果を得ることができます(例:float right)。それはあなたがやろうとしていることによります。

私の場合、私は主にCSS 5つ星評価システムを望んでいました。前の星に色を付ける(またはアイコンを交換する)必要があります。それぞれの要素を正しく浮動させることによって、私は本質的に同じ効果を得ています(したがって、星のhtmlは '後方'に書かれなければなりません)。

この例ではFontAwesomeを使用していて、fa-star-oとfa-starのユニコードを交換しています 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/

2
Andrew Leyva

実際の目的によっては、親セレクタを使用せずに(存在していたとしても)親セレクタの有用性を実現する方法があります。

たとえば、

<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のマージンを持つように設定し、LI内にUL要素(または他のタグ)がないものについては0にリセットします。

1
DynamicDan

私は同様の問題を抱えていて、この種の問題はすべて次のように解決できることを発見しました。

  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>

誰かに役立つことを願っています。

1
Hejar

いいえ。CSS経由ではできません。それは心に「カスケード」を取ります;-)。


ただし、JavaScriptをページに追加できる場合は、jQuery目標を達成できます。
jQueryのfindを使用して、ターゲット要素/クラス/ IDの「先読み」を実行し、バックトラックしてターゲットを選択できます。
次に、jQueryを使用して、要素のDOM(CSS)を書き換えます。

マイクブラントによるこの回答 に基づいて、次のjQueryスニペットが役立ちます。

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

これは、最初に<ul>の直後にあるすべての<p>を選択します。
次に、<p>sのセットから以前の<ul>sをすべて選択するために「バックトラック」します。

事実上、jQueryを介して「前の兄弟」が選択されています。
次に、.css関数を使用して、CSSでその要素の新しい値を渡します。


私の場合、#full-widthというIDを持つDIVを選択する方法を探していましたが、.companiesのクラスを持つ(間接的な)子孫DIVがある場合のみです。

.companiesの下ですべてのHTMLを制御できましたが、その上のHTMLを変更できませんでした。
そして、カスケードは1方向のみに進みます。

したがって、すべての#full-widthsを選択できます。
または.companiesの後にのみ続く#full-widthを選択できます。
しかし、not#full-widthsproceded.companiesのみを選択できました。

また、HTMLの上位に.companiesを追加できませんでした。 HTMLのその部分は外部で記述され、コードをラップしました。

しかし、jQueryでは、Ican必要な#full-widthsを選択してから、適切なスタイルを割り当てます。

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

これにより、すべての#full-width .companiesが検出され、それらの.companiesのみが選択されます。これは、CSSの標準で特定の要素をターゲットにするためにセレクターが使用される方法と同様です。
次に、.parentsを使用して「バックトラック」し、.companiesのすべての親を選択します。
ただし、それらの結果をフィルタリングして#fill-width要素のみを保持するため、最終的には、
#full-widthクラスの子孫がある場合、.companies要素のみを選択します。
最後に、結果の要素に新しい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リファレンスドキュメント:
$()またはjQuery() :DOM要素。
find :一致する要素の現在のセット内の各要素の子孫を取得します。セレクタ、jQueryオブジェクト、または要素。
parents :一致した要素のセット内の各要素の直前の兄弟を取得します。セレクターが提供される場合、そのセレクターと一致する場合にのみ前の兄弟を取得します(リストされた要素/セレクターのみを含むように結果をフィルターします)。
css :一致した要素のセットに1つ以上のCSSプロパティを設定します。

0
SherylHohman

前の兄弟trを選択するための解決策が必要でした。私はReactとStyledコンポーネントを使ってこの解決策を思いつきました。これは私の正確な解決策ではありません(これは数時間後のメモリからのものです)。 setHighlighterRow関数に欠陥があることを私は知っています。

OnMouseOver行は行インデックスをstateに設定し、前の行を新しい背景色で再描画します。

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;
    }
`;
0
kyle