Sélecteur CSS complexe pour parent d'enfant actif [dupliquer]

cette question a déjà une réponse ici:

Est-il un moyen pour sélectionner un élément parent basé sur la classe d'un élément enfant dans la classe? L'exemple qui est pertinent pour moi concernant la sortie HTML par un plugin de menu agréable pour http://drupal.org . La sortie rend comme ceci:

<ul class="menu">  
    <li>  
        <a class="active">Active Page</a>  
    </li>  
    <li>    
        <a>Some Other Page</a>  
    </li>  
</ul>  

ma question Est de savoir s'il est possible d'appliquer un style à l'élément de la liste qui contient l'ancre avec la classe active dessus. Évidemment, je préférerais que la liste soit marquée comme active, mais je n'ai pas le contrôle du code qui est produit. Je pourrais effectuer ce genre de chose en utilisant javascript (jQuery springs à l'esprit), mais je me demandais s'il y avait un moyen de faites ceci en utilisant les sélecteurs CSS.

juste pour être clair, je veux appliquer un style à l'élément de la liste, pas l'ancre.

280
demandé sur BoltClock 2008-09-05 04:01:36

10 réponses

malheureusement, il n'y a aucun moyen de faire ça avec CSS.

ce N'est pas très difficile avec JavaScript cependant:

// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;

// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.
135
répondu Dave Ward 2012-08-21 03:49:27

selon Wikipedia :

les sélecteurs ne peuvent pas monter

CSS offre pas la possibilité de sélectionner un parent ou un ancêtre de l'élément qui satisfait à certains critères. Un système de sélecteur plus avancé (tel que XPath) permettrait des feuilles de style plus sophistiquées. Toutefois, les principales raisons pour lesquelles le groupe de travail CSS a rejeté les propositions de sélecteurs parents sont les suivantes: lié aux performances du navigateur et aux problèmes de rendu incrémentiel.

et pour toute personne cherchant ainsi à l'avenir, cela pourrait également être appelé un sélecteur d'ancêtre.

mise à jour:

le sélecteurs Niveau 4 Spec vous permet de sélectionner quelle partie de la select est le sujet:

l'objet du sélecteur peut être explicitement identifié par la préprogrammation un signe dollar ( $ ) pour l'un des sélecteurs composés d'un sélecteur. Bien que la structure de l'élément que le sélecteur représente l' même chose avec ou sans le signe du dollar, en indiquant le sujet dans ce la manière peut changer quel sélecteur de composé représente le sujet dans ce structure.

exemple 1:

par exemple, le sélecteur suivant représente un élément de liste LI unique enfant de une liste de commandes:

OL > LI:only-child

cependant le suivant représente une liste ordonnée D'avoir 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 n'est pas disponible (actuellement, novembre 2011) dans n'importe quel navigateur ou comme un sélecteur dans jQuery.

227
répondu Sam Hasler 2012-02-20 17:17:09

en retard à la fête encore mais pour ce que cela vaut il est possible d'utiliser jQuery pour être un peu plus succinct. Dans mon cas, je devais trouver le <ul> étiquette parent pour un <span> étiquette contenue dans l'enfant <li> . jQuery a le sélecteur :has donc il est 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")

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

$("li").has(".active")
38
répondu David Clarke 2017-09-26 01:19:47

LE SÉLECTEUR" PARENT

pour le moment, il n'y a aucune option pour sélectionner le parent d'un élément dans CSS (pas même CSS3). Mais avec CSS4 , la nouvelle la plus importante dans la version actuelle du W3C est le support du sélecteur parent.

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

en utilisant ce qui précède, lors de la mise en relief d'un élément de liste, toute la liste non ordonnée sera mise en évidence par l'ajout d'un fond blanc.

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

27
répondu Praveen Kumar Purushothaman 2016-04-02 10:12:18

la première ébauche des sélecteurs Niveau 4 décrit une façon de définir explicitement le sujet d'un sélecteur. Cela permettrait à L'OP de style l'élément list avec le sélecteur $li > a.active

de déterminant l'objet d'un sélecteur :

par exemple, le sélecteur suivant représente un item LI unique enfant d'une liste commandée:

OL > LI:only-child

cependant la suivante représente une liste ordonnée D'avoir 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 de les sélecteurs sont pas.

Edit: compte tenu de la façon dont "draftty" un projet de spécification peut être, il est préférable de garder un oeil sur ce en vérifiant le CSSWG page sur les sélecteurs de niveau 4 .

16
répondu btlachance 2011-11-23 18:40:24

J'ai eu le même problème avec Drupal. Étant donné les limites de CSS, la façon d'obtenir ce fonctionnement est d'ajouter la classe "active" aux éléments parents lorsque le menu HTML est généré. Il y a une bonne discussion à ce sujet à 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 c'est encore en développement, j'ai intégré le patch à 6.x-1.3 http://drupal.org/node/465738 pour que je puisse continuer à utiliser la version du module prête à la production.

1
répondu Mark B 2009-05-18 12:14:36

beaucoup de gens ont répondu avec jQuery parent, mais juste pour ajouter à cela, je voulais partager un petit morceau de code que j'utilise pour ajouter des classes à mon navs afin que je puisse ajouter le style à li 's qui n'ont que des sous-menus et pas li 's qui ne le font pas.

$("li ul").parent().addClass('has-sub');
1
répondu GGedde 2013-01-28 07:09:52

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

lient les événements (dans ce cas, puisque mes onglets sont en mode Modal, j'ai dû les lier avec .live au lieu d'un .click de base .

$('#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..

<div id="tabView1" style="display:none;">
  <!-- start: the code for tabView 1 -->
  <div id="testTab1" style="width:1080px; height:640px; position:relative;">
    <h1 class="Bold_Gray_45px">Modal Header</h1>
    <div class="tabBleed"></div>
    <ul class="tabs">
      <li class="current"> <a href="#" class="tabLink" id="link1">Tab Title Link</a>
        <div class="tabContent" id="tabContent1-1">
          <div class="modalCol">
            <p>Your Tab Content</p>
            <p><a href="#" class="tabShopLink">tabBased Anchor Link</a> </p>
          </div>
          <div class="tabsImg"> </div>
        </div>
      </li>
      <li> <a href="#" class="tabLink" id="link2">Tab Title Link</a>
        <div class="tabContent" id="tabContent1-2">
          <div class="modalCol">
            <p>Your Tab Content</p>
            <p><a href="#" class="tabShopLink">tabBased Anchor Link</a> </p>
          </div>
          <div class="tabsImg"> </div>
        </div>
      </li>
    </ul>
  </div>
</div>

bien sûr, vous pouvez répéter ce motif..avec plus de LI's

1
répondu jdrefahl 2016-02-05 16:02:18

bien qu'il soit vrai que CSS ne peut pas ascensionner, 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 code D'exemple HTML, vous pouvez saisir le li Sans spécifier li

ul * a {
    property:value;
}

Dans cet exemple, l'ul est le parent d'un élément et l'élément est le parent de l'ancre. L'inconvénient de cette méthode est que s'Il ya un ul avec un élément enfant qui contient anchor hérite des styles spécifiés.

vous pouvez également utiliser le sélecteur d'enfant puisque vous devrez de toute façon 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 d'ul, CE qui signifie qu'il doit être dans l'arbre suivant la déclaration ul. Cela va être un peu plus spécifique et ne prendra qu'un élément de liste qui contient une ancre et est un enfant de ul.

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

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

cela devrait saisir l'ul avec la classe de menu, et l'élément de la liste des enfants qui ne contient qu'une ancre avec la classe d'actif.

0
répondu Matt Wagner 2012-06-13 17:37:00

une autre pensée m'est venue tout à l'heure qui pourrait être une solution pure CSS. Affichez votre classe active comme un bloc absolument positionné 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 triviale. Vous avez besoin d'une fonction getElementsByClass d'une sorte ou d'une autre, à moins que vous ne puissiez obtenir votre plugin drupal pour assigner un ID à l'élément actif au lieu d'une classe. Le la fonction que j'ai fournie j'ai attrapé d'un autre génie sur ainsi. Il fonctionne bien, il suffit de garder à l'esprit lorsque vous déboguez que la fonction retournera toujours un tableau de nœuds, pas 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;
}
0
répondu Jared 2012-10-26 23:56:07