Domanda

Il segno più ( + ) è per il prossimo fratello. Esiste un equivalente per il fratello precedente?

È stato utile?

Soluzione

No, non esiste un "fratello precedente" selettore.

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

Vedi Combinatore di fratelli adiacenti da Selettori livello 3 e 5.7 Selettori di fratelli adiacenti da Specifiche di Cascading Style Sheets Livello 2 Revisione 1 (CSS 2.1) .

Altri suggerimenti

Ho trovato un modo per dare uno stile a tutti i fratelli precedenti (al contrario di ~ ) 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>

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

previous:has(+ next) {}

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

Considera la proprietà order dei layout flex e grid.

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 proprietà flex order può spostare elementi sullo schermo.

Ecco un esempio:

  

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

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

STEPS

  1. Rendi ul un 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 target l'elemento A ( ~ o + ).

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

  1. Utilizza la proprietà flex order per ripristinare l'ordine dei fratelli sul display visivo.

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

... e voil & # 224 ;! È 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 proprietà order

     

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

     

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

Il valore iniziale order per tutti gli articoli flessibili è 0.

Vedi anche order nel CSS Specifica layout griglia .


Esempi di " selettori di fratelli precedenti " creato con la proprietà 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


Una nota a margine & # 8211; Due convinzioni obsolete sui CSS

Flexbox sta frantumando le convinzioni di lunga data sul CSS.

Una di queste convinzioni è che un selettore di fratelli precedente non è possibile nei CSS .

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

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

Il z-index Mito

Un'altra convinzione di lunga data è stata che z-index funziona solo su elementi posizionati.

In effetti, la versione più recente della specifica & # 8211; il Draft dell'Editor W3C & # 8211; afferma ancora che questo è vero:

  

9.9.1 Specificare il livello di stack: il 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.

Elementi che sono elementi flessibili o elementi della griglia può creare contesti di sovrapposizione anche quando position è statico .

  

4.3. Ordine flessibile Z-Ordering

     

Gli oggetti flessibili dipingono esattamente come i blocchi incorporati, tranne per il fatto che l'ordine di documento modificato dall'ordine viene utilizzato al posto di grezzo   ordine del documento e valori z-index diversi da auto creano un contesto di sovrapposizione anche se position è statico .

     

5.4. Ordine dell'asse Z: la proprietà z-index

     

L'ordine di disegno degli elementi della griglia è esattamente lo stesso dei blocchi incorporati, tranne per il fatto che l'ordine del documento modificato dall'ordine è   usato al posto dell'ordine del documento non elaborato e i valori z-index diversi da auto creano un contesto di sovrapposizione anche se    position è statico .

Ecco una dimostrazione di z-index che lavora su oggetti flessibili non posizionati: https: / /jsfiddle.net/m0wddwxs/

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

x ~ y

scrivi

y ~ x

Ovviamente questo corrisponde a " x " invece di " y " ;, ma risponde a " esiste una corrispondenza? " domanda e un 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.

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

float-right + inverte 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; + inverti 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>

  

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

Puoi usare i due selettori ax : ! e ?

Esistono 2 selettori di fratelli successivi nei CSS convenzionali:

  • + è il immediato successivo selettore di pari livello
  • ~ è il qualunque successivo selettore di pari livello

Nei CSS convenzionali, non esiste nessun precedente selettore di pari livello .

Tuttavia, nella libreria post-processore CSS ax sono presenti 2 selettori di fratelli precedenti :

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

Esempio di lavoro:

Nell'esempio seguente:

  • .any-successive: hover ~ div seleziona qualsiasi div
  • successivo
  • .immediate-successivo: hover + div seleziona il successivo div
  • .any-previous: hover! div seleziona qualsiasi div
  • precedente
  • .immediate-previous: hover? div seleziona il div
  • immediatamente precedente

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>

Un'altra soluzione flexbox

Puoi usare l'ordine inverso degli elementi in HTML. Quindi oltre a usare order come in la risposta di Michael_B puoi usare flex-direction: row -reverse; o flex-direction: column-reverse; a seconda del layout.

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

Al momento non esiste un modo ufficiale per farlo, ma puoi usare un piccolo trucco per raggiungere questo obiettivo! Ricorda che è sperimentale e presenta alcune limitazioni ... (controlla questo link se temi di compatibilità con il 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 puoi selezionare elementi precedenti in base alle classi degli elementi successivi
  • Questo è lo stesso per le pseudo-classi

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

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

Che selezionerebbe tutti i li prima del 3 ° (ad esempio 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.

Non è presente " precedente " purtroppo il selettore di pari livello, ma puoi possibilmente ottenere comunque lo stesso effetto usando il posizionamento (es. float right). 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 ottenendo essenzialmente lo stesso effetto (l'html per le stelle deve quindi essere scritto "all'indietro").

Sto usando FontAwesome in questo esempio e sto scambiando 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/

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

Supponiamo di avere:

<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 15px nella parte superiore e lo reimposta su 0 per quelli senza elementi UL (o altri tag) all'interno di LI.

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 e precedenti (tutti gli articoli sostituiti con quelli attuali e successivi) e i tuoi prossimi elementi.

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.

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


Tuttavia, se riesci ad aggiungere JavaScript alla tua pagina, un po 'di jQuery potrebbe portarti al tuo obiettivo finale.
Puoi utilizzare find di jQuery per eseguire un "look-ahead" sull'elemento target / classe / id, quindi tornare indietro per selezionare il target.
Quindi usi jQuery per riscrivere il DOM (CSS) per il tuo elemento.

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

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

Questa prima seleziona tutti i < ul > che seguono immediatamente un < p > .
Quindi "torna indietro". per selezionare tutti i < p > precedenti da quella serie di < ul > s.

In effetti, "precedente fratello" è stato selezionato tramite jQuery.
Ora, usa la funzione .css per inserire nuovi valori CSS 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 in .companies , ma non ho potuto alterare nessuno degli HTML sopra di esso.
E la cascata va solo in 1 direzione: in basso.

Così ho potuto selezionare TUTTI # full-width s.
Oppure potrei selezionare .companies che ha seguito solo un # full-width .
Ma potevo non selezionare solo # full-width che procedeva .companies .

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

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

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

Questo trova tutti i # full-width .companies e seleziona solo quei .companies , in modo simile al modo in cui i selettori vengono usati per targetizzare elementi specifici nello standard nei CSS. < br> Quindi utilizza .parents per " backtrack " e seleziona TUTTI i genitori di .companies ,
ma filtra questi risultati per mantenere solo gli elementi # fill-width , in modo che alla fine
seleziona un elemento # full-width solo se ha un discendente di classe .companies .
Infine, assegna un nuovo valore CSS ( width ) 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. < br> . trova : ottieni i discendenti di ciascun elemento nell'insieme corrente di elementi corrispondenti, filtrati da un selettore, oggetto jQuery o elemento.
. genitori : ottieni il fratello immediatamente precedente di ciascun elemento dell'insieme di elementi abbinati. 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 il set di elementi abbinati.

Avevo bisogno di una soluzione per selezionare il precedente fratello fratello. 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.

OnMouseSopra una riga imposterà l'indice di riga in modo da renderlo 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;
    }
`;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top