Pergunta

Essa pergunta já tem resposta aqui:

Existe uma maneira de selecionar um elemento pai com base na classe de um elemento filho da classe?O exemplo que é relevante para mim em relação à saída HTML de um ótimo plugin de menu para http://drupal.org.A saída é renderizada assim:

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

Minha dúvida é se é possível ou não aplicar um estilo ao item da lista que contém a âncora com a classe ativa.Obviamente, prefiro que o item da lista seja marcado como ativo, mas não tenho controle do código produzido.Eu poderia realizar esse tipo de coisa usando javascript (JQuery me vem à mente), mas queria saber se existe uma maneira de fazer isso usando seletores CSS.

Só para deixar claro, quero aplicar um estilo ao item da lista, não à âncora.

Foi útil?

Solução

Infelizmente, não há como fazer isso com CSS.

Porém, não é muito difícil com JavaScript:

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

// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.

Outras dicas

De acordo com a Wikipédia:

Os seletores não conseguem subir

CSS não oferece nenhuma maneira de selecionar um pai ou ancestral de elemento que satisfaça determinados critérios.Um esquema de seletor mais avançado (como XPath) permitiria folhas de estilo mais sofisticadas.No entanto, as principais razões para o Grupo de Trabalho CSS rejeitar propostas para seletores pais estão relacionadas ao desempenho do navegador e a problemas de renderização incremental.

E para qualquer pessoa que pesquisar SO no futuro, isso também poderá ser chamado de seletor de ancestral.

Atualizar:

O Especificações de nível 4 dos seletores permite selecionar qual parte do select é o assunto:

O sujeito do seletor pode ser explicitamente identificado, precendendo um sinal de dólar ($) para um dos seletores de compostos em um seletor.Embora a estrutura do elemento que o seletor represente seja a mesma com ou sem o sinal de dólar, indicando que o sujeito dessa maneira pode alterar qual seletor de composto representa o sujeito nessa estrutura.

Exemplo 1:

Por exemplo, o seletor a seguir representa um item de lista Li Li Fill On a List Orded OL:

OL > LI:only-child

No entanto, o seguinte representa uma lista ordenada com uma criança única, sendo a criança uma Li:

$OL > LI:only-child

As estruturas representadas por esses dois seletores são as mesmas, mas os sujeitos dos seletores não são.

Embora não esteja disponível (atualmente, novembro de 2011) em nenhum navegador ou como seletor no jQuery.

Atrasado para a festa de novo, mas pelo que vale a pena é possível usar jQuery para ser um pouco mais sucinto.No meu caso eu precisava encontrar o <ul> tag pai para um <span> tag contida no filho <li>.jQuery tem o :has seletor para que seja possível identificar um pai pelos filhos que ele contém (atualizado de acordo com o comentário do @Afrowave ref: https://api.jquery.com/has-selector/):

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

selecionará o ul elemento que possui um elemento filho com id algumId.Ou, para responder à pergunta original, algo como o seguinte deve resolver o problema (não testado):

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

O SELETOR “PAIS”

No momento, não há opção para selecionar o pai de um elemento em CSS (nem mesmo em CSS3).Mas com CSS4, a novidade mais importante no rascunho atual do W3C é o suporte ao seletor pai.

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

Usando o acima, ao passar o mouse sobre um elemento da lista, toda a lista não ordenada será destacada adicionando um fundo branco a ela.

Documentação oficial: https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview (última fila).

O primeiro rascunho de Seletores Nível 4 descreve uma maneira de definir explicitamente o assunto de um seletor.Isso permitiria ao OP estilizar o elemento da lista com o seletor $li > a.active

De Determinando o assunto de um seletor:

Por exemplo, o seletor a seguir representa um item de lista LI, filho exclusivo de uma lista ordenada OL:

OL > LI:only-child

Porém o seguinte representa uma lista ordenada OL tendo um filho único, sendo esse filho um LI:

$OL > LI:only-child

As estruturas representadas por estes dois seletores são as mesmas, mas os assuntos dos seletores não são.

Editar:Dado o quão "esboçado" um rascunho de especificação pode ser, é melhor manter o controle sobre isso, verificando o Página do CSSWG sobre seletores de nível 4.

Resposta futura com seletores CSS4

As novas especificações CSS contêm uma versão experimental :has pseudo seletor que pode ser capaz de fazer isso.

li:has(a:active) {
  /* ... */
}

O suporte ao navegador sobre isso é basicamente inexistente neste momento, mas está em consideração no especificações oficiais.


Resposta em 2012 que estava errada em 2012 e está ainda mais errada em 2018

Embora seja verdade que CSS não pode ASCEND, é incorreto dizer que você não pode capturar o elemento pai de outro elemento.Deixe-me reiterar:

Usando seu código de exemplo HTML, você pode capturar li sem especificar li

ul * a {
    property:value;
}

Neste exemplo, ul é o pai de algum elemento e esse elemento é o pai da âncora.A desvantagem de usar esse método é que se houver um ul com qualquer elemento filho que contenha uma âncora, ele herdará os estilos especificados.

Você também pode usar o seletor filho, pois terá que especificar o elemento pai de qualquer maneira.

ul>li a {
    property:value;
}

Neste exemplo, a âncora deve ser descendente de um li que DEVE ser filho de ul, o que significa que deve estar dentro da árvore após a declaração ul.Isso será um pouco mais específico e capturará apenas um item da lista que contém uma âncora E é filho de ul.

Então, para responder sua pergunta por código.

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

Isso deve pegar o ul com a classe de menu e o item da lista filho que contém apenas uma âncora com a classe de ativo.

Eu tive o mesmo problema com o Drupal.Dadas as limitações do CSS, a maneira de fazer isso funcionar é adicionar a classe "ativa" aos elementos pai quando o HTML do menu é gerado.Há uma boa discussão sobre isso em http://drupal.org/node/219804, o resultado disso é que essa funcionalidade foi implementada na versão 6.x-2.x do módulo nicemenus.Como isso ainda está em desenvolvimento, fiz backport do patch para 6.x-1.3 em http://drupal.org/node/465738 para que eu possa continuar a usar a versão do módulo pronta para produção.

Muitas pessoas responderam com jQuery pai, mas só para acrescentar isso, gostaria de compartilhar um trecho rápido de código que uso para adicionar classes aos meus navegadores para que possa adicionar estilo a lié que só tem sub-menus e não liisso não acontece.

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

Na verdade, encontrei o mesmo problema do autor da postagem original.Existe uma solução simples de apenas usar .parent() seletor jQuery.Meu problema era que eu estava usando .parent em vez de .parent().Erro estúpido, eu sei.

Vincule os eventos (neste caso como minhas abas estão em Modal eu precisei vinculá-los com .live em vez de um básico .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;
})

Aqui está o 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>

Claro que você pode repetir esse padrão..com mais LI's

Outro pensamento me ocorreu agora mesmo que poderia ser uma solução CSS pura.Exiba sua classe ativa como um bloco absolutamente posicionado e defina seu estilo para encobrir o pai li.

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

Para aqueles que desejam usar javascript sem jquery...

Selecionar o pai é trivial.Você precisa de um getElementsByClass função de algum tipo, a menos que você consiga fazer com que seu plug-in drupal atribua ao item ativo um ID em vez de Classe.A função que forneci foi obtida de algum outro gênio do SO.Funciona bem, mas lembre-se, ao depurar, que a função sempre retornará uma matriz de nós, não apenas um único nó.

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top