Esiste un selettore "fratello precedente"?


1356

Il segno più ( +) è per il prossimo fratello.

Esiste un equivalente per il fratello precedente?


18
OMG, tutte le risposte qui che suggeriscono di invertire l'ordine degli elementi html e quindi utilizzare i CSS per farli apparire all'indietro sono un vero tratto. Sicuramente non è specificato nella domanda, ma la maggior parte delle domande "puoi fare X con CSS" dovrebbe presumere che non puoi cambiare l'HTML in modo strutturale.
squarecandy

3
@squarecandy, concordo principalmente con il tuo commento. Ma le soluzioni che consideri inadeguate sono comunque utili in alcuni casi (nota i voti positivi). Quindi vale la pena pubblicare. Quello che vedi come un "vero tratto" potrebbe essere una "soluzione creativa" per gli altri.
Michael Benjamin,

Risposte:


839

No, non esiste un selettore "fratello precedente".

In una nota correlata, ~è per il fratello successore generale (nel senso che l'elemento viene dopo questo, ma non necessariamente immediatamente dopo) ed è un selettore CSS3. +è per il prossimo fratello ed è CSS2.1.

Vedere Combinatore di fratelli adiacenti dal selettore Livello 3 e 5.7 Selettori di fratello adiacente dalla specifica Cascading Style Sheets Livello 2 Revisione 1 (CSS 2.1) .


14
Dallo standard CSS3: gli elementi rappresentati dalle due sequenze condividono lo stesso genitore nella struttura del documento e l'elemento rappresentato dalla prima sequenza precede (non necessariamente immediatamente) l'elemento rappresentato dalla seconda.
Lie Ryan,

26
@Lie Ryan: Sì, ma il punto cruciale nella sua risposta è che non selezioni l'elemento precedente.
BoltClock

42
Ecco un esempio che ho fatto per vedere cosa può e cosa non può fare. jsfiddle.net/NuuHy/1
Abacus,

7
La funzione jquery utile per questo è prev (). Ad esempio $ ("# the_element"). Prev (). Css ("background-color", "red")
Satbir Kira,

1
A seconda del markup, questo potrebbe aiutare: stackoverflow.com/questions/42680881/...
Samnau

235

Ho trovato un modo per dare uno stile a tutti i fratelli precedenti (opposti ~) che potrebbero funzionare a seconda delle necessità.

Supponiamo che tu abbia un elenco di link e quando passi con il mouse su uno di questi, tutti i precedenti dovrebbero diventare rossi. Puoi farlo in questo modo:

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


17
Puoi aggiungere una spiegazione di come funziona. (sembra che applichi uno stile a tutti gli elementi e ai seguenti elementi, ma può essere descritto esplicitamente)
AL

1
Soluzione eccezionale. Non è necessario riordinare gli elementi nel markup né nel rendering (via float:right). Richiedeva un crollo dello spazio bianco tra unità / parole e riempimento invece dei margini, ma altrimenti funziona perfettamente!
Steven Vachon,

7
sì, ma un singolo precedente è necessario il più delle volte NON TUTTI i precedenti!
Azerafati,

42
I collegamenti diventano tutti rossi se passo sopra lo spazio tra loro, per me.
Lynn,

3
@Lynn la risposta include solo il codice per rendere rossi i collegamenti precedenti al passaggio del mouse. Gli stili aggiuntivi dipendono dal tuo caso d'uso. Per un componente di valutazione a stelle (che immagino sia un caso comune), dovresti liberarti di quello spazio e anche rendere rosso il link al passaggio del mouse.
Mantish

164

Selettori livello 4 introduce:has() (precedentemente l'indicatore soggetto !) che ti permetterà di selezionare un fratello precedente con:

previous:has(+ next) {}

... ma al momento della stesura, è una certa distanza oltre il limite per il supporto del browser.


52
"Bleeding edge for support browser" potrebbe essere una sopravvalutazione. Al momento della stesura di questo, nemmeno l'ultima versione di Chrome può utilizzare la :has()pseudo-classe.
Reed Martin,

33
@ReedMartin - Ecco perché ho detto una certa distanza oltre il limite del sanguinamento
Quentin

12
": has non è contrassegnato come parte del profilo del selettore dinamico, il che significa che non può essere utilizzato all'interno dei fogli di stile; solo con funzioni come document.querySelector ()." - developer.mozilla.org/en-US/docs/Web/CSS/:has
Arch Linux Tux

1
@ArchLinuxTux: "Questa limitazione è stata rimossa", quindi una volta potremmo usare questa funzione: D.
Jacob van Lingen,

@JacobvanLingen - caniuse.com/#feat=css-has - Al momento nessun browser lo supporta.
Quentin,

153

Considera la orderproprietà dei layout flessibili e di griglia.

Mi concentrerò su flexbox negli esempi seguenti, ma gli stessi concetti si applicano a Grid.


Con Flexbox, è possibile simulare un precedente selettore di pari livello.

In particolare, la orderproprietà flex può spostare elementi sullo schermo.

Ecco un esempio:

Volete che l'elemento A diventi rosso quando l'elemento B è sospeso.

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

PASSI

  1. Crea ulun contenitore flessibile.

    ul { display: flex; }

  1. Invertire l'ordine dei fratelli nel mark-up.

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

  1. Usa un selettore di pari livello per scegliere come bersaglio l'elemento A ( ~o +lo farà).

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

  1. Utilizzare la orderproprietà flex per ripristinare l'ordine dei fratelli sul display visivo.

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

... e voilà! È nato un selettore di fratelli precedente (o almeno simulato).

Ecco il codice completo:

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>

Dalle specifiche del flexbox:

5.4. Ordine di visualizzazione: la orderproprietà

Gli elementi Flex sono, per impostazione predefinita, visualizzati e disposti nello stesso ordine in cui appaiono nel documento di origine. La orderproprietà può essere utilizzata per modificare questo ordine.

La orderproprietà controlla l'ordine in cui gli oggetti flessibili appaiono all'interno del contenitore flessibile, assegnandoli a gruppi ordinali. Prende un singolo <integer>valore, che specifica a quale gruppo ordinale appartiene l'elemento flessibile.

L'iniziale order valore per tutti gli articoli flessibili è 0.

Vedi anche ordernelle specifiche Layout griglia CSS .


Esempi di "selettori di fratelli precedenti" creati con la orderproprietà flex .

.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


Una nota a margine - Due convinzioni obsolete sui CSS

Flexbox sta frantumando le convinzioni di lunga data sul CSS.

Una di queste credenze è che un CSS precedente non è possibile selezionare un selettore di pari livello .

Dire che questa convinzione è diffusa sarebbe un eufemismo. Ecco un esempio di domande correlate sul solo StackTranslate.it:

Come sopra descritto, questa convinzione non è del tutto vera. Un selettore di fratelli precedente può essere simulato in CSS usando la orderproprietà flex .

Il z-indexmito

Un'altra convinzione di vecchia data è stata che z-indexfunziona solo su elementi posizionati.

In effetti, la versione più recente delle specifiche - la bozza dell'editor del W3C - afferma ancora che ciò è vero:

9.9.1 Specifica del livello di stack: la z-index proprietà

z-index

  • Valore: auto | | ereditare
  • Iniziale: auto
  • Si applica a: elementi posizionati
  • Ereditato: no
  • Percentuali: N / A
  • Media: visivo
  • Valore calcolato: come specificato

(enfasi aggiunta)

In realtà, tuttavia, queste informazioni sono obsolete e inaccurate.

Gli elementi che sono elementi flessibili o elementi della griglia possono creare contesti di sovrapposizione anche quando lo positionsono static.

4.3. Articolo flessibile Z-Ordering

Gli articoli Flex dipingono esattamente come i blocchi incorporati, tranne per il fatto che l'ordine di documento modificato dall'ordine viene utilizzato al posto dell'ordine di documento non elaborato e z-indexvalori diversi dalla autocreazione di un contesto di sovrapposizione anche se lo positionè static.

5.4. Ordinazione sull'asse Z: la z-indexproprietà

L'ordine di disegno degli elementi della griglia è esattamente lo stesso dei blocchi incorporati, tranne per il fatto che l'ordine di documento modificato dall'ordine viene utilizzato al posto dell'ordine di documento non elaborato e z-indexvalori diversi dalla autocreazione di un contesto di sovrapposizione anche se lo positionè static.

Ecco una dimostrazione di come z-indexlavorare su oggetti flessibili non posizionati: https://jsfiddle.net/m0wddwxs/


15
La orderproprietà non è una soluzione poiché è destinata esclusivamente a modificare l' ordine visivo , quindi non ripristina l' ordine semantico originale che si è costretti a modificare in HTML affinché questa soluzione alternativa funzioni.
Marat Tanalin,

2
@Marat Tanalin: per il 90% dei casi d'uso, supponendo che il supporto del browser non sia un problema, funzionerà perfettamente. Il restante 10% dei casi d'uso è 1) casi in cui la modifica dell'ordine visivo non è una soluzione, oppure 2) casi che non coinvolgono affatto i CSS. Per fortuna, per # 2, selors-4 fornisce: has (), ed è semplicemente compito degli sviluppatori delle librerie di selettori implementarlo.
BoltClock

5
Tieni presente che il CSS2.2 ED che stai citando è, in sostanza, ancora CSS2. E il layout di flexbox e griglia non esiste in CSS2, quindi per quanto riguarda CSS2, tali informazioni sono certamente vere. Per lo meno, il testo potrebbe essere aggiornato per menzionare che z-index potrebbe applicarsi ad altri tipi di elementi nei livelli futuri di CSS, allo stesso modo in cui afferma che altre proprietà possono stabilire un contesto di sovrapposizione, come l'opacità.
BoltClock

3
Nel caso in cui qualcuno abbia difficoltà a capire quando z-indexfunzionerà, anche quando "omg, non è positionspecificato!", La specifica menziona il concetto di contesto di accatastamento , che è ben spiegato da questo articolo su MDN
Rogier Spieker,

3
@Michael_B sei il benvenuto! Ho avuto a che fare con molti front-end ignari di questo. Un'altra cosa che vorrei menzionare, il finto selettore di fratelli precedenti funziona bene anche con float: right(o qualsiasi altro mezzo per invertire l'ordinamento, di cui flex/orderha effetti collaterali (minimi?) Minimi). Montato due violini: dimostrando l' float: rightapproccio e dimostrandodirection: rtl
Rogier Spieker,

69

Avevo la stessa domanda, ma poi ho avuto un momento "duh". Invece di scrivere

x ~ y

Scrivi

y ~ x

Ovviamente questo corrisponde a "x" invece di "y", ma risponde "c'è una corrispondenza?" domanda e il semplice attraversamento del DOM potrebbe portarti all'elemento giusto in modo più efficiente rispetto al looping in javascript.

Mi rendo conto che la domanda originale era una domanda CSS, quindi questa risposta è probabilmente completamente irrilevante, ma altri utenti Javascript possono inciampare sulla domanda tramite la ricerca come ho fatto io.


18
Credo che funzioni quando si può trovare facilmente y. Il problema è che y può essere trovato solo rispetto a x, e invertendolo, non puoi trovare y perché devi prima trovare x. Questo è ovviamente in riferimento alla domanda di essere un fratello precedente anziché successivo, ma può anche valere per essere un fratello successivo.
David,

19
Sei un po 'duro, duro. (scusa, non ho potuto resistere.) Il punto è che a volte devi solo sapere "esiste?". Altre volte puoi usare ": before" per mettere qualcosa tra i due elementi. Infine, se devi passare a jQuery, usare find ("y ~ x"). Prev () è più facile di molte alternative.
Bryan Larsen,

157
L'idea di un precedente selettore di fratelli è che selezionerà l'elemento precedente. Sfortunatamente, invertirlo, come descritto qui, non fornisce questa funzionalità.
Zenexer,

14
Grazie @Zenexer per il chiarimento che questa risposta non fornisce una soluzione effettiva alla domanda originale, stavo iniziando a sentirmi stupido pensando a come y ~ xrisolvere il mio problema
Jaime Hablutzel,

4
Capisco l'idea alla base di questa risposta, tuttavia il ragionamento fornito nella risposta non ha molto senso. Il selettore y ~ xnon risponde "c'è una corrispondenza?" domanda, perché i due selettori qui indicati significano cose completamente diverse. Ad esempio, non è y ~ xmai possibile produrre una corrispondenza data la sottostruttura <root><x/><y/></root>. Se la domanda è "esiste?" quindi il selettore è semplicemente y. Se la domanda è "esiste y dato un fratello x in una posizione arbitraria?" allora avresti bisogno di entrambi i selettori. (Anche se forse sto solo facendo un pignolo a questo punto ...)
BoltClock

25

Due trucchi . Invertendo sostanzialmente l'ordine HTML degli elementi desiderati in HTML e usando l' operatore
~ Fratelli successivi :

float-right + inverti l'ordine degli elementi 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>


Parent con direction: rtl;+ inverte l'ordine degli elementi interni

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


25

+è per il prossimo fratello. Esiste un equivalente per il fratello precedente?

È possibile utilizzare i selettori a due asce : !e?

Ci sono 2 selettori di fratelli successivi nei CSS convenzionali:

  • +è il selettore di pari livello immediatamente successivo
  • ~è qualsiasi ulteriore selettore fratelli

Nel CSS convenzionale, non esiste un precedente selettore di pari livello .

Tuttavia, nella libreria post-processor CSS ax , ci sono 2 selettori di fratelli precedenti :

  • ?è il selettore di fratelli precedente immediato (opposto di +)
  • !è qualsiasi precedente selettore pari livello (opposto ~)

Esempio di lavoro:

Nell'esempio seguente:

  • .any-subsequent:hover ~ div seleziona qualsiasi successivo div
  • .immediate-subsequent:hover + div seleziona il successivo immediato div
  • .any-previous:hover ! div seleziona qualsiasi precedente div
  • .immediate-previous:hover ? div seleziona il precedente immediato 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>


3
Questo mi dà un errore di sintassi quando provo a implementarlo su Sass all'interno di un progetto di rotaie.
alex,

25
ax è un post-elaboratore CSS. Non utilizza la stessa sintassi dei pre-processori CSS come Sass, Less o Stylus.
Rounin,

1
@Rounin ti dispiacerebbe aggiungere alcuni collegamenti alla documentazione? Non riesco a trovare ax post-processor.
Dionys

@Dionys - Grazie per l'interesse. ax è un progetto che ho iniziato a fine 2016, quando non conoscevo ES2015 e persino gli oggetti in JS erano molto nuovi per me. Il repository GitHub è qui: github.com/RouninMedia/axe . Intendo molto tornare a questo punto ad un certo punto (ho anche sviluppato qualcosa chiamato ax-blades che sono l'equivalente CSS degli eventi javascript), ma prima devo completare il mio lavoro su un altro progetto (nome in codice ashiva ).
Rounin,

17

Un'altra soluzione flexbox

È possibile utilizzare l'ordine inverso degli elementi in HTML. Quindi oltre a usare ordercome nella risposta di Michael_B puoi usare flex-direction: row-reverse;o in flex-direction: column-reverse;base al tuo layout.

Campione di lavoro:

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


16

Non esiste un modo ufficiale per farlo al momento, ma puoi usare un piccolo trucco per raggiungere questo obiettivo! Ricorda che è sperimentale e presenta alcune limitazioni ... (controlla questo link se ti preoccupi della compatibilità del navigatore)

Quello che puoi fare è usare un selettore CSS3: la pseudo classe chiamata 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>

limitazioni

  • Non è possibile selezionare elementi precedenti in base alle classi degli elementi successivi
  • Questo è lo stesso per le pseudo-classi

1
@Ian perché :nth-child(-n+4)è una pseudo classe che deve essere applicata a un selettore per funzionare correttamente. Se non sei convinto, prova a sperimentarlo usando una forchetta del mio violino e vedrai che non si
sveglia

1
In realtà, puoi scegliere un tipo di nodo indipendente usando il *selettore, ma è una pratica terribilmente cattiva.
Josh Burgess,

1
Questa è la risposta che ha funzionato per me, non sono sicuro del perché non sia stato votato più in alto o accettato.
Jake Cattrall,

1
In realtà, funziona per diversi nodi: jsfiddle.net/aLhv9r1w/316 . Aggiorna la tua risposta :)
Jamie Barker il

1
Avevo un selettore complesso, ma diciamo che lo è li#someListIteme volevo il nodo (i) proprio prima di esso (che è il modo in cui interpreto "precedente") - Non vedo come le informazioni fornite possano aiutarmi a esprimerlo attraverso i CSS. Stai solo selezionando i primi n fratelli e presumi che io conosca il n. Sulla base di questa logica, qualsiasi selettore potrebbe fare il trucco e selezionare gli elementi di cui ho bisogno (come: not ()).
Bitoolean,

4

Se conosci la posizione esatta funzionerebbe :nth-child()un'esclusione basata su tutti i fratelli seguenti.

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

Che selezionerebbe tutte le lis prima del 3 ° (es. 1 ° e 2 °). Ma, a mio avviso, sembra brutto e ha una custodia molto stretta.

Puoi anche selezionare l'ennesimo figlio da destra a sinistra:

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

Che fa lo stesso.


3

No. Non è possibile tramite CSS. Prende a cuore la "Cascade" ;-).


Tuttavia, se sei in grado di aggiungere JavaScript alla tua pagina, un po 'di jQuery potrebbe portarti al tuo obiettivo finale.
Puoi usare jQuery findper eseguire un "look-ahead" sul tuo elemento / classe / ID target, quindi tornare indietro per selezionare il tuo target.
Quindi usi jQuery per riscrivere il DOM (CSS) per il tuo elemento.

Sulla base di questa risposta di Mike Brant , il seguente frammento di jQuery potrebbe essere d'aiuto.

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

Questo prima seleziona tutti <ul>i messaggi che seguono immediatamente a <p>.
Quindi "torna indietro" per selezionare tutte le <p>s precedenti da quella serie di <ul>s.

In effetti, "fratello precedente" è stato selezionato tramite jQuery.
Ora, usa la .cssfunzione per passare nel tuo CSS nuovi valori per quell'elemento.


Nel mio caso stavo cercando un modo per selezionare un DIV con l'id #full-width, ma SOLO se avesse un DIV (indiretto) discendente con la classe di .companies.

Avevo il controllo di tutto l'HTML sotto .companies, ma non potevo alterare nessuno degli HTML sopra di esso.
E la cascata va solo in 1 direzione: in basso.

Quindi potrei selezionare TUTTI #full-width.
O potrei selezionare .companiesche ha seguito solo a #full-width.
Ma non sono riuscito a selezionare solo quelli #full-widthche procedevano .companies .

E, ancora una volta, non sono stato in grado di aggiungere .companiesaltro in alto nell'HTML. Quella parte dell'HTML è stata scritta esternamente e ha racchiuso il nostro codice.

Ma con jQuery, posso selezionare i messaggi richiesti #full-width, quindi assegnare lo stile appropriato:

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

Questo trova tutto #full-width .companiese seleziona solo quelli .companies, simili a come i selettori sono usati per indirizzare elementi specifici nello standard nei CSS.
Quindi usa .parents"backtrack" e seleziona TUTTI i genitori di .companies,
ma filtra quei risultati per mantenere solo gli #fill-widthelementi, in modo che alla fine
selezioni un #full-widthelemento solo se ha un .companiesdiscendente di classe.
Infine, assegna un nuovo widthvalore CSS ( ) all'elemento risultante.

$(".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>

Documenti di riferimento jQuery:
$ () o jQuery () : elemento DOM.
. trova : ottiene i discendenti di ciascun elemento nell'insieme corrente di elementi corrispondenti, filtrati da un selettore, un oggetto jQuery o un elemento.
. genitori : ottieni il fratello immediatamente precedente di ciascun elemento nell'insieme di elementi corrispondenti. Se viene fornito un selettore, recupera il fratello precedente solo se corrisponde a quel selettore (filtra i risultati per includere solo gli elementi / selettori elencati).
. css : imposta una o più proprietà CSS per l'insieme di elementi corrispondenti.


Questo non ha nulla a che fare con la domanda. Ovviamente è possibile usare JS e non è nemmeno necessario jQuery per questo ( previousElementSibling).
Fabian von Ellerts,

1
@FabianvonEllerts Ho risposto alla domanda di OP direttamente nella prima riga della mia risposta. Come afferma la mia risposta, non è letteralmente possibile tramite CSS . Ho quindi fornito 1 possibile percorso per raggiungere l'obiettivo, utilizzando una tecnologia (JS | JQuery) a cui gli utenti di CSS potrebbero avere familiarità e accesso. Ad esempio, molti siti WordPress hanno anche JQuery, quindi è un punto di accesso semplice: facile da usare, ricordare ed espandere. Sarebbe irresponsabile rispondere semplicemente a NO , senza fornire un modo alternativo per raggiungere l'obiettivo. Ho condiviso ciò che ho imparato e usato quando avevo la stessa domanda.
SherylHohman,

previousElementSibling()per chi ha più familiarità con le funzioni native di JS DOM potrebbe fornire un altro percorso non CSS in avanti.
SherylHohman,

Ho trovato gli altri HACK CSS molto interessanti, ma per il mio caso d'uso particolare non hanno funzionato (sono rientrati nella categoria avvertimenti) o erano troppo contorti. Per gli altri che si trovano nella stessa circostanza, è giusto condividere questo metodo di facile utilizzo che può funzionare, laddove le soluzioni di cui sopra falliscono o sarebbe troppo difficile da implementare / mantenere. Molti CSS HACKS sono stati condivisi. Questo lavoro in giro non è stato coperto. NESSUNA delle risposte utilizza il +selettore (inesistente) richiesto dall'OP. Considera questa risposta un "hack" di JS. È qui per risparmiare a qualcun altro il tempo che ho trascorso per trovare una soluzione.
SherylHohman,

2

Non v'è alcun selettore "precedente" di pari livello, purtroppo, ma si può forse ancora ottenere lo stesso effetto utilizzando il posizionamento (ad esempio a destra float). Dipende da cosa stai cercando di fare.

Nel mio caso, volevo un sistema di valutazione a 5 stelle principalmente CSS. Avrei bisogno di colorare (o scambiare l'icona di) le stelle precedenti. Fluttuando ciascun elemento a destra, sto essenzialmente ottenendo lo stesso effetto (l'html per le stelle deve quindi essere scritto "all'indietro").

Sto usando FontAwesome in questo esempio e lo scambio tra gli unicodi di fa-star-o e 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/


1
float right +eo ~selettori mi colpiscono come il lavoro più pulito in circolazione.
Wylliam Judd,

2

A seconda del tuo obiettivo esatto, c'è un modo per ottenere l'utilità di un selettore genitore senza usarne uno (anche se esistesse) ...

Dì che abbiamo:

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

Cosa possiamo fare per far risaltare visivamente il blocco Socks (compresi i colori delle calze) usando la spaziatura?

Cosa sarebbe bello ma non esiste:

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

Cosa esiste:

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

In questo modo tutti i collegamenti di ancoraggio hanno un margine di 15 px in alto e lo reimposta su 0 per quelli senza elementi UL (o altri tag) all'interno di LI.


2

Avevo bisogno di una soluzione per selezionare il precedente fratello germ. Ho trovato questa soluzione usando i componenti React e Styled. Questa non è la mia soluzione esatta (è dalla memoria, ore dopo). So che c'è un difetto nella funzione setHighlighterRow.

OnMouseOver una riga imposterà l'indice di riga sullo stato e restituirà la riga precedente con un nuovo colore di sfondo

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

Non c'è, e c'è .

Se devi posizionare l'etichetta prima dell'input, invece posiziona l'etichetta dopo l'input, mantieni sia l'etichetta che l'input all'interno di un div e modella il div come segue:

.input-box {
  display: flex;
  flex-direction: column-reverse;
}
<div class="input-box">
                <input
                  id="email"
                  class="form-item"
                 
                />
                <label for="email" class="form-item-header">                  
                      E-Mail*                  
                </label>
</div>

Ora puoi applicare le opzioni standard di stile per i fratelli successivi disponibili in CSS e sembrerà come se stessi usando uno stile di fratello precedente.


-1

Ho avuto un problema simile e ho scoperto che tutti i problemi di questa natura possono essere risolti come segue:

  1. dai uno stile a tutti i tuoi oggetti.
  2. dai uno stile al tuo oggetto selezionato.
  3. dai uno stile agli oggetti successivi usando + o ~.

e in questo modo sarai in grado di dare uno stile ai tuoi elementi attuali, precedenti (tutti gli articoli sostituiti con quelli attuali e successivi) e i tuoi prossimi.

esempio:

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

Spero che aiuti qualcuno.


1
è sostanzialmente lo stesso trucco della risposta precedente della stessa discussione: stackoverflow.com/a/27993987/717732
quetzalcoatl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.