Existe-t-il un sélecteur parent CSS?

3179

Comment sélectionner l' <li>élément qui est un parent direct de l'élément d'ancrage?

Par exemple, mon CSS serait quelque chose comme ceci:

li < a.active {
    property: value;
}

De toute évidence, il existe des moyens de le faire avec JavaScript, mais j'espère qu'il existe une sorte de solution de contournement qui existe nativement au niveau CSS 2.

Le menu que j'essaye de styliser est craché par un CMS, donc je ne peux pas déplacer l'élément actif vers l' <li>élément ... (sauf si je thème le module de création de menu que je préfère ne pas faire).

Des idées?

jcuenod
la source

Réponses:

2536

Il n'existe actuellement aucun moyen de sélectionner le parent d'un élément en CSS.

S'il y avait un moyen de le faire, ce serait dans l'une des spécifications actuelles des sélecteurs CSS:

Cela dit, l' ébauche de travail des sélecteurs de niveau 4 comprend une :has()pseudo-classe qui fournira cette capacité. Elle sera similaire à l' implémentation jQuery .

li:has(> a.active) { /* styles to apply to the li tag */ }

Cependant, en mai 2020, cela n'est toujours pris en charge par aucun navigateur .

En attendant, vous devrez recourir à JavaScript si vous devez sélectionner un élément parent.

Dan Herbert
la source
68
Il semblerait qu'il ait déjà été suggéré et rejeté: stackoverflow.com/questions/45004/…
RobM
14
On dirait que le sélecteur de sujet a été revisité, sauf en utilisant !maintenant:The subject of the selector can be explicitly identified by appending an exclamation mark (!) to one of the compound selectors in a selector.
animuson
13
Le préfixé $me paraissait mieux ... le préfixé !peut être ignoré plus facilement.
Christoph
51
Torsion de l'intrigue majeure! Le Selectors 4 WD vient d'être mis à jour aujourd'hui pour exclure l'indicateur de sujet du profil rapide, qui doit être utilisé par les implémentations CSS. Si ce changement persiste, cela signifie que vous ne pourrez plus utiliser l'indicateur de sujet dans les feuilles de style (sauf si vous utilisez ajouter une sorte de polyfill comme celui décrit dans une autre réponse ) - vous ne pouvez l'utiliser qu'avec l'API Selectors et n'importe où sinon que le profil complet peut être implémenté.
BoltClock
55
Autre mise à jour majeure: il semble qu'ils envisagent de supprimer complètement la syntaxe du sélecteur de sujet et de la remplacer par le :has()pseudo que tout le monde connaît et aime de jQuery. Le dernier ED a supprimé toutes les références à l'indicateur de sujet et l'a remplacé par le :has()pseudo. Je ne connais pas les raisons exactes, mais le CSSWG a tenu un sondage il y a quelque temps et les résultats ont dû influencer cette décision. C'est très probablement pour la compatibilité avec jQuery (afin qu'il puisse tirer parti de qSA sans modifications), et parce que la syntaxe des indicateurs de sujet s'est avérée trop confuse.
BoltClock
152

Je ne pense pas que vous pouvez sélectionner le parent en CSS uniquement.

Mais comme vous semblez déjà avoir une .activeclasse, il serait plus facile de déplacer cette classe vers la li(au lieu de la a). De cette façon, vous pouvez accéder à la fois au liet avia CSS uniquement.

jeroen
la source
4
Vous ne pouvez pas déplacer le pseudo-sélecteur vers l'élément de liste, car il ne s'agit pas d'un élément focalisable. Il utilise le sélecteur: active, donc lorsque l'ancre est active, il souhaite que l'élément de liste soit affecté. Les éléments de la liste ne seront jamais à l'état actif. Soit dit en passant, il est regrettable qu'un tel sélecteur n'existe pas. Il est impossible d'obtenir un menu CSS pur pour être entièrement accessible au clavier sans lui (en utilisant des sélecteurs frères, vous pouvez faire apparaître des sous-menus créés à l'aide de listes imbriquées, mais une fois que la liste devient focalisée, elle est à nouveau masquée). S'il existe des solutions CSS uniquement pour ce conun particulier
12
@Dominic Aquilina Jetez un oeil à la question, l'OP utilise une classe, pas un pseudo sélecteur.
jeroen
125

Vous pouvez utiliser ce script :

*! > input[type=text] { background: #000; }

Cela sélectionnera n'importe quel parent d'une entrée de texte. Mais attendez, il y a encore beaucoup plus. Si vous le souhaitez, vous pouvez sélectionner un parent spécifié:

.input-wrap! > input[type=text] { background: #000; }

Ou sélectionnez-le lorsqu'il est actif:

.input-wrap! > input[type=text]:focus { background: #000; }

Consultez ce HTML:

<div class="input-wrap">
    <input type="text" class="Name"/>
    <span class="help hide">Your name sir</span>
</div>

Vous pouvez sélectionner cela span.helplorsque le inputest actif et l'afficher:

.input-wrap! .help > input[type=text]:focus { display: block; }

Il y a beaucoup plus de capacités; il suffit de consulter la documentation du plugin.

BTW, cela fonctionne dans Internet Explorer.

Idered
la source
5
supposons que l'utilisation de jquery patent()serait plus rapide. Cela doit cependant être testé
Dan
2
@Idered Il échoue lorsque vous avez une déclaration CSS d'un sujet de sélecteur sans sélecteur enfant ( #a!seul déclenche une erreur, #a! pfonctionne), et donc les autres ne fonctionneront pas non plus à cause de Uncaught TypeError: Cannot call method 'split' of undefined: voir jsfiddle.net/HerrSerker/VkVPs
yunzen
3
@HerrSerker je pense #a! est un sélecteur invalide, que doit-il sélectionner?
Idered
2
@Idered je ne sais pas. La spécification ne dit pas que c'est illégal. #une! devrait se sélectionner. Au moins, leur devrait être aucune erreur dans le JavaScript
yunzen
5
D'après mon commentaire sur la réponse acceptée, il semble que le polyfill puisse être nécessaire même dans un avenir proche, car l'indicateur de sujet peut ne jamais être implémenté par les navigateurs en CSS.
BoltClock
108

Comme mentionné par quelques autres, il n'y a pas de moyen de styliser les parents d'un élément en utilisant uniquement CSS, mais ce qui suit fonctionne avec jQuery :

$("a.active").parents('li').css("property", "value");
zcrar70
la source
21
Le <sélecteur n'existe pas (vérifié à l'aide de jQuery 1.7.1).
Rob W
6
Peut-être que cette <syntaxe a fonctionné en 2009, mais je l'ai mise à jour (pour 2013).
Alastair
5
Mieux encore, utiliser intégré jQuery :has()sélecteur : $("li:has(a.active)").css("property", "value");. Il se lit de manière similaire au !sélecteur proposé par CSS 4 . Voir aussi: :parentsélecteur , .parents()méthode , .parent()méthode .
Rory O'Kane
7
Et plutôt que d'utiliser .css("property", "value")pour styliser les éléments sélectionnés, vous devriez généralement .addClass("someClass")et avoir dans votre CSS .someClass { property: value }( via ). De cette façon, vous pouvez noter le style avec toute la puissance de CSS et des préprocesseurs que vous utilisez.
Rory O'Kane
69

Il n'y a pas de sélecteur de parents; juste comme il n'y a pas de sélecteur de frère précédent. Une bonne raison de ne pas disposer de ces sélecteurs est que le navigateur doit parcourir tous les enfants d'un élément pour déterminer si une classe doit être appliquée ou non. Par exemple, si vous avez écrit:

body:contains-selector(a.active) { background: red; }

Ensuite, le navigateur devra attendre jusqu'à ce qu'il ait tout chargé et analysé jusqu'au </body>pour déterminer si la page doit être rouge ou non.

L'article Pourquoi nous n'avons pas de sélecteur parent l' explique en détail.

Salman A
la source
11
alors accélérez le navigateur. Internet lui-même plus rapidement. ce sélecteur est absolument nécessaire, et la raison de ne pas le mettre en œuvre est, malheureusement, parce que nous vivons dans un monde lent et primitif.
vsync
11
en fait, le sélecteur rendrait un navigateur très rapide lent.
Salman A
5
J'espère que les développeurs de navigateurs proposeront une implémentation qui est (au moins) aussi rapide que la version javascript, qui est celle que les gens finissent par utiliser de toute façon.
Marc.2377
"nous vivons dans un monde lent et primitif" toux toux nouvelle montre apple toux toux
Marvin
@ Marc.2377 Si vous essayez l'exemple ci-dessus dans JS sur votre site Web, je ne le visiterai jamais. D'un autre côté, je dirais que la plupart du temps, vous ne vous souciez que des enfants immédiats, donc si cela ne concernait que les enfants immédiats, ce serait un bon ajout sans trop d'impact.
xryl669
54

Il n'y a aucun moyen de le faire en CSS 2. Vous pouvez ajouter la classe à liet référencer le a:

li.active > a {
    property: value;
}
Josh
la source
3
en faisant afficher l'élément a: bloc, vous pouvez le styliser pour l'adapter à l'ensemble de la zone li. si vous pouvez expliquer le style que vous recherchez, je pourrais peut-être vous aider avec une solution.
Josh
il s'agit en fait d'une solution simple et élégante et, dans de nombreux cas, il est logique de définir la classe sur le parent.
Ricardo
35

Essayez de passer aà l' blockaffichage, puis utilisez le style de votre choix. L' aélément remplira l' liélément et vous pourrez modifier son apparence comme vous le souhaitez. N'oubliez pas de mettre le liremplissage à 0.

li {
  padding: 0;
  overflow: hidden;
}
a {
  display: block;
  width: 100%;
  color: ..., background: ..., border-radius: ..., etc...
}
a.active {
  color: ..., background: ...
}
Raseko
la source
31

Le sélecteur CSS " General Sibling Combinator " pourrait être utilisé pour ce que vous voulez:

E ~ F {
    property: value;
}

Cela correspond à tout Félément précédé d'un Eélément.

cobaasta
la source
24
Ce n'est qu'un sélecteur de frères et sœurs, ce n'est pas un enfant, un parent ... ne répond pas vraiment à la question du compagnon
Alireza
26

Pas en CSS 2 pour autant que je sache. CSS 3 a des sélecteurs plus robustes mais n'est pas implémenté de manière cohérente dans tous les navigateurs. Même avec les sélecteurs améliorés, je ne pense pas que cela accomplira exactement ce que vous avez spécifié dans votre exemple.

Mark Hurd
la source
24

Je sais que l'OP recherchait une solution CSS mais c'est simple à réaliser en utilisant jQuery. Dans mon cas, j'avais besoin de trouver la <ul>balise parent d'une <span>balise contenue dans l'enfant <li>. jQuery a le :hassélecteur donc il est possible d'identifier un parent par les enfants qu'il contient:

$("ul:has(#someId)")

sélectionnera l' ulélément qui a un élément enfant avec l'id someId . Ou pour répondre à la question d'origine, quelque chose comme ce qui suit devrait faire l'affaire (non testé):

$("li:has(.active)")
David Clarke
la source
3
Ou utilisez $yourSpan.closest("ul")et vous obtiendrez l'UL parent de votre élément span. Néanmoins, votre réponse est à mon humble avis complètement hors sujet. Nous pouvons répondre à toutes les questions de CSS avec une solution jQuery.
Robin van Baalen
1
Comme identifié dans d'autres réponses, il n'y a aucun moyen de le faire en utilisant CSS 2. Étant donné cette contrainte, la réponse que j'ai fournie est celle que je connais est efficace et est le moyen le plus simple de répondre à la question en utilisant javascript imho.
David Clarke
Compte tenu de vos votes positifs, certaines personnes sont d'accord avec vous. Mais la seule réponse reste celle acceptée; clair et simple "cela ne peut pas être fait comme vous le souhaitez". Si la question est de savoir comment atteindre 60 mph sur un vélo et que vous y répondez "simple; montez dans une voiture et mettez le gaz", ce n'est toujours pas une réponse. D'où mon commentaire.
Robin van Baalen
1
Cette approche rendrait le SO presque complètement inutile. Je recherche SO pour savoir comment résoudre les problèmes, pas pour trouver la "seule réponse" ne résout pas le problème. C'est pourquoi SO est si génial, car il y a toujours plus d'une façon d'écorcher un chat.
David Clarke
23

Le pseudo-élément :focus-withinpermet de sélectionner un parent si un descendant a le focus.

Un élément peut être focalisé s'il a un tabindexattribut.

Prise en charge du navigateur pour la mise au point interne

Tabindex

Exemple

.click {
  cursor: pointer;
}

.color:focus-within .change {
  color: red;
}

.color:focus-within p {
  outline: 0;
}
<div class="color">
  <p class="change" tabindex="0">
    I will change color
  </p>
  <p class="click" tabindex="1">
    Click me
  </p>
</div>

sol
la source
2
Cela fonctionne bien dans mon cas, merci! Juste un non, l'exemple serait plus illustratif si vous changez la couleur au parent, pas au frère, c'est remplacer .color:focus-within .changepar .color:focus-within. Dans mon cas, j'utilise bootstrap nav-bar qui ajoute la classe aux enfants lorsqu'il est actif et je veux ajouter une classe au parent .nav-bar. Je pense que c'est un scénario assez courant où je possède le balisage mais le composant css + js est bootstrap (ou autre) donc je ne peux pas changer le comportement. Bien que je puisse ajouter tabindex et utiliser ce CSS. Merci!
cancerbero
22

Il s'agit de l'aspect le plus discuté de la spécification des sélecteurs de niveau 4 . Avec cela, un sélecteur sera en mesure de styliser un élément en fonction de son enfant en utilisant un point d'exclamation après le sélecteur donné (!).

Par exemple:

body! a:hover{
   background: red;
}

définira une couleur d'arrière-plan rouge si l'utilisateur survole une ancre.

Mais il faut attendre l'implémentation des navigateurs :(

Marco Allori
la source
21

Vous pouvez essayer d'utiliser un lien hypertexte comme parent, puis modifier les éléments internes au survol. Comme ça:

a.active h1 {color:red;}

a.active:hover h1 {color:green;}

a.active h2 {color:blue;}

a.active:hover h1 {color:yellow;}

De cette façon, vous pouvez modifier le style dans plusieurs balises internes, en fonction du survol de l'élément parent.

Riverstorm
la source
1
C'est correct, mais limite le code de balisage dans la abalise à certains éléments uniquement, si vous souhaitez vous conformer aux normes XHTML. Par exemple, vous ne pouvez pas utiliser un divdedans asans recevoir un avertissement de violation du schéma.
Ivaylo Slavov
2
Totalement raison Ivaylo! "a" est un élément non bloc, il ne peut donc pas utiliser d'éléments bloc à l'intérieur.
riverstorm
1
En HTML5, il est parfaitement possible de mettre des éléments de bloc à l'intérieur des liens.
Matthew James Taylor
2
... si c'était sémantiquement faux, ils ne l'auraient pas autorisé en HTML5 là où il ne l'était pas auparavant.
BoltClock
14

Actuellement, il n'y a pas de sélecteur de parents et il n'est même pas discuté dans aucune des discussions du W3C. Vous devez comprendre comment CSS est évalué par le navigateur pour comprendre si nous en avons besoin ou non.

Il y a beaucoup d'explications techniques ici.

Jonathan Snook explique comment le CSS est évalué .

Chris Coyier sur les pourparlers de Parent selector .

Harry Roberts à nouveau sur l'écriture de sélecteurs CSS efficaces .

Mais Nicole Sullivan a quelques faits intéressants sur les tendances positives .

Ces personnes sont toutes de première classe dans le domaine du développement frontal.

Suraj Naik
la source
12
Le needest défini par les exigences des développeurs Web, si le fait de l'avoir dans la spécification est décidé par d'autres facteurs.
nicodemus13
14

Juste une idée de menu horizontal ...

Partie de HTML

<div class='list'>
  <div class='item'>
    <a>Link</a>
  </div>
  <div class='parent-background'></div>
  <!-- submenu takes this place -->
</div>

Fait partie de CSS

/* Hide parent backgrounds... */
.parent-background {
  display: none; }

/* ... and show it when hover on children */
.item:hover + .parent-background {
  display: block;
  position: absolute;
  z-index: 10;
  top: 0;
  width: 100%; }

Démo mise à jour et le reste du code

Un autre exemple comment l'utiliser avec des entrées de texte - sélectionner le jeu de champs parent

Ilya B.
la source
3
Je ne sais pas du tout comment vous entendez généraliser cela à certains / plusieurs / la plupart des cas d'utilisation du sélecteur parent, ni même exactement quelles parties de ce CSS font quoi. Pouvez-vous ajouter une explication approfondie?
Nathan Tuggy
2
Je n'ai pas essayé d'appliquer cela à des scénarios du monde réel, c'est pourquoi je dis "Pas pour la production". Mais je pense que cela ne peut être appliqué au menu à 2 niveaux qu'avec une largeur d'élément fixe. "quelles parties de ce CSS font quoi" - .test-sibling ici est en fait le fond de l'élément parent (la dernière ligne de CSS).
Ilya B.
2
Explication ajoutée (section css de jsfiddle, à partir de "MAIN PART") ... Et je me suis trompé - il peut y avoir un certain nombre de sous-niveaux.
Ilya B.
13

Voici un hack à utiliser pointer-eventsavec hover:

<!doctype html>
<html>
	<head>
		<title></title>
		<style>
/* accessory */
.parent {
	width: 200px;
	height: 200px;
	background: gray;
}
.parent, 
.selector {
	display: flex;
	justify-content: center;
	align-items: center;
}
.selector {
	cursor: pointer;
	background: silver;
	width: 50%;
	height: 50%;
}
		</style>
		<style>
/* pertinent */
.parent {
	background: gray;
	pointer-events: none;
}
.parent:hover {
	background: fuchsia;
}
.parent 
.selector {
	pointer-events: auto;
}
		</style>
	</head>
	<body>
		<div class="parent">
			<div class="selector"></div>
		</div>
	</body>
</html>

Jan Kyu Peblik
la source
12

Il existe un plugin qui étend CSS pour inclure des fonctionnalités non standard qui peuvent vraiment aider lors de la conception de sites Web. Cela s'appelle EQCSS .

Une des choses qu'EQCSS ajoute est un sélecteur parent. Il fonctionne dans tous les navigateurs, Internet Explorer 8 et plus. Voici le format:

@element 'a.active' {
  $parent {
    background: red;
  }
}

Donc, ici, nous avons ouvert une requête d'élément sur chaque élément a.active, et pour les styles à l'intérieur de cette requête, des choses comme du $parentsens, car il y a un point de référence. Le navigateur peut trouver le parent, car il est très similaire à parentNodeJavaScript.

Voici une démo de$parent et une autre $parentdémo qui fonctionne dans Internet Explorer 8 , ainsi qu'une capture d'écran au cas où vous ne disposez pas d'Internet Explorer 8 pour tester .

EQCSS comprend également des méta-sélecteurs : $prevpour l'élément avant un élément sélectionné et $thisuniquement pour les éléments qui correspondent à une requête d'élément, et plus encore.

innovati
la source
11

C'est maintenant 2019, et la dernière version du module d'imbrication CSS a en fait quelque chose comme ça. Présentation @nestdes règles at.

3.2. La règle Nesting At: @nest

Bien que la nidification directe soit agréable, elle est quelque peu fragile. Certains sélecteurs d'imbrication valides, comme .foo &, sont interdits, et la modification du sélecteur de certaines manières peut rendre la règle invalide de manière inattendue. De plus, certaines personnes trouvent la nidification difficile à distinguer visuellement des déclarations environnantes.

Pour vous aider dans tous ces problèmes, cette spécification définit la règle @nest, qui impose moins de restrictions sur l'imbrication valide des règles de style. Sa syntaxe est:

@nest = @nest <selector> { <declaration-list> }

La règle @nest fonctionne de manière identique à une règle de style: elle commence par un sélecteur et contient des déclarations qui s'appliquent aux éléments auxquels le sélecteur correspond. La seule différence est que le sélecteur utilisé dans une règle @nest doit contenir un nid, ce qui signifie qu'il contient un sélecteur d'imbrication quelque part. Une liste de sélecteurs contient des nids si tous ses sélecteurs complexes individuels contiennent des nids.

(Copiez et collez à partir de l'URL ci-dessus).

Exemple de sélecteurs valides sous cette spécification:

.foo {
  color: red;
  @nest & > .bar {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   .foo > .bar { color: blue; }
 */

.foo {
  color: red;
  @nest .parent & {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   .parent .foo { color: blue; }
 */

.foo {
  color: red;
  @nest :not(&) {
    color: blue;
  }
}
/* Equivalent to:
   .foo { color: red; }
   :not(.foo) { color: blue; }
 */
roberrrt-s
la source
10

Techniquement, il n'y a aucun moyen direct de le faire. Cependant, vous pouvez trier cela avec jQuery ou JavaScript.

Cependant, vous pouvez également faire quelque chose comme ça.

a.active h1 {color: blue;}
a.active p {color: green;}

jQuery

$("a.active").parents('li').css("property", "value");

Si vous souhaitez y parvenir en utilisant jQuery, voici la référence du sélecteur parent jQuery .

Prabhakar Undurthi
la source
9

Le W3C a exclu un tel sélecteur en raison de l'énorme impact sur les performances qu'il aurait sur un navigateur.

rgb
la source
27
faux. parce que le DOM est un arbre, ils doivent aller au parent avant d'arriver à l'enfant, donc il suffit de revenir en arrière d'un nœud. oo
NullVoxPopuli
9
Les sélecteurs CSS sont une file d'attente, donc l' ordre du sélecteur est évalué plutôt que la hiérarchie XPath ou DOM du document.
Paul Sweatte
3
@rgb C'est du moins ce qu'ils nous ont dit.
2013
9

La réponse courte est NON ; nous n'en avons pas parent selectorà ce stade en CSS, mais si vous n'avez pas à échanger les éléments ou les classes de toute façon, la deuxième option utilise JavaScript. Quelque chose comme ça:

var activeATag = Array.prototype.slice.call(document.querySelectorAll('a.active'));

activeATag.map(function(x) {
  if(x.parentNode.tagName === 'LI') {
    x.parentNode.style.color = 'red'; // Your property: value;
  }
});

Ou d'une manière plus courte si vous utilisez jQuery dans votre application:

$('a.active').parents('li').css('color', 'red'); // Your property: value;
Alireza
la source
5

Bien qu'il n'y ait pas de sélecteur parent dans CSS standard à l'heure actuelle, je travaille sur un projet (personnel) appelé ax (c'est-à-dire Syntaxe de sélecteur CSS augmentée / ACSSSS ) qui, parmi ses 7 nouveaux sélecteurs, comprend les deux:

  1. un sélecteur parent immédiat< (qui permet à la sélection opposée de >)
  2. un sélecteur d'ancêtre quelconque ^ (qui permet à la sélection opposée de [SPACE])

ax est actuellement à un stade de développement BETA relativement précoce.

Voir une démo ici:

http://rounin.co.uk/projects/axe/axe2.html

(comparer les deux listes de gauche avec des sélecteurs standard et les deux listes de droite avec des sélecteurs de haches)

Rounin
la source
3
Le projet est actuellement en phase bêta. Vous pouvez (au moins actuellement) activer les sélecteurs de haches dans vos styles CSS en incluant <script src="https://rouninmedia.github.io/axe/axe.js"></script>à la fin de votre document html, juste avant </body>.
Rounin
4

Au moins jusqu'à CSS 3 inclus, vous ne pouvez pas sélectionner comme ça. Mais cela peut être fait assez facilement de nos jours en JavaScript, il vous suffit d'ajouter un peu de JavaScript vanille, notez que le code est assez court.

cells = document.querySelectorAll('div');
[].forEach.call(cells, function (el) {
    //console.log(el.nodeName)
    if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
        console.log(el)
    };
});
<div>Peter</div>
<div><a href="#">Jackson link</a></div>
<div>Philip</div>
<div><a href="#">Pullman link</a></div>

Eduard Florinescu
la source
4

Des idées?

CSS 4 sera fantaisiste s'il ajoute des crochets à la marche arrière . Jusque - là , il est possible (mais pas recommandé) d'utiliser checkboxet / ou radio inputs pour briser la manière habituelle que les choses sont reliées, et par qui permettent également CSS de fonctionner en dehors de son champ d' application normale ...

/* Hide things that may be latter shown */
.menu__checkbox__selection,
.menu__checkbox__style,
.menu__hidden {
  display: none;
  visibility: hidden;
  opacity: 0;
  filter: alpha(opacity=0); /* Old Microsoft opacity */
}


/* Base style for content and style menu */
.main__content {
  background-color: lightgray;
  color: black;
}

.menu__hidden {
  background-color: black;
  color: lightgray;
  /* Make list look not so _listy_ */
  list-style: none;
  padding-left: 5px;
}

.menu__option {
  box-sizing: content-box;
  display: block;
  position: static;
  z-index: auto;
}

/* &#9660; - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
  content: '\2630';
  display: inline-block;
}
*/

/* &#9660; - Down Arrow */
.menu__trigger__selection::after {
  content: "\25BC";
  display: inline-block;
  transform: rotate(90deg);
}


/* Customize to look more `select` like if you like */
.menu__trigger__style:hover,
.menu__trigger__style:active {
  cursor: pointer;
  background-color: darkgray;
  color: white;
}


/**
 * Things to do when checkboxes/radios are checked
 */

.menu__checkbox__selection:checked + .menu__trigger__selection::after,
.menu__checkbox__selection[checked] + .menu__trigger__selection::after {
  transform: rotate(0deg);
}

/* This bit is something that you may see elsewhere */
.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
  display: block;
  visibility: visible;
  opacity: 1;
  filter: alpha(opacity=100); /* Microsoft!? */
}


/**
 * Hacky CSS only changes based off non-inline checkboxes
 * ... AKA the stuff you cannot unsee after this...
 */
.menu__checkbox__style[id="style-default"]:checked ~ .main__content {
  background-color: lightgray;
  color: black;
}

.menu__checkbox__style[id="style-default"]:checked ~ .main__content .menu__trigger__style[for="style-default"] {
  color: darkorange;
}

.menu__checkbox__style[id="style-one"]:checked ~ .main__content {
  background-color: black;
  color: lightgray;
}

.menu__checkbox__style[id="style-one"]:checked ~ .main__content .menu__trigger__style[for="style-one"] {
  color: darkorange;
}

.menu__checkbox__style[id="style-two"]:checked ~ .main__content {
  background-color: darkgreen;
  color: red;
}

.menu__checkbox__style[id="style-two"]:checked ~ .main__content .menu__trigger__style[for="style-two"] {
  color: darkorange;
}
<!--
  This bit works, but will one day cause troubles,
  but truth is you can stick checkbox/radio inputs
  just about anywhere and then call them by id with
  a `for` label. Keep scrolling to see what I mean
-->
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-default">
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-one">
<input type="radio"
       name="colorize"
       class="menu__checkbox__style"
       id="style-two">


<div class="main__content">

  <p class="paragraph__split">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
  </p>

  <input type="checkbox"
         class="menu__checkbox__selection"
         id="trigger-style-menu">
  <label for="trigger-style-menu"
         class="menu__trigger__selection"> Theme</label>

  <ul class="menu__hidden">
    <li class="menu__option">
      <label for="style-default"
             class="menu__trigger__style">Default Style</label>
    </li>

    <li class="menu__option">
      <label for="style-one"
             class="menu__trigger__style">First Alternative Style</label>
    </li>

    <li class="menu__option">
      <label for="style-two"
             class="menu__trigger__style">Second Alternative Style</label>
    </li>
  </ul>

  <p class="paragraph__split">
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>

</div>

... assez dégoûtant , mais avec seulement CSS et HTML, il est possible de toucher et de retoucher tout sauf le bodyet :rootde n'importe où en reliant les propriétés idet forde radio/ checkbox inputs et des label déclencheurs ; quelqu'un va probablement montrer comment les retoucher à un moment donné.

Une mise en garde supplémentaire est que seul un input d'un particulier idpeut - être utilisé, premier checkbox/ radio gagne un état basculée en d' autres termes ... Mais plusieurs étiquettes peuvent tous les points à la même input, mais qui ferait à la fois le code HTML et CSS look même grosser.


... J'espère qu'il existe une sorte de solution de contournement qui existe en natif de CSS niveau 2 ...

Je ne suis pas sûr des autres :sélecteurs, mais je :checkedpour pré-CSS 3. Si je me souviens bien, c'était quelque chose comme ça, c'est [checked]pourquoi vous pouvez le trouver dans le code ci-dessus, par exemple,

.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
 /* rules: and-stuff; */
}

... mais pour des choses comme ::afteret :hover, je ne sais pas du tout dans quelle version CSS celles-ci sont apparues en premier.

Cela dit, veuillez ne jamais utiliser cela dans la production, pas même dans la colère. Comme une plaisanterie bien sûr, ou en d'autres termes simplement parce que quelque chose peut être fait ne signifie pas toujours que cela devrait .

S0AndS0
la source
3

Non, vous ne pouvez pas sélectionner le parent uniquement en CSS.

Mais comme vous semblez déjà avoir une .activeclasse, il serait plus facile de déplacer cette classe vers la li(au lieu de la a). De cette façon, vous pouvez accéder à la fois au liet avia CSS uniquement.

Gaurav Aggarwal
la source
1

La modification de l'élément parent basé sur l'élément enfant ne peut actuellement se produire que lorsque nous avons un <input>élément à l'intérieur de l'élément parent. Lorsqu'une entrée obtient le focus, son élément parent correspondant peut être affecté à l'aide de CSS.

L'exemple suivant vous aidera à comprendre l'utilisation :focus-withinen CSS.

.outer-div {
  width: 400px;
  height: 400px;
  padding: 50px;
  float: left
}

.outer-div:focus-within {
  background: red;
}

.inner-div {
  width: 200px;
  height: 200px;
  float: left;
  background: yellow;
  padding: 50px;
}
<div class="outer-div">
  <div class="inner-div">
    I want to change outer-div(Background color) class based on inner-div. Is it possible?
    <input type="text" placeholder="Name" />
  </div>
</div>

Sethuraman
la source
1

C'est possible avec esperluette à Sass :

h3
  font-size: 20px
  margin-bottom: 10px
  .some-parent-selector &
    font-size: 24px
    margin-bottom: 20px

Sortie CSS:

h3 {
  font-size: 20px;
  margin-bottom: 10px;
}
.some-parent-selector h3 {
  font-size: 24px;
  margin-bottom: 20px;
}
Rodolfo Jorge Nemer Nogueira
la source
2
c'est vrai, mais seulement si vous connaissez le sélecteur à l'avance.
Shahar
11
Cela ne sélectionne pash3 le parent de, ce qui était l'objectif. Cela sélectionnerait les h3s qui sont des descendants de .some-parent-selector.
Jacob Ford
1

J'embaucherais du code JavaScript pour le faire. Par exemple, dans React lorsque vous parcourez un tableau, ajoutez une autre classe au composant parent, ce qui indique qu'il contient vos enfants:

<div className={`parent ${hasKiddos ? 'has-kiddos' : ''}`}>
    {kiddos.map(kid => <div key={kid.id} />)}
</div>

Et puis simplement:

.parent {
    color: #000;
}

.parent.has-kiddos {
    color: red;
}
Damiano
la source
0

Il n'y a pas de sélecteur parent css (et donc dans les préprocesseurs css) en raison de "Les principales raisons pour lesquelles le groupe de travail CSS rejetait précédemment les propositions de sélecteurs parents sont liées aux performances du navigateur et aux problèmes de rendu incrémentiel."

Dmitry Sokolov
la source