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

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

Complex CSS selector for parent of active child

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ul class="menu">  
   
<li>
 
        Active Page  
   
</li>
 
   
<li>
   
        Some Other Page  
   
</li>
 

</ul>

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

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


根据维基百科:

Selectors are unable to ascend

CSS offers no way to select a parent or ancestor of element that satisfies certain criteria. A more advanced selector scheme (such as XPath) would enable more sophisticated stylesheets. However, the major reasons for the CSS Working Group rejecting proposals for parent selectors are related to browser performance and incremental rendering issues.

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

更新:

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

The subject of the selector can be explicitly identified by prepending
a dollar sign ($) to one of the compound selectors in a selector.
Although the element structure that the selector represents is the
same with or without the dollar sign, indicating the subject in this
way can change which compound selector represents the subject in that
structure.

Example 1:

For example, the following selector represents a list item LI unique child of
an ordered list OL:

1
OL > LI:only-child

However the following one represents an ordered list OL having a unique child,
that child being a LI:

1
$OL > LI:only-child

The structures represented by these two selectors are the same,
but the subjects of the selectors are not.

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


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

但是使用JavaScript并不是很困难:

1
2
3
4
5
6
7
// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;

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


迟到了派对,但是为了它的价值,可以使用jQuery更简洁一些。在我的情况下,我需要找到包含在子

  • 中的标记的

      父标记。 jQuery具有:has选择器,因此可以通过它包含的子节点识别父节点(根据@ Afrowave的注释ref:https://api.jquery.com/has-selector/更新):

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

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

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

      "父母"选择者

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

      1
      2
      3
      $ul li:hover{
          background: #fff;
      }

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

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


      选择器级别4的初稿概述了一种显式设置选择器主题的方法。这将允许OP使用选择器$li > a.active设置list元素的样式

      从确定选择器的主题:

      For example, the following selector represents a list item LI unique child of an ordered list OL:

      OL > LI:only-child

      However the following one represents an ordered list OL having a unique child, that child being a LI:

      $OL > LI:only-child

      The structures represented by these two selectors are the same, but the subjects of the selectors are not.

      编辑:鉴于规范草案的"草率"如何,最好通过检查4级选择器上的CSSWG页面来关注这一点。


      CSS4选择器的未来答案

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

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

      此时浏览器支持基本上不存在,但它在官方规范中考虑。

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

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

      使用HTML示例代码,您可以在不指定li的情况下获取li

      1
      2
      3
      ul * a {
          property:value;
      }

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

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

      1
      2
      3
      ul>li a {
          property:value;
      }

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

      那么,通过代码回答你的问题。

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

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


      许多人回答了jQuery父级,但只是为了补充,我想分享一个快速的代码片段,我用它来为我的导航器添加类,所以我可以添加样式到li的只有子菜单,而不是li的菜单。

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

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

      绑定事件(在这种情况下,因为我的选项卡在Modal中,我需要用.live而不是基本.click绑定它们。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      $('#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 ..

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
        <!-- start: the code for tabView 1 -->
       
          <h1 class="Bold_Gray_45px">Modal Header
         
          <ul class="tabs">
            <li class="current"> Tab Title Link
             
               
                  <p>
      Your Tab Content
      </p>
                  <p>
      tabBased Anchor Link
      </p>
               
                 
             
           
      </li>

           
      <li>
       Tab Title Link
             
               
                  <p>
      Your Tab Content
      </p>
                  <p>
      tabBased Anchor Link
      </p>
               
                 
             
           
      </li>

         
      </ul>

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


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


      刚才我想到的另一个想法是纯CSS解决方案。将活动类显示为绝对定位的块,并将其样式设置为覆盖父li。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      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上抓住了其他一些天才。它运行良好,在您调试时请记住该函数将始终返回节点数组,而不仅仅是单个节点。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      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;
      }


  • 推荐阅读