活动子的父级的复杂CSS选择器

时间:2008-09-05 00:01:36

标签: css css-selectors

有没有办法根据类中子元素的类选择父元素?与我相关的示例与http://drupal.org的精美菜单插件的HTML输出相关。输出呈现如下:

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

我的问题是,是否可以将样式应用于包含具有活动类的锚的列表项。显然,我更喜欢将列表项标记为活动,但我无法控制生成的代码。我可以使用javascript(JQuery spring to mind)执行此类操作,但我想知道是否有办法使用CSS选择器来执行此操作。

为了清楚起见,我想将样式应用于列表项,而不是锚点。

10 个答案:

答案 0 :(得分:234)

According to Wikipedia

  

选择器无法提升

     
    

CSS无法选择满足特定条件的元素的父元素或祖先元素。更高级的选择器方案(例如XPath)将启用更复杂的样式表。但是,CSS工作组拒绝父选择器提案的主要原因与浏览器性能和增量渲染问题有关。

  

对于将来搜索SO的任何人来说,这也可能被称为祖先选择器。

更新:

Selectors Level 4 Spec允许您选择选择的哪个部分是主题:

  

可以通过预先明确地明确识别选择器的主题   美元符号($)到选择器中的一个复合选择器。   虽然选择器表示的元素结构是   是否有美元符号,表示此主题   方式可以改变哪个复合选择器代表其中的主题   结构

     

示例1:

     

例如,以下选择器表示列表项LI唯一子项   有序列表OL:

OL > LI:only-child
     

然而,以下一个表示具有唯一孩子的有序列表OL,   那个孩子是李:

$OL > LI:only-child
     

这两个选择器所代表的结构是相同的,   但是选择者的主题不是。

虽然这在任何浏览器中都不可用(目前,2011年11月),或者作为jQuery中的选择器。

答案 1 :(得分:143)

不幸的是,用CSS没办法做到这一点。

但使用JavaScript并不是很困难:

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

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

答案 2 :(得分:39)

再次参加聚会,但是为了它的价值,使用jQuery可能会更简洁一些。在我的情况下,我需要找到包含在子<ul>中的<span>标记的<li>父标记。 jQuery具有:has选择器,因此可以通过它包含的子节点识别父节点(根据@ Afrowave的注释ref https://api.jquery.com/has-selector/更新):

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

将选择具有id someId 的子元素的ul元素。或者回答原始问题,类似下面的内容应该可以做到(未经测试):

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

答案 3 :(得分:28)

“父母”选择者

现在,没有选择在CSS中选择元素的父元素(甚至不是CSS3)。但是对于 CSS4 ,当前W3C草案中最重要的新闻是对父选择器的支持。

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

使用上面的内容,当悬停列表元素时,整个无序列表将通过添加白色背景来突出显示。

官方文件:https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview(最后一行)。

答案 4 :(得分:16)

Selectors Level 4的初稿概述了一种明确设置选择器的主题的方法。这将允许OP使用选择器$li > a.active

设置list元素的样式

来自Determining the Subject of a Selector

  

例如,以下选择器表示有序列表OL的列表项LI唯一子项:

     

OL > LI:only-child

     

然而,下面的代表一个有序列表OL,它有一个独特的孩子,那个孩子是LI:

     

$OL > LI:only-child

     

这两个选择器所代表的结构是相同的,但选择器的主体不是。

编辑:鉴于规范草案的“草率”如何,最好通过查看CSSWG's page on selectors level 4来了解相关信息。

答案 5 :(得分:2)

CSS4选择器的未来答案

新的CSS规范包含一个实验性:has伪选择器,可能能够做到这一点。

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

browser support目前基本上不存在official specs,但在{{3}}上考虑了这一点。


在2012年回答2012年的错误,2018年更加错误

虽然CSS不能ASCEND,但是你不能抓住另一个元素的父元素是不正确的。让我重申一下:

使用您的HTML示例代码,您可以在不指定li

的情况下获取li
ul * a {
    property:value;
}

在此示例中,ul是某个元素的父元素,该元素是锚点的父元素。使用此方法的缺点是,如果有一个包含锚的任何子元素的ul,它将继承指定的样式。

您也可以使用子选择器,因为您无论如何都必须指定父元素。

ul>li a {
    property:value;
}

在这个例子中,锚必须是li的后代,它必须是ul的子元素,这意味着它必须在ul声明之后的树中。这将更加具体,只会获取包含锚点的列表项并且是ul的子项。

所以,按代码回答你的问题。

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

这应该使用菜单类获取ul,以及仅包含活动类的锚的子列表项。

答案 6 :(得分:1)

我和Drupal有同样的问题。鉴于CSS的局限性,实现此方法的方法是在生成菜单HTML时将“活动”类添加到父元素。在http://drupal.org/node/219804有一个很好的讨论,其结果是这个功能已经被转移到nicemenus模块的6.x-2.x版本。由于这仍处于开发阶段,我已将补丁向后移植到http://drupal.org/node/465738的6.x-1.3,以便我可以继续使用模块的生产就绪版本。

答案 7 :(得分:1)

我实际上遇到了与原始海报相同的问题。有一个简单的解决方案,只使用.parent() jQuery选择器。我的问题是,我使用的是.parent而不是.parent()。我知道这个愚蠢的错误。

绑定事件(在这种情况下,因为我的标签位于模态中,我需要将它们与.live绑定,而不是基本.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;
})

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

当然你可以重复那种模式......更多LI的

答案 8 :(得分:1)

许多人使用jQuery家长回答,但只是为了补充一点,我想分享一小段代码,用于向我的导航中添加类,以便我可以为li添加样式那只有子菜单而不是li没有。

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

答案 9 :(得分:0)

刚才我想到的另一个想法是纯CSS解决方案。将您的活动类显示为绝对定位的块,并将其样式设置为覆盖父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;
}    

对于那些想要在没有jquery的情况下使用javascript的人......

选择父母是微不足道的。您需要某种getElementsByClass函数,除非您可以让您的drupal插件为活动项分配ID而不是Class。我提供的功能是我从SO上抓住了其他一些天才。它运行良好,在您调试时请记住该函数将始终返回节点数组,而不仅仅是单个节点。

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