Gibt es einen Selektor für frühere Geschwister?

1355

Das Pluszeichen ( +) steht für das nächste Geschwister.

Gibt es ein Äquivalent für das vorherige Geschwister?

Jourkey
quelle
18
OMG, alle Antworten hier, die darauf hindeuten, dass Sie die Reihenfolge der HTML-Elemente umkehren und dann CSS verwenden, um sie rückwärts erscheinen zu lassen, sind eine echte Strecke. Sicher, es wird in der Frage nicht angegeben , aber die meisten Fragen zu "Können Sie X mit CSS ausführen" sollten davon ausgehen, dass Sie den HTML-Code nicht strukturell ändern können.
Squarecandy
3
@squarecandy, ich stimme Ihrem Kommentar größtenteils zu. Die Lösungen, die Sie als unzureichend bezeichnen, sind jedoch in einigen Fällen dennoch nützlich (beachten Sie die positiven Stimmen). Es lohnt sich also, sie zu veröffentlichen. Was Sie als "echte Strecke" betrachten, kann für andere eine "kreative Lösung" sein.
Michael Benjamin

Antworten:

839

Nein, es gibt keinen Selektor für "vorherige Geschwister".

In einem verwandten Hinweis, ~ist für allgemeine Nachfolger Geschwister (dh das Element kommt nach diesem, aber nicht unbedingt unmittelbar danach) und ist ein CSS3-Selektor. +ist für das nächste Geschwister und ist CSS2.1.

Siehe Benachbarter Geschwisterkombinator aus Selektoren Level 3 und 5.7 Benachbarte Geschwisterkombinatoren aus Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) .

Cletus
quelle
14
Aus dem CSS3-Standard: Die durch die beiden Sequenzen dargestellten Elemente haben im Dokumentbaum dasselbe übergeordnete Element, und das durch die erste Sequenz dargestellte Element steht (nicht unbedingt unmittelbar) vor dem durch die zweite dargestellten Element.
Lie Ryan
26
@Lie Ryan: Ja, aber der Punkt, den Cletus in seiner Antwort hervorhebt, ist, dass Sie das vorhergehende Element nicht auswählen .
BoltClock
42
Hier ist ein Beispiel, das ich gemacht habe, um zu sehen, was dies kann und was nicht. jsfiddle.net/NuuHy/1
Abacus
7
Die dafür nützliche jquery-Funktion ist prev (). Zum Beispiel $ ("# the_element"). Prev (). CSS ("Hintergrundfarbe", "rot")
Satbir Kira
1
Abhängig von Ihrem Markup kann dies helfen: stackoverflow.com/questions/42680881/…
samnau
235

Ich habe einen Weg gefunden, alle vorherigen Geschwister (im Gegensatz zu ~) zu stylen, die je nach Bedarf funktionieren können.

Angenommen, Sie haben eine Liste mit Links, und wenn Sie mit der Maus über einen Link fahren, sollten alle vorherigen rot werden. Sie können es so machen:

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

Mantish
quelle
17
Sie können eine Erklärung hinzufügen, wie es funktioniert. (Es scheint, dass Sie einen Stil auf alle Elemente und auf die folgenden Elemente anwenden, aber es kann explizit beschrieben werden)
AL
1
Tolle Lösung. Sie müssen die Elemente weder im Markup noch im Rendering (via float:right) neu anordnen . Es war ein Leerraumkollaps zwischen Einheiten / Wörtern und Auffüllen anstelle von Rändern erforderlich, aber ansonsten funktioniert es einwandfrei!
Steven Vachon
7
ja, aber ein einziger Vorgänger wird die meiste Zeit benötigt, NICHT ALLE vorherigen!
Azerafati
41
Die Links werden alle rot, wenn ich für mich über den Raum zwischen ihnen schwebe.
Lynn
3
@Lynn Die Antwort enthält nur den Code, mit dem die vorherigen Links beim Hover rot angezeigt werden. Zusätzliche Stile hängen von Ihrem Anwendungsfall ab. Für eine Sternebewertungskomponente (was meiner Meinung nach ein häufiger Fall ist) müssten Sie diesen Bereich entfernen und auch den schwebenden Link rot machen.
Mantish
164

Selectors Level 4 führt:has() (früher die Betreff-Anzeige !) ein, mit der Sie ein vorheriges Geschwister auswählen können mit:

previous:has(+ next) {}

… Aber zum Zeitpunkt des Schreibens ist es für die Browserunterstützung ein Stück weit entfernt.

QUentin
quelle
51
"Bleeding Edge für Browser-Unterstützung" könnte eine Übertreibung sein. Zum Zeitpunkt des Schreibens kann nicht einmal die neueste Version von Chrome die :has()Pseudoklasse verwenden.
Reed Martin
33
@ ReedMartin - Deshalb habe ich ein Stück jenseits der Blutungskante
Quentin
12
": has ist nicht als Teil des dynamischen Auswahlprofils markiert, was bedeutet, dass es nicht in Stylesheets verwendet werden kann; nur mit Funktionen wie document.querySelector ()." - developer.mozilla.org/en-US/docs/Web/CSS/:has
Arch Linux Tux
1
@ArchLinuxTux: "Diese Einschränkung wurde jetzt entfernt", daher können wir diese Funktion möglicherweise einmal verwenden: D.
Jacob van Lingen
@JacobvanLingen - caniuse.com/#feat=css-has - Derzeit wird dies von keinem Browser unterstützt.
Quentin
153

Berücksichtigen Sie die orderEigenschaft von Flex- und Rasterlayouts.

Ich werde mich in den folgenden Beispielen auf Flexbox konzentrieren, aber die gleichen Konzepte gelten für Grid.


Mit der Flexbox kann ein vorheriger Geschwister-Selektor simuliert werden.

Insbesondere kann die Flex- orderEigenschaft Elemente auf dem Bildschirm verschieben.

Hier ist ein Beispiel:

Sie möchten, dass Element A rot wird, wenn Sie den Mauszeiger über B halten.

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

SCHRITTE

  1. Machen Sie den uleinen flexiblen Behälter.

    ul { display: flex; }

  1. Kehren Sie die Reihenfolge der Geschwister im Aufschlag um.

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

  1. Verwenden Sie einen Geschwister-Selektor, um auf Element A zu zielen ( ~oder dies zu +tun).

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

  1. Verwenden Sie die Flex- orderEigenschaft, um die Reihenfolge der Geschwister in der visuellen Anzeige wiederherzustellen.

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

... und voilà! Ein früherer Geschwister-Selektor wird geboren (oder zumindest simuliert).

Hier ist der vollständige Code:

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>

Aus der Flexbox-Spezifikation:

5.4. Anzeigereihenfolge: die orderEigenschaft

Flex-Elemente werden standardmäßig in derselben Reihenfolge angezeigt und angeordnet, wie sie im Quelldokument angezeigt werden. Das order Eigenschaft kann verwendet werden, um diese Reihenfolge zu ändern.

Die orderEigenschaft steuert die Reihenfolge, in der Flex-Elemente im Flex-Container angezeigt werden, indem sie Ordnungsgruppen zugewiesen werden. Es wird ein einzelner <integer>Wert verwendet, der angibt, zu welcher Ordnungsgruppe das Flex-Element gehört.

Der Anfangswert orderfür alle Flex-Elemente ist 0.

Siehe auch orderin der CSS Grid Layout-Spezifikation .


Beispiele für "vorherige Geschwisterselektoren", die mit der orderEigenschaft flex erstellt wurden .

.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


Eine Randnotiz - Zwei veraltete Überzeugungen über CSS

Flexbox erschüttert langjährige Überzeugungen über CSS.

Eine solche Überzeugung ist, dass ein früherer Geschwister-Selektor in CSS nicht möglich ist .

Zu sagen, dass dieser Glaube weit verbreitet ist, wäre eine Untertreibung. Hier finden Sie eine Auswahl verwandter Fragen zum Stapelüberlauf:

Wie oben beschrieben, ist dieser Glaube nicht ganz richtig. Ein vorheriger Geschwister-Selektor kann mithilfe der Flex- orderEigenschaft in CSS simuliert werden .

Der z-indexMythos

Ein weiterer langjähriger Glaube war, dass z-indexnur auf positionierten Elementen funktioniert.

Tatsächlich behauptet die aktuellste Version der Spezifikation - der Entwurf des W3C-Editors - immer noch, dass dies wahr ist:

9.9.1 Angeben der Stapelebene: die z-index Eigenschaft

z-index

  • Wert: auto | | erben
  • Initial: auto
  • Gilt für: positionierte Elemente
  • Geerbt: nein
  • Prozentsätze: N / A.
  • Medien: visuell
  • Berechneter Wert: wie angegeben

(Betonung hinzugefügt)

In Wirklichkeit sind diese Informationen jedoch veraltet und ungenau.

Elemente, die flexible Elemente oder Rasterelemente sind, können Stapelkontexte erstellen, selbst wenn dies der Fall positionist static.

4.3. Flex Artikel Z-Bestellung

Flex-Elemente malen genauso wie Inline-Blöcke, außer dass die Reihenfolge der geänderten Dokumente anstelle der Reihenfolge der Rohdokumente verwendet wird und z-indexandere Werte als das autoErstellen eines Stapelkontexts verwendet werden, selbst wenn dies der Fall positionist static.

5.4. Z-Achsen-Reihenfolge: die z-indexEigenschaft

Die Malreihenfolge von Rasterelementen entspricht genau der von Inline-Blöcken, außer dass die Reihenfolge der geänderten Dokumente anstelle der Reihenfolge der Rohdokumente verwendet wird und z-indexandere Werte als das autoErstellen eines Stapelkontexts verwendet werden, selbst wenn dies der Fall positionist static.

Hier ist eine Demonstration der z-indexArbeit an nicht positionierten Flex-Elementen: https://jsfiddle.net/m0wddwxs/

Michael Benjamin
quelle
15
Die orderEigenschaft ist keine Lösung, da sie ausschließlich die visuelle Reihenfolge ändern soll. Daher wird nicht die ursprüngliche semantische Reihenfolge wiederhergestellt, die Sie in HTML ändern müssen, damit diese Problemumgehung funktioniert.
Marat Tanalin
2
@Marat Tanalin: In 90% der Anwendungsfälle funktioniert dies einwandfrei, sofern die Browserunterstützung kein Problem darstellt. Die verbleibenden 10% der Anwendungsfälle sind entweder 1) Fälle, in denen eine Änderung der visuellen Reihenfolge keine Lösung darstellt, oder 2) Fälle, in denen CSS überhaupt nicht zum Einsatz kommt. Zum Glück bietet selectors-4 für # 2: has (), und es liegt einfach an den Entwicklern von Selektorbibliotheken, es zu implementieren.
BoltClock
5
Denken Sie daran, dass die von Ihnen zitierte CSS2.2-ED im Wesentlichen immer noch CSS2 ist. Und Flexbox- und Grid-Layout gibt es in CSS2 nicht. Für CSS2 gelten diese Informationen mit Sicherheit. Zumindest könnte der Text aktualisiert werden, um zu erwähnen, dass der Z-Index möglicherweise auf andere Elementtypen in zukünftigen CSS-Ebenen angewendet wird, genauso wie es heißt, dass andere Eigenschaften einen Stapelkontext wie die Deckkraft herstellen können.
BoltClock
3
Falls mit jemandem Schwierigkeiten zu verstehen , wenn z-indexfunktionieren wird, auch wenn „omg, gibt es keines position, die Spezifikation , das Konzept der Nennungen angegeben!“ Stapel Kontext , der durch schön erklärt diesen Artikel auf MDN
Rogier Spieker
3
@ Michael_B Gern geschehen! Ich habe mich mit vielen Front-Endern befasst, die sich dessen nicht bewusst sind. Eine andere Sache, die ich erwähnen möchte, ist, dass der Faux-Vorgänger-Geschwister-Selektor auch gut funktioniert float: right(oder mit anderen Mitteln, um die Reihenfolge umzukehren, von denen flex/ordernur geringe (geringste?) Nebenwirkungen auftreten). Zwei Geigen ausgepeitscht: Demonstration der float: rightAnnäherung und Demonstrationdirection: rtl
Rogier Spieker
69

Ich hatte die gleiche Frage, aber dann hatte ich einen "duh" Moment. Anstatt zu schreiben

x ~ y

schreiben

y ~ x

Offensichtlich stimmt dies mit "x" anstelle von "y" überein, aber es antwortet mit "Gibt es eine Übereinstimmung?" Frage, und einfache DOM-Durchquerung kann Sie effizienter zum richtigen Element bringen, als in Javascript zu schleifen.

Mir ist klar, dass die ursprüngliche Frage eine CSS-Frage war, daher ist diese Antwort wahrscheinlich völlig irrelevant, aber andere Javascript-Benutzer können über die Suche über die Frage stolpern, wie ich es getan habe.

Bryan Larsen
quelle
18
Ich glaube, das funktioniert, wenn y leicht zu finden ist. Das Problem ist, wenn y nur relativ zu x gefunden werden kann und wenn Sie es umkehren, können Sie y nicht finden, weil Sie zuerst x finden müssen. Dies bezieht sich natürlich auf die Frage, ob y eher dem Geschwister als dem nächsten vorausgeht, kann aber auch dafür gelten, dass y ein nachfolgendes Geschwister ist.
David
19
Du bist ziemlich hart, hart. (Entschuldigung, ich konnte nicht widerstehen.) Der Punkt ist, dass man manchmal nur wissen muss, ob es dich gibt. In anderen Fällen können Sie ": before" verwenden, um etwas zwischen die beiden Elemente zu setzen. Wenn Sie in jQuery einsteigen müssen, ist die Verwendung von find ("y ~ x"). Prev () einfacher als viele Alternativen.
Bryan Larsen
156
Die Idee eines vorherigen Geschwister-Selektors ist, dass er das vorherige Element auswählt. Leider bietet das Umkehren, wie hier beschrieben, diese Funktionalität nicht.
Zenexer
14
Vielen Dank an @Zenexer für die Klarstellung, dass diese Antwort keine tatsächliche Lösung für die ursprüngliche Frage darstellt. Ich begann mich dumm zu fühlen, darüber nachzudenken, wie ich y ~ xmein Problem lösen könnte
Jaime Hablutzel
4
Ich verstehe die Idee hinter dieser Antwort, aber die Begründung in der Antwort macht keinen Sinn. Der Selektor y ~ xantwortet nicht mit "Gibt es eine Übereinstimmung?" Frage, weil die beiden hier angegebenen Selektoren völlig unterschiedliche Bedeutungen haben. Es gibt keine Möglichkeit, y ~ xjemals eine Übereinstimmung zu erzeugen, wenn beispielsweise der Teilbaum gegeben wäre <root><x/><y/></root>. Wenn die Frage lautet "Existiert du?" dann ist der Selektor einfach y. Wenn die Frage lautet: "Existiert y bei einem Geschwister x in einer beliebigen Position?" dann brauchst du beide Selektoren. (Obwohl ich vielleicht gerade nicht picke ...)
BoltClock
25

Zwei Tricks . Grundsätzlich invertieren Sie die HTML-Reihenfolge Ihrer gewünschten Elemente in HTML und verwenden Sie den Operator
~ Nächste Geschwister :

float-right + Kehren Sie die Reihenfolge der HTML-Elemente um

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>


Eltern mit direction: rtl;+ kehren die Reihenfolge der inneren Elemente um

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

Roko C. Buljan
quelle
25

+ist für das nächste Geschwister. Gibt es ein Äquivalent für das vorherige Geschwister?

Sie können die beiden Axt- Selektoren verwenden: !und?

Es gibt 2 nachfolgende Geschwister-Selektoren in herkömmlichem CSS:

  • +ist der unmittelbar nachfolgende Geschwister-Selektor
  • ~ist jede nachfolgende Geschwister Selektor

In herkömmlichem CSS gibt es keinen vorherigen Geschwister-Selektor .

In der Axe CSS-Postprozessorbibliothek gibt es jedoch zwei vorherige Geschwister-Selektoren :

  • ?ist der unmittelbar vorhergehende Geschwister-Selektor (Gegenteil von +)
  • !ist jeder vorherigen Geschwister Selektor (gegenüber ~)

Arbeitsbeispiel:

Im folgenden Beispiel:

  • .any-subsequent:hover ~ div wählt eine beliebige nachfolgende aus div
  • .immediate-subsequent:hover + div wählt die unmittelbar folgende aus div
  • .any-previous:hover ! div wählt eine vorherige aus div
  • .immediate-previous:hover ? div wählt den unmittelbar vorhergehenden aus 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>

Rounin
quelle
3
Dies gibt mir einen Syntaxfehler, wenn ich versuche, ihn auf sass in einem Rails-Projekt zu implementieren.
Alex
25
ax ist ein CSS-Postprozessor. Es wird nicht dieselbe Syntax wie bei CSS-Vorprozessoren wie Sass, Less oder Stylus verwendet.
Rounin
1
@Rounin Würde es Ihnen etwas ausmachen, einige Dokumentationslinks hinzuzufügen? Ich kann keinen Axt -Postprozessor finden.
Dionys
@Dionys - Danke für dein Interesse. ax ist ein Projekt, das ich Ende 2016 gestartet habe, als ich ES2015 nicht kannte und sogar Objekte in JS für mich sehr neu waren. Das GitHub-Repository befindet sich hier: github.com/RouninMedia/axe . Ich möchte unbedingt irgendwann darauf zurückkommen (ich habe auch so genannte Axe-Blades entwickelt, die das CSS-Äquivalent von Javascript-Ereignissen sind), aber ich muss zuerst meine Arbeit an einem anderen Projekt (Codename Ashiva ) abschließen .
Rounin
17

Eine weitere Flexbox-Lösung

Sie können die Reihenfolge der Elemente in HTML invers verwenden. Dann neben der Verwendung orderin als Michael_B Antwort können Sie verwenden , flex-direction: row-reverse;oderflex-direction: column-reverse; auf der Anlage abhängig.

Arbeitsprobe:

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

Vadim Ovchinnikov
quelle
16

Derzeit gibt es keinen offiziellen Weg, dies zu tun, aber Sie können einen kleinen Trick verwenden, um dies zu erreichen! Denken Sie daran, dass es experimentell ist und einige Einschränkungen aufweist ... (Überprüfen Sie diesen Link, wenn Sie Bedenken hinsichtlich der Kompatibilität des Navigators haben.)

Sie können einen CSS3-Selektor verwenden: die aufgerufene Pseudoklasse 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>

Einschränkungen

  • Sie können keine vorherigen Elemente basierend auf den Klassen der nächsten Elemente auswählen
  • Dies gilt auch für Pseudoklassen
0x1gen
quelle
1
@Ian, weil das :nth-child(-n+4)eine Pseudoklasse ist, die auf einen Selektor angewendet werden muss, um richtig zu funktionieren. Wenn Sie nicht überzeugt sind, versuchen Sie es mit einer Gabel meiner Geige zu experimentieren und Sie werden sehen, dass es nicht wok
0x1gene
1
Eigentlich können Sie mit dem *Selektor knotentypunabhängig werden, aber es ist eine widerlich schlechte Praxis.
Josh Burgess
1
Dies ist die Antwort, die für mich funktioniert hat, nicht sicher, warum sie nicht höher gewählt oder akzeptiert wurde.
Jake Cattrall
1
Tatsächlich funktioniert es für verschiedene Knoten: jsfiddle.net/aLhv9r1w/316 . Bitte aktualisieren Sie Ihre Antwort :)
Jamie Barker
1
Ich hatte einen komplexen Selektor, aber sagen wir mal, li#someListItemich wollte die Knoten direkt davor (so interpretiere ich "vorherige") - ich sehe nicht, wie die von Ihnen angegebenen Informationen mir helfen können, dies durch CSS auszudrücken. Sie wählen nur die ersten n Geschwister aus und nehmen an, dass ich die n kenne. Basierend auf dieser Logik kann jeder Selektor den Trick ausführen und die Elemente auswählen, die ich benötige (z. B.: Not ()).
Bitoolean
4

Wenn Sie die genaue Position kennen, würde ein :nth-child()basierter Ausschluss aller folgenden Geschwister funktionieren.

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

Welches würde alle auswählen li s vor dem 3. (zB 1. und 2.). Aber meiner Meinung nach sieht das hässlich aus und hat einen sehr engen Anwendungsfall.

Sie können auch das n-te Kind von rechts nach links auswählen:

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

Welches macht das gleiche.

Kernel
quelle
3

Nein, es ist nicht über CSS möglich. Es nimmt die "Kaskade" zu Herzen ;-).


Wenn Sie jedoch JavaScript zu Ihrer Seite hinzufügen können , können Sie mit ein wenig jQuery Ihr Endziel erreichen.
Sie können jQuery's verwenden find, um einen "Look-Ahead" für Ihr Zielelement / Ihre Zielklasse / ID durchzuführen, und dann einen Backtrack durchführen, um Ihr Ziel auszuwählen.
Anschließend verwenden Sie jQuery, um das DOM (CSS) für Ihr Element neu zu schreiben.

Basierend auf dieser Antwort von Mike Brant könnte das folgende jQuery-Snippet helfen.

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

Dies wählt zuerst alle <ul>s aus, die unmittelbar auf a folgen <p>.
Dann "zurückverfolgt", um alle vorherigen <p>s aus diesem Satz von <ul>s auszuwählen .

Tatsächlich wurde "Vorheriges Geschwister" über jQuery ausgewählt.
Verwenden Sie jetzt die .cssFunktion, um Ihrem CSS neue Werte für dieses Element zu übergeben.


In meinem Fall suchte ich nach einer Möglichkeit, einen DIV mit der ID auszuwählen #full-width, aber NUR, wenn er einen (indirekten) Nachkommen-DIV mit der Klasse von hatte .companies.

Ich hatte die Kontrolle über den gesamten HTML-Code .companies, konnte aber keinen der darüber liegenden HTML-Code ändern.
Und die Kaskade geht nur in eine Richtung: nach unten.

Somit konnte ich ALLE #full-widths auswählen .
Oder ich könnte auswählen, .companiesdass nur ein folgte #full-width.
Aber ich konnte nicht nur #full-widths auswählen , die weitergingen .companies .

Und wieder konnte ich nicht hinzufügen .companies keine höheren Werte im HTML . Dieser Teil des HTML-Codes wurde extern geschrieben und hat unseren Code verpackt.

Aber mit jQuery, ich kann die erforderlichen wählen #full-widths, weisen dann den entsprechenden Stil:

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

Dies findet alle #full-width .companiesund wählt nur diejenigen aus .companies, ähnlich wie Selektoren verwendet werden, um bestimmte Elemente im Standard in CSS anzuvisieren.
Anschließend wird .parents"Backtrack" verwendet und ALLE übergeordneten Elemente von ausgewählt .companies,
diese Ergebnisse werden jedoch gefiltert, um nur #fill-widthElemente beizubehalten, sodass am Ende
nur dann ein #full-widthElement ausgewählt wird, wenn es einen .companiesKlassennachkommen hat.
Schließlich weist es widthdem resultierenden Element einen neuen CSS ( ) -Wert zu.

$(".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-Referenzdokumente:
$ () oder jQuery () : DOM-Element.
. find : Ruft die Nachkommen jedes Elements in der aktuellen Gruppe übereinstimmender Elemente ab, gefiltert nach einem Selektor, einem jQuery-Objekt oder einem Element.
. Eltern : Holen Sie sich das unmittelbar vorhergehende Geschwister jedes Elements in der Gruppe der übereinstimmenden Elemente. Wenn ein Selektor bereitgestellt wird, ruft er das vorherige Geschwister nur ab, wenn er mit diesem Selektor übereinstimmt (filtert die Ergebnisse so, dass nur die aufgelisteten Elemente / Selektoren enthalten sind).
. CSS: Legen Sie eine oder mehrere CSS-Eigenschaften für den Satz übereinstimmender Elemente fest.

SherylHohman
quelle
Das hat nichts mit der Frage zu tun. Natürlich ist es mit JS möglich und Sie brauchen dafür nicht einmal jQuery ( previousElementSibling).
Fabian von Ellerts
1
@FabianvonEllerts Ich habe die Frage von OP direkt in der ersten Zeile meiner Antwort beantwortet. Wie meine Antwort besagt, ist dies über CSS buchstäblich nicht möglich . Ich lieferte dann 1 möglicher Weg nach vorne , das Ziel zu erreichen, mit einer Technologie (JS | JQuery) , dass die Nutzer von CSS vertraut sind mit und haben Zugang zu. Beispielsweise verfügen viele WordPress-Sites auch über JQuery, sodass dies ein einfacher Einstiegspunkt ist: einfach zu verwenden, zu merken und zu erweitern. Es wäre unverantwortlich, einfach mit NEIN zu antworten , ohne einen alternativen Weg zur Erreichung des Ziels anzugeben. Ich teilte mit, was ich gelernt und verwendet hatte, als ich dieselbe Frage hatte.
SherylHohman
previousElementSibling()Für diejenigen, die mit nativen JS-DOM-Funktionen besser vertraut sind, könnte ein weiterer Nicht-CSS-Pfad bereitgestellt werden.
SherylHohman
Ich fand die anderen CSS-HACKS sehr interessant, aber für meinen speziellen Anwendungsfall funktionierten sie entweder nicht (fielen in die Kategorie der Vorbehalte) oder waren zu kompliziert. Für andere, die unter den gleichen Umständen fallen, ist es fair, diese benutzerfreundliche Methode zu teilen, die funktionieren kann, wenn die oben genannten Lösungen fehlschlagen oder zu schwierig zu implementieren / zu warten wären. Viele CSS HACKS wurden geteilt. Diese Problemumgehung wurde nicht behandelt. KEINE der Antworten verwendet den +(nicht vorhandenen) Selektor, den das OP speziell angefordert hat. Betrachten Sie diese Antwort als JS "Hack". Es ist hier, um jemand anderem Zeit zu sparen, die ich aufgewendet habe, um eine Lösung zu finden.
SherylHohman
2

Es gibt leider keinen "vorherigen" Geschwister-Selektor, aber Sie können möglicherweise immer noch den gleichen Effekt erzielen, indem Sie die Positionierung verwenden (z. B. nach rechts schweben). Es hängt davon ab, was Sie versuchen zu tun.

In meinem Fall wollte ich in erster Linie ein CSS-5-Sterne-Bewertungssystem. Ich müsste die vorherigen Sterne einfärben (oder das Symbol austauschen). Wenn ich jedes Element nach rechts schwebe, erhalte ich im Wesentlichen den gleichen Effekt (das HTML für die Sterne muss daher "rückwärts" geschrieben werden).

In diesem Beispiel verwende ich FontAwesome und wechsle zwischen den Unicodes von fa-star-o und 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/

Andrew Leyva
quelle
1
nach rechts schweben und +oder ~Selektoren scheinen mir die sauberste Arbeit zu sein.
Wylliam Judd
2

Abhängig von Ihrem genauen Ziel gibt es eine Möglichkeit, die Nützlichkeit eines übergeordneten Selektors zu erreichen, ohne einen zu verwenden (selbst wenn einer existieren würde) ...

Sagen wir, wir haben:

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

Was können wir tun, um den Sockenblock (einschließlich der Sockenfarben) durch Abstände optisch hervorzuheben?

Was wäre schön, existiert aber nicht:

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

Was gibt es:

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

Dadurch werden alle Ankerlinks so eingestellt, dass sie oben einen Rand von 15 Pixel haben, und für diejenigen ohne UL-Elemente (oder andere Tags) in LIs wird dieser Wert auf 0 zurückgesetzt.

DynamicDan
quelle
2

Ich brauchte eine Lösung, um das vorherige Geschwister tr auszuwählen. Ich habe diese Lösung mit React- und Styled-Komponenten entwickelt. Dies ist nicht meine genaue Lösung (Dies ist aus dem Gedächtnis, Stunden später). Ich weiß, dass die Funktion setHighlighterRow fehlerhaft ist.

OnMouseOver eine Zeile setzt den Zeilenindex auf Status und rendert die vorherige Zeile mit einer neuen Hintergrundfarbe

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;
    }
`;
Kyle
quelle
-1

Ich hatte ein ähnliches Problem und fand heraus, dass alle Probleme dieser Art wie folgt gelöst werden können:

  1. Geben Sie all Ihren Artikeln einen Stil.
  2. Geben Sie Ihrem ausgewählten Artikel einen Stil.
  3. Geben Sie den nächsten Elementen einen Stil mit + oder ~.

Auf diese Weise können Sie Ihre aktuellen, vorherigen Elemente (alle Elemente, die mit aktuellen und nächsten Elementen überschrieben werden) und Ihre nächsten Elemente formatieren.

Beispiel:

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

Hoffe es hilft jemandem.

Hejar
quelle
1
es ist im Grunde der gleiche Trick wie bei älteren Antwort aus dem gleichen Thread: stackoverflow.com/a/27993987/717732
quetzalcoatl