Y a-t-il un sélecteur «frère précédent»?

1356

Le signe plus ( +) est pour le prochain frère.

Y a-t-il un équivalent pour le frère précédent?

Jourkey
la source
18
OMG, toutes les réponses ici suggérant que vous inversiez l'ordre des éléments html puis utilisez CSS pour les faire apparaître en arrière sont un véritable étirement. Bien sûr, cela ne spécifie pas dans la question, mais la plupart des questions "pouvez-vous faire X avec CSS" devraient supposer que vous ne pouvez pas modifier le code HTML structurellement.
squarecandy
3
@squarecandy, je suis principalement d'accord avec votre commentaire. Mais les solutions que vous citez comme inadéquates sont néanmoins utiles dans certains cas (notez les votes positifs). Ils valent donc la peine d'être publiés. Ce que vous voyez comme un «véritable tronçon» peut être une «solution créative» pour les autres.
Michael Benjamin

Réponses:

839

Non, il n'y a pas de sélecteur "frère précédent".

Sur une note connexe, ~est pour le frère successeur général (ce qui signifie que l'élément vient après celui-ci, mais pas nécessairement immédiatement après) et est un sélecteur CSS3. +est pour le prochain frère et est CSS2.1.

Voir Combinateur frère adjacent des sélecteurs de niveau 3 et 5.7 Sélecteurs frère adjacent des feuilles de style en cascade, niveau 2, révision 2 (CSS 2.1) .

cletus
la source
14
Du standard CSS3: Les éléments représentés par les deux séquences partagent le même parent dans l'arborescence du document et l'élément représenté par la première séquence précède (pas nécessairement immédiatement) l'élément représenté par la seconde.
Lie Ryan
26
@Lie Ryan: Oui, mais le point que le cletus fait valoir dans sa réponse est que vous ne sélectionnez pas l'élément précédent.
BoltClock
42
Voici un exemple que j'ai fait pour voir ce que cela peut et ne peut pas faire. jsfiddle.net/NuuHy/1
Abacus
7
La fonction jquery utile pour cela est prev (). Par exemple $ ("# the_element"). Prev (). Css ("background-color", "red")
Satbir Kira
1
En fonction de votre balisage, cela peut vous aider: stackoverflow.com/questions/42680881/…
samnau
235

J'ai trouvé un moyen de styliser tous les frères et sœurs précédents (à l'opposé de ~) qui peuvent fonctionner selon ce dont vous avez besoin.

Supposons que vous ayez une liste de liens et que lorsque vous passez la souris dessus, tous les précédents devraient devenir rouges. Vous pouvez le faire comme ceci:

/* 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
la source
17
Vous pouvez ajouter une explication de son fonctionnement. (il semble que vous appliquiez un style à tous les éléments et aux éléments suivants, mais il peut être décrit explicitement)
AL
1
Super solution. Pas besoin de réorganiser les éléments en balisage ni en rendu (via float:right). Cela a nécessité un effondrement des espaces blancs entre les unités / mots et le remplissage au lieu des marges, mais cela fonctionne parfaitement sinon!
Steven Vachon
7
oui, mais un seul précédent est nécessaire la plupart du temps PAS TOUS les précédents!
azerafati
42
Les liens deviennent tous rouges si je survole l'espace entre eux, pour moi.
Lynn
3
@Lynn, la réponse comprend uniquement le code pour rendre les liens précédents rouges en survol. Les styles supplémentaires dépendent de votre cas d'utilisation. Pour un composant de classement par étoiles (ce qui, je suppose, est un cas courant), vous devez vous débarrasser de cet espace et également rendre rouge le lien survolé.
mantish
164

Sélecteurs de niveau 4 introduit:has() (auparavant l'indicateur de sujet !) qui vous permettra de sélectionner un frère précédent avec:

previous:has(+ next) {}

… Mais au moment de la rédaction de ce document, la distance est au-delà du bord de saignement pour la prise en charge du navigateur.

Quentin
la source
52
«Un saignement de plus pour la prise en charge du navigateur» pourrait être une surestimation. Au moment d'écrire ces lignes, même la dernière version de Chrome ne pouvait pas utiliser la :has()pseudo-classe.
Reed Martin
33
@ReedMartin - C'est pourquoi j'ai dit une certaine distance au-delà du bord de saignement
Quentin
12
": has n'est pas marqué comme faisant partie du profil de sélecteur dynamique, ce qui signifie qu'il ne peut pas être utilisé dans les feuilles de style; uniquement avec des fonctions comme document.querySelector ()." - developer.mozilla.org/en-US/docs/Web/CSS/:has
Arch Linux Tux
1
@ArchLinuxTux: "Cette limitation est maintenant supprimée", donc une fois, nous pouvons éventuellement utiliser cette fonctionnalité: D.
Jacob van Lingen
@JacobvanLingen - caniuse.com/#feat=css-has - Aucun navigateur ne le prend en charge pour le moment.
Quentin
153

Considérez la orderpropriété des dispositions de flexion et de grille.

Je vais me concentrer sur flexbox dans les exemples ci-dessous, mais les mêmes concepts s'appliquent à Grid.


Avec flexbox, un sélecteur de frère précédent peut être simulé.

En particulier, la orderpropriété flex peut déplacer des éléments autour de l'écran.

Voici un exemple:

Vous voulez que l'élément A devienne rouge lorsque l'élément B est survolé.

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

PAS

  1. Faites ulun récipient flexible.

    ul { display: flex; }

  1. Inversez l'ordre des frères et sœurs dans la majoration.

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

  1. Utilisez un sélecteur frère pour cibler l'élément A ( ~ou +fera l'affaire).

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

  1. Utilisez la orderpropriété flex pour restaurer l'ordre des frères et sœurs sur l'affichage visuel.

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

... et voilà! Un ancien sélecteur de frères et sœurs est né (ou du moins simulé).

Voici le code complet:

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>

De la spécification flexbox:

5.4. Ordre d'affichage: la orderpropriété

Les éléments Flex sont, par défaut, affichés et disposés dans le même ordre qu'ils apparaissent dans le document source. La orderpropriété peut être utilisée pour modifier cet ordre.

La orderpropriété contrôle l'ordre dans lequel les éléments flexibles apparaissent dans le conteneur flex, en les affectant à des groupes ordinaux. Il prend une seule <integer>valeur, qui spécifie à quel groupe ordinal l'élément flex appartient.

La première order valeur pour tous les éléments flexibles est 0.

Voir également orderdans la spécification CSS Grid Layout .


Exemples de "sélecteurs de frères précédents" créés avec la orderpropriété 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


Une note latérale - Deux croyances obsolètes sur CSS

Flexbox brise les croyances de longue date sur CSS.

L'une de ces croyances est qu'un sélecteur de frère précédent n'est pas possible en CSS .

Dire que cette croyance est répandue serait un euphémisme. Voici un échantillon de questions connexes sur Stack Overflow seul:

Comme décrit ci-dessus, cette croyance n'est pas entièrement vraie. Un sélecteur frère précédent peut être simulé en CSS à l'aide de la orderpropriété flex .

Le z-indexmythe

Une autre croyance de longue date est que z-index ne fonctionne que sur les éléments positionnés.

En fait, la version la plus récente de la spécification - le projet de l'éditeur du W3C - affirme toujours que cela est vrai:

9.9.1 Spécification du niveau de pile: la z-index propriété

z-index

  • Valeur: auto | | hériter
  • Initiale: auto
  • S'applique à: éléments positionnés
  • Hérité: non
  • Pourcentages: N / A
  • Média: visuel
  • Valeur calculée: comme spécifié

(pas d'italique dans l'original)

En réalité, cependant, ces informations sont obsolètes et inexactes.

Les éléments qui sont des éléments flexibles ou des éléments de grille peuvent créer des contextes d'empilement même lorsqu'ils le positionsont static.

4.3. Commande flexible d'articles Z

Les éléments flexibles peignent exactement la même chose que les blocs en ligne, sauf que l'ordre des documents modifié par ordre est utilisé à la place de l'ordre des documents bruts et des z-indexvaleurs autres queauto création d'un contexte d'empilement, même siposition eststatic .

5.4. Ordre de l'axe Z: lez-index propriété

L'ordre de peinture des éléments de la grille est exactement le même que celui des blocs en ligne, sauf que l'ordre des documents modifié par l'ordre est utilisé à la place de l'ordre des documents bruts et des z-indexvaleurs autres que la autocréation d'un contexte d'empilement, même si position eststatic .

Voici une démonstration du z-indextravail sur des éléments flex non positionnés: https://jsfiddle.net/m0wddwxs/

Michael Benjamin
la source
16
La orderpropriété n'est pas une solution car elle est uniquement destinée à modifier l' ordre visuel , elle ne restaure donc pas l' ordre sémantique d' origine que vous êtes obligé de modifier en HTML pour que cette solution de contournement fonctionne.
Marat Tanalin
5
Gardez à l'esprit que le CSS2.2 ED que vous citez est, en substance, toujours CSS2. Et la flexbox et la disposition de la grille n'existent pas dans CSS2, en ce qui concerne CSS2, ces informations sont certainement vraies. À tout le moins, le texte pourrait être mis à jour pour mentionner que z-index peut s'appliquer à d'autres types d'éléments dans les futurs niveaux de CSS, de la même manière qu'il dit que d'autres propriétés peuvent établir un contexte d'empilement, comme l'opacité.
BoltClock
3
@BoltClock Mon commentaire n'a rien à voir avec le support du navigateur. La technique rompt la sémantique au profit de la présentation. Je crois qu'une classe ordinaire ordinaire ajoutée à l'élément frère précédent côté serveur est beaucoup plus raisonnable.
Marat Tanalin
3
Dans le cas où quelqu'un a du mal à comprendre quand z-indexcela fonctionnera, même lorsque "omg, il n'y a pas positionspécifié!", La spécification mentionne le concept de contexte d'empilement , qui est bien expliqué par cet article sur MDN
Rogier Spieker
3
@Michael_B vous êtes les bienvenus! J'ai eu affaire à de nombreux front-end ignorant cela. Une autre chose que je voudrais mentionner, le faux sélecteur de frère précédent fonctionne également très bien avec float: right(ou tout autre moyen pour inverser l'ordre, qui flex/ordera peu (le moins?) D'effets secondaires). Fouetté deux violons: démonstration de l' float: rightapproche et démonstrationdirection: rtl
Rogier Spieker
69

J'avais la même question, mais ensuite j'ai eu un moment "duh". Au lieu d'écrire

x ~ y

écrire

y ~ x

Évidemment, cela correspond à "x" au lieu de "y", mais il répond au "y a-t-il une correspondance?" question, et une simple traversée DOM peut vous amener au bon élément plus efficacement que de boucler en javascript.

Je me rends compte que la question d'origine était une question CSS, donc cette réponse est probablement complètement hors de propos, mais d'autres utilisateurs Javascript peuvent tomber sur la question via la recherche comme je l'ai fait.

Bryan Larsen
la source
18
Je crois que ça marche quand on peut le trouver facilement. Le problème est que si y ne peut être trouvé que par rapport à x, et en l'inversant, vous ne pouvez pas trouver y car vous devez d'abord trouver x. Ceci est bien sûr en référence à la question de y étant frère aîné plutôt que suivant, mais peut également s'appliquer pour y étant un frère frère suivant.
David
19
Tu es un peu dur, Harsh. (désolé, je n'ai pas pu résister.) Le fait est que parfois il suffit de savoir "existe-t-il?". D'autres fois, vous pouvez utiliser ": avant" pour mettre quelque chose entre les deux éléments. Enfin, si vous devez passer dans jQuery, l'utilisation de find ("y ~ x"). Prev () est plus facile que de nombreuses alternatives.
Bryan Larsen
157
L'idée d'un sélecteur frère précédent est qu'il sélectionnera l'élément précédent. Malheureusement, l'inverser, comme décrit ici, ne fournit pas cette fonctionnalité.
Zenexer
14
Merci @Zenexer pour la clarification que cette réponse ne fournit pas de solution réelle à la question d'origine, je commençais à me sentir stupide en pensant à comment y ~ xrésoudre mon problème
Jaime Hablutzel
4
Je comprends l'idée derrière cette réponse, mais le raisonnement donné dans la réponse n'a pas vraiment de sens. Le sélecteur y ~ xne répond pas "y a-t-il une correspondance?" question, parce que les deux sélecteurs donnés ici signifient des choses complètement différentes. Il n'y a aucun moyen de y ~ xproduire une correspondance avec le sous-arbre <root><x/><y/></root>par exemple. Si la question est "existe-t-il?" alors le sélecteur est simplement y. Si la question est "y existe-t-il étant donné un frère x dans une position arbitraire?" alors vous auriez besoin des deux sélecteurs. (Bien que je sois peut-être en train de taquiner à ce stade ...)
BoltClock
25

Deux astuces . Fondamentalement, inverser l'ordre HTML de vos éléments souhaités en HTML et utiliser l' opérateur
~ Next siblings :

float-right + inverser l'ordre des éléments 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 avec direction: rtl;+ inverse l'ordre des éléments internes

.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
la source
25

+est pour le prochain frère. Y a-t-il un équivalent pour le frère précédent?

Vous pouvez utiliser les deux sélecteurs de haches :! et?

Il y a 2 sélecteurs de frères et sœurs subséquents en CSS conventionnel:

  • +est l' immédiat sélecteur frère / sœur suivant
  • ~est le tout sélecteur de fratrie ultérieur

En CSS conventionnel, il n'y a pas de sélecteur de frère précédent .

Cependant, dans la bibliothèque de post-processeur ax ax CSS, il y a 2 sélecteurs frères précédents :

  • ?est le sélecteur frère immédiat immédiat (opposé à+ )
  • !est le tout sélecteur de frère précédent ( à l' opposé de ~)

Exemple de travail:

Dans l'exemple ci-dessous:

  • .any-subsequent:hover ~ div sélectionne tout div
  • .immediate-subsequent:hover + div sélectionne le suivant immédiat div
  • .any-previous:hover ! div sélectionne tout précédent div
  • .immediate-previous:hover ? div sélectionne le précédent immédiat 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
la source
3
Cela me donne une erreur de syntaxe lorsque j'essaie de l'implémenter sur sass à l'intérieur d'un projet de rails.
alex
25
ax est un post-processeur CSS. Il n'utilise pas la même syntaxe que les pré-processeurs CSS tels que Sass, Less ou Stylus.
Rounin
1
@Rounin voudriez-vous ajouter des liens de documentation? Je ne trouve pas de post-processeur ax .
Dionys
@Dionys - Merci de votre intérêt. ax est un projet que j'ai commencé fin 2016, quand je ne connaissais pas ES2015 et même les objets en JS étaient très nouveaux pour moi. Le référentiel GitHub est ici: github.com/RouninMedia/axe . Je veux vraiment y revenir à un moment donné (j'ai également développé quelque chose appelé hache-lames qui sont l'équivalent CSS des événements javascript), mais je dois d'abord terminer mon travail sur un autre projet (nom de code ashiva ).
Rounin
17

Une autre solution flexbox

Vous pouvez utiliser l'ordre inverse des éléments en HTML. Ensuite, en plus d'utiliser ordercomme dans la réponse de Michael_B, vous pouvez utiliser flex-direction: row-reverse;ouflex-direction: column-reverse; fonction de votre mise en page.

Échantillon de travail:

.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
la source
16

Il n'y a aucun moyen officiel de le faire pour le moment mais vous pouvez utiliser une petite astuce pour y parvenir! N'oubliez pas qu'il est expérimental et qu'il a des limites ... (vérifiez ce lien si vous vous inquiétez de la compatibilité du navigateur)

Ce que vous pouvez faire, c'est utiliser un sélecteur CSS3: la pseudo classe appelée 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>

Limites

  • Vous ne pouvez pas sélectionner les éléments précédents en fonction des classes des éléments suivants
  • C'est la même chose pour les pseudo-classes
0x1gene
la source
1
@Ian car la :nth-child(-n+4)est une pseudo-classe qui doit être appliquée à un sélecteur pour fonctionner correctement. Si vous n'êtes pas convaincu, essayez de l'expérimenter à l'aide d'une fourchette de mon violon et vous verrez qu'il ne fonctionne pas
0x1gene
1
En fait, vous pouvez devenir indépendant du type de nœud à l'aide du *sélecteur, mais c'est une mauvaise pratique odieuse.
Josh Burgess
1
C'est la réponse qui a fonctionné pour moi, je ne sais pas pourquoi elle n'est pas votée plus haut ou acceptée.
Jake Cattrall
1
En fait, cela fonctionne pour différents nœuds: jsfiddle.net/aLhv9r1w/316 . Veuillez mettre à jour votre réponse :)
Jamie Barker
1
J'avais un sélecteur complexe, mais disons que c'est li#someListItemet je voulais le ou les nœuds juste avant (c'est ainsi que j'interprète "précédent") - Je ne vois pas comment les informations que vous avez fournies peuvent m'aider à exprimer cela via CSS. Vous sélectionnez simplement les n premiers frères et sœurs, et supposez que je connais le n. Sur la base de cette logique, n'importe quel sélecteur peut faire l'affaire et sélectionner les éléments dont j'ai besoin (tels que: not ()).
bitoolean
4

Si vous connaissez la position exacte, une :nth-child()exclusion basée sur tous les frères et sœurs suivants fonctionnerait.

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

Qui sélectionnerait tous les lis avant le 3ème (par exemple 1er et 2ème). Mais, à mon avis, cela semble moche et a un cas d'utilisation très serré.

Vous pouvez également sélectionner le nième enfant de droite à gauche:

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

Ce qui fait la même chose.

noyau
la source
3

Non, ce n'est pas possible via CSS. Il prend à cœur la "Cascade" ;-).


Cependant, si vous pouvez ajouter JavaScript à votre page, un peu de jQuery pourrait vous permettre d'atteindre votre objectif final.
Vous pouvez utiliser jQuery findpour effectuer une "anticipation" sur votre élément / classe / id cible, puis revenir en arrière pour sélectionner votre cible.
Ensuite, vous utilisez jQuery pour réécrire le DOM (CSS) pour votre élément.

Sur la base de cette réponse de Mike Brant , l'extrait de code jQuery suivant pourrait vous aider.

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

Cette première sélectionne tous les <ul>s qui suivent immédiatement a <p>.
Ensuite, il "revient en arrière" pour sélectionner tous les <p>s précédents de cet ensemble de <ul>s.

En effet, "frère précédent" a été sélectionné via jQuery.
Maintenant, utilisez la .cssfonction pour passer vos nouvelles valeurs CSS pour cet élément.


Dans mon cas, je cherchais un moyen de sélectionner un DIV avec l'id #full-width, mais UNIQUEMENT s'il avait un DIV descendant (indirect) avec la classe de .companies.

J'avais le contrôle de tout le HTML sous .companies, mais je ne pouvais pas modifier le HTML au-dessus.
Et la cascade ne va que dans un sens: vers le bas.

Ainsi, je pouvais sélectionner TOUS les #full-widths.
Ou je pourrais sélectionner .companiesqui a seulement suivi a #full-width.
Mais je ne pouvais pas sélectionner uniquement les #full-widths qui se déroulaient .companies .

Et, encore une fois, je n'ai pas pu ajouter .companies plus haut dans le HTML. Cette partie du code HTML a été écrite en externe et a enveloppé notre code.

Mais avec jQuery, je peux sélectionner les #full-widths requis , puis attribuer le style approprié:

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

Cela trouve tout #full-width .companies, et sélectionne seulement ceux-ci .companies, de la même manière que les sélecteurs sont utilisés pour cibler des éléments spécifiques en standard en CSS.
Ensuite, il utilise .parentspour "revenir en arrière" et sélectionner TOUS les parents de .companies,
mais filtre ces résultats pour ne conserver que les #fill-widthéléments, de sorte qu'à la fin,
il ne sélectionne un #full-widthélément que s'il a un .companiesdescendant de classe.
Enfin, il attribue une nouvelle widthvaleur CSS ( ) à l'élément résultant.

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

Documents de référence jQuery:
$ () ou jQuery () : élément DOM.
. find : récupère les descendants de chaque élément dans l'ensemble actuel d'éléments correspondants, filtré par un sélecteur, un objet jQuery ou un élément.
. parents : Obtenez le frère immédiatement précédent de chaque élément dans l'ensemble des éléments correspondants. Si un sélecteur est fourni, il ne récupère le frère précédent que s'il correspond à ce sélecteur (filtre les résultats pour n'inclure que les éléments / sélecteurs répertoriés).
. css : définissez une ou plusieurs propriétés CSS pour l'ensemble des éléments correspondants.

SherylHohman
la source
Cela n'a rien à voir avec la question. Bien sûr, il est possible d'utiliser JS et vous n'avez même pas besoin de jQuery pour cela ( previousElementSibling).
Fabian von Ellerts
1
@FabianvonEllerts J'ai répondu à la question d'OP directement dans la première ligne de ma réponse. Comme ma réponse l'indique, ce n'est littéralement pas possible via CSS . J'ai ensuite fourni 1 voie possible pour atteindre l'objectif, en utilisant une technologie (JS | JQuery) que les utilisateurs de CSS pourraient connaître et avoir accès. Par exemple, de nombreux sites WordPress ont également JQuery, c'est donc un point d'entrée facile: facile à utiliser, à mémoriser et à développer. Il serait irresponsable de simplement répondre NON , sans fournir un autre moyen d'atteindre l'objectif. J'ai partagé ce que j'avais appris et utilisé lorsque j'avais la même question.
SherylHohman
previousElementSibling()pour ceux qui connaissent mieux les fonctions natives de JS DOM pourraient fournir un autre chemin non CSS vers l'avant.
SherylHohman
J'ai trouvé les autres CSS HACKS très intéressants, mais pour mon cas d'utilisation particulier, ils ne fonctionnaient pas (tombaient dans la catégorie des mises en garde) ou étaient trop compliqués. Pour d'autres qui tombent dans la même circonstance, il est juste de partager cette méthode facile à utiliser qui peut fonctionner, où les solutions ci-dessus échouent, ou seraient trop difficiles à mettre en œuvre / à maintenir. De nombreux HACKS CSS ont été partagés. Ce travail n'a pas été couvert. AUCUNE des réponses n'utilise le +sélecteur (inexistant) que l'OP a spécifiquement demandé. Considérez cette réponse comme un "hack" JS. C'est là pour faire gagner du temps à quelqu'un d'autre pour trouver une solution.
SherylHohman
2

Il n'y a malheureusement pas de sélecteur de frère "précédent", mais vous pouvez éventuellement encore obtenir le même effet en utilisant le positionnement (par exemple le droit à flotteur). Cela dépend de ce que vous essayez de faire.

Dans mon cas, je voulais un système de notation 5 étoiles principalement CSS. Il faudrait que je colorie (ou permute l'icône) des étoiles précédentes. En flottant chaque élément à droite, j'obtiens essentiellement le même effet (le html pour les étoiles doit donc être écrit «à l'envers»).

J'utilise FontAwesome dans cet exemple et permute entre les unicodes de fa-star-o et 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
la source
1
flotter à droite et +ou les ~sélecteurs me semblent être le travail le plus propre qui soit.
Wylliam Judd du
2

Selon votre objectif exact, il existe un moyen de réaliser l'utilité d'un sélecteur de parents sans en utiliser un (même s'il en existait un) ...

Disons que nous avons:

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

Que pouvons-nous faire pour que le bloc de chaussettes (y compris les couleurs de chaussettes) se démarque visuellement en utilisant l'espacement?

Ce qui serait bien mais n'existe pas:

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

Ce qui existe:

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

Cela définit tous les liens d'ancrage pour avoir une marge de 15 pixels en haut et la réinitialise à 0 pour ceux sans éléments UL (ou autres balises) à l'intérieur des LI.

DynamicDan
la source
2

J'avais besoin d'une solution pour sélectionner le frère précédent tr. J'ai trouvé cette solution en utilisant des composants React et Styled. Ce n'est pas ma solution exacte (c'est de mémoire, des heures plus tard). Je sais qu'il y a une faille dans la fonction setHighlighterRow.

OnMouseOver une ligne définira l'index de ligne à l'état et rendra la ligne précédente avec une nouvelle couleur d'arrière-plan

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
la source
0

Il n'y a pas, et il y a .

Si vous devez placer l'étiquette avant l'entrée, au lieu de la placer après l'entrée, conservez à la fois l'étiquette et l'entrée dans un div et stylisez le div comme suit:

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

Vous pouvez maintenant appliquer les options de style frère suivant standard disponibles dans css, et cela apparaîtra comme si vous utilisiez un style frère précédent.

Ron16
la source
-1

J'ai eu un problème similaire et j'ai découvert que tous les problèmes de cette nature peuvent être résolus comme suit:

  1. donnez un style à tous vos articles.
  2. donnez un style à votre article sélectionné.
  3. donnez aux éléments suivants un style en utilisant + ou ~.

et de cette façon, vous pourrez styliser vos éléments actuels et précédents (tous les éléments remplacés par les éléments actuels et suivants) et vos prochains éléments.

exemple:

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

J'espère que cela aide quelqu'un.

Hejar
la source
1
c'est fondamentalement la même astuce que dans les anciennes réponses du même fil: stackoverflow.com/a/27993987/717732
quetzalcoatl