Sélecteur CSS complexe pour le parent de l’enfant actif

Est-il possible de sélectionner un élément parent en fonction de la classe d’un élément enfant dans la classe? L’exemple qui me concerne concernant la sortie HTML par un joli plugin de menu pour http://drupal.org . La sortie rend comme ceci:

 

Ma question est de savoir s’il est possible d’appliquer un style à l’élément de liste contenant l’ancre avec la classe active. De toute évidence, je préférerais que l’élément de la liste soit marqué comme actif, mais je n’ai pas le contrôle du code qui est produit. Je pourrais faire ce genre de chose en utilisant javascript (JQuery me vient à l’esprit), mais je me demandais s’il y avait un moyen de faire cela en utilisant les sélecteurs CSS.

Juste pour être clair, je veux appliquer un style à l’élément de liste, pas l’ancre.

Malheureusement, il n’y a aucun moyen de le faire avec CSS.

Ce n’est pas très difficile avec JavaScript si:

 // JavaScript code: document.getElementsByClassName("active")[0].parentNode; // jQuery code: $('.active').parent().get(0); // This would be the 's parent 
  • .
  • Selon Wikipedia :

    Les sélecteurs ne peuvent pas monter

    CSS n’offre aucun moyen de sélectionner un parent ou un ancêtre d’élément qui satisfait à certains critères. Un schéma de sélecteur plus avancé (tel que XPath) permettrait des feuilles de style plus sophistiquées. Cependant, les principales raisons pour lesquelles le groupe de travail CSS rejette les propositions de sélecteurs parents sont liées aux performances du navigateur et aux problèmes de rendu incrémentiel.

    Et pour quiconque recherchera SO dans le futur, cela pourrait également être appelé un sélecteur d’ancêtres.

    Mettre à jour:

    Les spécifications du sélecteur de niveau 4 vous permettent de sélectionner la partie du sujet sélectionnée:

    Le sujet du sélecteur peut être explicitement identifié en ajoutant un signe dollar ($) à l’un des sélecteurs composés d’un sélecteur. Bien que la structure des éléments représentée par le sélecteur soit identique avec ou sans le signe dollar, l’indication du sujet de cette manière peut modifier le sélecteur composé représentant le sujet dans cette structure.

    Exemple 1:

    Par exemple, le sélecteur suivant représente un élément de liste LI enfant unique d’une liste ordonnée OL:

     OL > LI:only-child 

    Cependant, la suivante représente une liste ordonnée OL ayant un enfant unique, cet enfant étant un LI:

     $OL > LI:only-child 

    Les structures représentées par ces deux sélecteurs sont les mêmes, mais les sujets des sélecteurs ne le sont pas.

    Bien que ce ne soit pas disponible (actuellement, novembre 2011) dans n’importe quel navigateur ou comme sélecteur dans jQuery.

    Plus tard à la fête, mais pour ce que ça vaut, il est possible d’utiliser jQuery pour être un peu plus succinct. Dans mon cas, je devais trouver la

      parent

        pour une contenue dans l’enfant

      • . jQuery a le sélecteur :has afin qu’il soit possible d’identifier un parent par les enfants qu’il contient (mis à jour par le commentaire de @Afrowave réf: https://api.jquery.com/has-selector/ ):

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

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

         $("li").has(".active") 

        LE SÉLECTEUR “PARENT”

        Pour l’instant, il n’y a pas d’option pour sélectionner le parent d’un élément dans CSS (même pas CSS3). Mais avec CSS4 , la nouvelle la plus importante dans le brouillon W3C actuel est la prise en charge du sélecteur parent.

         $ul li:hover{ background: #fff; } 

        En utilisant ce qui précède, lorsque vous survolez un élément de la liste, toute la liste non ordonnée sera mise en évidence en y ajoutant un arrière-plan blanc.

        Documentation officielle: https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview (dernière ligne).

        La première version du sélecteur de niveau 4 présente un moyen de définir explicitement le sujet d’un sélecteur. Cela permettrait à l’OP de mettre en forme l’élément de liste avec le sélecteur $li > a.active

        De la détermination du sujet d’un sélecteur :

        Par exemple, le sélecteur suivant représente un élément de liste LI enfant unique d’une liste ordonnée OL:

        OL > LI:only-child

        Cependant, la suivante représente une liste ordonnée OL ayant un enfant unique, cet enfant étant un LI:

        $OL > LI:only-child

        Les structures représentées par ces deux sélecteurs sont les mêmes, mais les sujets des sélecteurs ne le sont pas.

        Edit: Compte tenu de la façon dont “drafty” peut être une ébauche de spécification, il est préférable de garder un œil sur cela en vérifiant la page du CSSWG sur les sélecteurs de niveau 4 .

        J’ai eu le même problème avec Drupal. Compte tenu des limitations de CSS, le moyen d’obtenir ce fonctionnement est d’append la classe “active” aux éléments parents lorsque le menu HTML est généré. Il y a une bonne discussion à ce sujet sur http://drupal.org/node/219804 , dont le résultat est que cette fonctionnalité a été intégrée à la version 6.x-2.x du module nicemenus. Comme il est encore en développement, j’ai sauvegardé le correctif sur la version 6.x-1.3 à l’ adresse http://drupal.org/node/465738 afin que je puisse continuer à utiliser la version du module prête pour la production.

        Beaucoup de gens ont répondu avec le parent de jQuery , mais juste pour append à cela je voulais partager un extrait rapide de code que j’utilise pour append des classes à mes navs afin que je puisse append des styles qui n’ont que des sous-menus et pas li c’est pas ça.

         $("li ul").parent().addClass('has-sub'); 

        J’ai en fait rencontré le même problème que l’affiche originale. Il existe une solution simple pour utiliser .parent() sélecteur jQuery .parent() . Mon problème était, j’utilisais .parent au lieu de .parent() . Erreur stupide je sais.

        Liez les événements (dans ce cas, puisque mes tabs sont dans Modal, je devais les lier avec .live au lieu d’un .click base .click .

         $('#testTab1 .tabLink').live('click', function() { $('#modal ul.tabs li').removeClass("current"); //Remove any "current" class $(this).parent().addClass("current"); //Add "current" class to selected tab $('#modal div#testTab1 .tabContent').hide(); $(this).next('.tabContent').fadeIn(); return false; }) $('#testTab2 .tabLink').live('click', function() { $('#modal ul.tabs li').removeClass("current"); //Remove any "current" class $(this).parent().addClass("current"); //Add "current" class to selected tab $('#modal div#testTab2 .tabContent').hide(); $(this).next('.tabContent').fadeIn(); return false; }) 

        Voici le HTML ..

          

        Bien sûr, vous pouvez répéter ce modèle..avec plus de LI

        S’il est vrai que CSS ne peut pas ASCEND, il est incorrect que vous ne puissiez pas saisir l’élément parent d’un autre élément. Permettez-moi de répéter:

        En utilisant votre exemple de code HTML, vous pouvez saisir le li sans spécifier li

         ul * a { property:value; } 

        Dans cet exemple, le ul est le parent de certains éléments et cet élément est le parent de anchor. L’inconvénient de l’utilisation de cette méthode est que s’il existe un ul avec un élément enfant contenant une ancre, il hérite des styles spécifiés.

        Vous pouvez également utiliser le sélecteur enfant car vous devrez quand même spécifier l’élément parent.

         ul>li a { property:value; } 

        Dans cet exemple, l’ancre doit être un descendant d’un li qui DOIT être un enfant de ul, ce qui signifie qu’il doit être dans l’arbre suivant la déclaration ul. Cela va être un peu plus précis et ne va récupérer qu’un élément de liste contenant une ancre ET est un enfant de ul.

        SO, pour répondre à votre question par code.

         ul.menu > li a.active { property:value; } 

        Cela devrait récupérer le ul avec la classe de menu et l’élément de liste enfant qui ne contient qu’une ancre avec la classe active.

        Une autre pensée m’a semblé tout à l’heure, qui pourrait être une pure solution CSS. Affichez votre classe active en tant que bloc positionné de manière absolue et définissez son style pour couvrir le li parent.

         a.active { position:absolute; display:block; width:100%; height:100%; top:0em; left:0em; background-color: whatever; border: whatever; } /* will also need to make sure the parent li is a positioned element so... */ ul.menu li { position:relative; } 

        Pour ceux d’entre vous qui veulent utiliser javascript sans jquery …

        La sélection du parent est sortingviale. Vous avez besoin d’une fonction getElementsByClass , à moins que vous ne puissiez obtenir votre plugin drupal pour atsortingbuer un identifiant à l’élément actif au lieu de Class. La fonction que j’ai fournie, je l’ai attrapé d’un autre génie sur SO. Cela fonctionne bien, gardez simplement à l’esprit, lorsque vous déboguez, que la fonction retournera toujours un tableau de nœuds, pas seulement un seul nœud.

         active_li = getElementsByClass("active","a"); active_li[0].parentNode.style.whatever="whatever"; function getElementsByClass(node,searchClass,tag) { var classElements = new Array(); var els = node.getElementsByTagName(tag); // use "*" for all elements var elsLen = els.length; var pattern = new RegExp("\\b"+searchClass+"\\b"); for (i = 0, j = 0; i < elsLen; i++) { if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; } } return classElements; }