Сложный селектор CSS для родителя активного дочернего элемента [дубликат]

StackOverflow https://stackoverflow.com/questions/45004

  •  09-06-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

Есть ли способ выбрать родительский элемент на основе класса дочернего элемента в классе?Пример, который имеет отношение ко мне, касается вывода HTML с помощью хорошего плагина меню для http://drupal.org.Вывод выглядит следующим образом:

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

Мой вопрос заключается в том, можно ли применить стиль к элементу списка, содержащему привязку с активным классом.Очевидно, я бы предпочел, чтобы элемент списка был помечен как активный, но я не могу контролировать создаваемый код.Я мог бы выполнить подобные действия с помощью javascript (на ум приходит JQuery), но мне было интересно, есть ли способ сделать это с помощью селекторов CSS.

Чтобы внести ясность: я хочу применить стиль к элементу списка, а не к привязке.

Это было полезно?

Решение

К сожалению, с помощью CSS этого сделать невозможно.

Однако с JavaScript это не очень сложно:

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

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

Другие советы

По данным Википедии:

Селекторы не могут подняться

CSS не предлагает возможности выбрать родителя или предка элемента, который удовлетворяет определенным критериям.Более продвинутая схема выбора (например, XPath) позволит использовать более сложные таблицы стилей.Однако основные причины отклонения рабочей группой CSS предложений по родительским селекторам связаны с производительностью браузера и проблемами инкрементного рендеринга.

И для тех, кто будет искать SO в будущем, это также можно назвать селектором предков.

Обновлять:

А Селекторы уровня 4 Спецификация позволяет вам выбрать, какая часть выделения является предметом:

Предмет селектора может быть явно идентифицирован путем приготовления знака доллара ($) одному из составных селекторов в селекторе.Хотя структура элемента, которую представляет селектор, такая же с знаком доллара или без них, указываясь на этот субъект таким образом, может изменить, какой селектор соединений представляет субъект в этой структуре.

Пример 1:

Например, следующий селектор представляет собой элемент списка LI уникальный ребенок упорядоченного списка OL:

OL > LI:only-child

Однако следующее представляет собой упорядоченный список, имеющий уникального ребенка, этот ребенок - это Ли:

$OL > LI:only-child

Структуры, представленные этими двумя селекторами, одинаковы, но субъекты селекторов нет.

Хотя это недоступно (на данный момент, ноябрь 2011 г.) ни в одном браузере или в качестве селектора в jQuery.

Снова опоздал на вечеринку, но, чего бы это ни стоило, можно использовать jQuery, чтобы быть немного более кратким.В моем случае мне нужно было найти <ul> родительский тег для <span> тег, содержащийся в дочернем элементе <li>.jQuery имеет :has селектор, чтобы можно было идентифицировать родителя по содержащимся в нем дочерним элементам (обновлено согласно комментарию @Afrowave, ссылка: https://api.jquery.com/has-selector/):

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

выберет ul элемент, у которого есть дочерний элемент с идентификатором какой-то идентификатор.Или, чтобы ответить на исходный вопрос, что-то вроде следующего должно помочь (непроверено):

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

«РОДИТЕЛЬСКИЙ» СЕЛЕКТОР

На данный момент в CSS (даже CSS3) нет возможности выбрать родительский элемент элемента.Но с CSS4, Самая важная новость в текущем проекте W3C — поддержка родительского селектора.

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

Используя вышеизложенное, при наведении курсора на элемент списка весь неупорядоченный список будет выделен путем добавления к нему белого фона.

Официальная документация: https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview (последний ряд).

Первый проект Селекторы уровня 4 описывает способ явно установить предмет селектора.Это позволит ОП стилизовать элемент списка с помощью селектора. $li > a.active

От Определение темы селектора:

Например, следующий селектор представляет уникальный дочерний элемент списка LI упорядоченного списка OL:

OL > LI:only-child

Однако следующий представляет собой упорядоченный список OL, имеющий уникального дочернего элемента, причем этот дочерний элемент является LI:

$OL > LI:only-child

Структуры, представленные этими двумя селекторами, одинаковы, но субъекты селекторов — нет.

Редактировать:Учитывая, насколько «черновым» может быть черновой вариант спецификации, лучше всего следить за ним, проверяя Страница CSSWG на уровне селекторов 4.

Будущий ответ с селекторами CSS4

Новые спецификации CSS содержат экспериментальную :has псевдоселектор, который может это сделать.

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

А поддержка браузера на данный момент по этому вопросу практически не существует, но он рассматривается на официальные характеристики.


Ответ в 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 с классом меню и элемент дочернего списка, который содержит только привязку с активным классом.

У меня была такая же проблема с Drupal.Учитывая ограничения CSS, способ заставить это работать — добавить «активный» класс к родительским элементам при создании HTML-меню.Есть хорошее обсуждение этого на http://drupal.org/node/219804, в результате чего эта функциональность была добавлена ​​в версию 6.x-2.x модуля nicemenus.Поскольку он все еще находится в разработке, я перенес патч на версию 6.x-1.3 по адресу: http://drupal.org/node/465738 чтобы я мог продолжать использовать готовую к использованию версию модуля.

Многие люди ответили jQuery родителем, но в дополнение к этому я хотел бы поделиться небольшим фрагментом кода, который я использую для добавления классов в свою навигацию, чтобы я мог добавить стиль к liу которых есть только подменю, а не liэто не так.

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

На самом деле я столкнулся с той же проблемой, что и исходный плакат.Существует простое решение: просто использовать .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.

Только что мне пришла в голову еще одна мысль, которая могла бы быть решением на чистом 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;
}    

Для тех из вас, кто хочет использовать JavaScript без jquery...

Выбор родителя тривиален.Тебе необходимо getElementsByClass какую-то функцию, если только вы не можете заставить свой плагин Drupal присваивать активному элементу идентификатор вместо класса.Предоставленную мной функцию я взял у какого-то другого гения 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top