CSSの以前の兄弟セレクターとそれらを偽装する方法

CSS兄弟セレクターを使用したことがある場合、2つしかないことを知っています。 +兄弟コンビネータは直後に来る最初の一致を選択し、〜後続兄弟コンビネータは後に来るすべての一致を選択します。
しかし、以前のものを選択する方法はありません。親セレクターまたは前の兄弟セレクターのいずれかは、単にものではありません。

私はあなたがそれを望んでいることを知っています、あなたは私がそれを望んでいることを知っていますが、厳しい真実はそれらが存在しないということです(そしておそらく決してないでしょう)。理由についての投稿は100万件あります。それらの実装方法に関する提案もあります。しかし、CSSルールの単方向処理に固執しているため、「専門知識の欠如」からリフローや無限ループに陥る可能性が最も高くなります。

幸いなことに、ほとんどのCSSの制限と同様に、私たちはそれを偽造できます。

最初に考慮すべきことは、なぜ以前の兄弟を始めたいのかということです。
2つのケースが思い浮かびます。

  1. 特定の要素のすべての兄弟を選択する必要があり、〜後続の兄弟コンビネータは後に来るもののみを選択します。
  2. 前に来た兄弟だけを選択する必要があります

1.すべての兄弟を選択する

時々、前の兄弟と次の兄弟の両方を選択する必要があります。そのために、実際に親を選択し、その周りにいくつかのトリックを使用できます。

たとえば、いずれかのホバー時に次の構造のすべてのスパンを選択するには、親のホバーで子セレクターを使用するだけです。親からのポインターイベントを必ず無効にし、子でリセットします。したがって、実行したいアクションは、親自体ではなく子を入力したときにのみ発生します。

ホバーされている兄弟を除くすべての兄弟を選択する必要がある場合は、前の手法と:notセレクターを組み合わせて除外できます。

これの典型的な使用例はメニューです:

上記のコードは、ホバリングされている要素を除くすべての

  • 要素の不透明度を下げます。

    さらに、タイプやn番目のセレクターなどのフィルターを使用して、影響を与えたい兄弟をさらに正確にすることができます。

    いくつかのスタイリングを使用すると、次のように機能します。

    注:pointer-events:noneアプローチを実行する場合は、スタックが混乱する可能性があることに注意してください(スタック順で「下」にある要素を選択できる場合があります)。また、IE10以下では動作しません。他の何かのためにポインターイベントが必要になる可能性があるという意味は別です。そのため、使用するときは特に注意してください。

    2.以前のものを選択する

    このユースケースでは、HTMLの順序を逆にしてから、CSSで並べ替え、〜後続の兄弟コンビネーターまたは+隣接する兄弟セレクターを使用できます。この方法では、次の兄弟を選択しますが、前の兄弟を選択しているように見えます。

    これを行うには複数の方法があります。最も単純でおそらく最も古いものは、コンテナの書き込み方向を変更することです。

    要素に実際のテキストを表示する必要がある場合は、いつでも元に戻すことができます。

    しかし、それは多くの方法で手に負えないことができます。幸いなことに、最新のCSSツールボックスにより、はるかに簡単かつ安全になりました。コンテナでFlexboxを使用し、flex-direction:row-reverseで順序を逆にするだけです。

    Flexboxのアプローチの最大の利点は、執筆の方向を混乱させないことです。子供をリセットする必要はありません。すべてがより予測可能です。

    「前の兄弟」を使用してCSSのみの星評価システムを作成する

    意味的には、評価システムは、ラジオボタンとそれに対応するラベルの単純なリストと考えることができます。 :checked疑似セレクターを使用して兄弟を変更できるため、これは便利です。

    そこから始めましょう:

    前述したように、要素は「前の兄弟」セレクターを許可するために逆の順序になっています。ユニコードの「白い星」文字(U + 2606)を使用して空の星を表していることに注意してください。

    それらを正しい(逆の)順序で並べて表示しましょう:

    ラジオボタン自体を非表示にします。誰もそれを見たくありません。

    そして、スターキャラクターにスタイリングを適用します。

    唯一の本当に重要な行はposition:relativeです。これにより、最初は非表示になる、塗りつぶされた星(U + 2605)擬似要素をその上に絶対配置できます。

    星にカーソルを合わせると、塗りつぶされた星の擬似要素がその星と以前の兄弟すべてに対して表示されるようになります。

    選択した評価についても同じです。チェックされたラジオボタンの前にあるすべてのラベルを一致させます。

    !importantフラグを使用することは、優れたプラクティスの正反対であることを忘れないでください。次のセクションで説明する追加機能をそれなしで実現する方法は他にないため、ここで行います。

    最後になりましたが、ユーザーが変更したい場合に備えて、現在の評価を「記憶」する必要があります。たとえば、5つの星を選択し、何らかの理由で4に変更したい場合、星4の上にホバーするときに星1から4を塗りつぶし、5番目を半​​透明として表示する必要があります。

    これは、コンテナにカーソルを合わせたときに、チェックされた入力の前の兄弟の不透明度を変更することで実現できます。

    それが、最初のホバリング宣言で不透明度1!importantが必要だった理由でもあります。そうでなければ、この最後のルールが特異性コンテストで勝ち、すべてに半透明の塗りつぶしを適用することになります。

    そして、「前の兄弟」セレクターを使用した、クロスブラウザー、完全に機能するCSSのみの星評価システムがあります。

    ご覧のとおり、「不可能」だからといって、試してはいけないという意味ではありません。プログラミングとは、限界を押し広げることです。そのため、壁にぶつかるたびに、少し強く押してください。それとも、それを回避する方法を見つけることは、より良い類推かもしれないと思う?ハッキングを続けてください!

    アクセシビリティに関する注意

    前のスニペットは、わかりやすくするための簡略化です。多くのアクセシビリティの制限があるため、本番環境で使用することはお勧めできません。

    スニペットをもう少しアクセスしやすくするために、まず、display:none以外のほとんどの方法でラジオボタンを非表示にしてフォーカス可能にします。また、疑似セレクター:focus-withinを使用して、内部の要素がフォーカスされたときに星のスニペット全体にフォーカスリングを追加する必要があります。

    同一の「☆」ラベルはスクリーンリーダーには意味がないため、ラベル内に「n Stars」テキストを含むを用意することをお勧めします。

    また、リバースHTMLソース+ display:row-reverseアプローチでは、キーボードレーティングがリバースされないため、キーボードレーティングが扱いにくくなります。 Flexboxとキーボードのアクセシビリティは非常に厄介なトピックですが、その解決策に最も近いのは各要素にaria-flowtotagを追加することです。これにより、少なくとも一部のスクリーンリーダーとブラウザの組み合わせの問題が修正されます。

    以下の回答で説明したように、よりアクセスしやすいスニペット(前の兄弟を評価する代わりに、次の兄弟を変更して空に見える代替手法を使用する)については、Patrick Coleを確認してください。