Как стилизовать родительский элемент при наведении на дочерний элемент?


160

Я знаю, что не существует родительского селектора CSS , но возможно ли стилизовать родительский элемент при наведении на дочерний элемент без такого селектора?

В качестве примера: рассмотрим кнопку удаления, которая при наведении подсвечивает элемент, который собирается удалить:

<div>
    <p>Lorem ipsum ...</p>
    <button>Delete</button>
</div>

С помощью чистого CSS, как изменить цвет фона этого раздела, когда мышь находится над кнопкой?



Ответы:


134

Ну, этот вопрос задавался много раз раньше, и короткий типичный ответ таков: это не может быть сделано простым CSS. Это в названии: каскадные таблицы стилей поддерживают стилизацию только в каскадном направлении, но не вверх.

Но в большинстве случаев, когда этот эффект желателен, как в данном примере, все еще существует возможность использовать эти каскадные характеристики для достижения желаемого эффекта. Рассмотрим эту псевдо-разметку:

<parent>
    <sibling></sibling>
    <child></child>
</parent>

Хитрость заключается в том, чтобы дать брату тот же размер и положение, что и у родителя, и стилизовать родного брата вместо родителя. Это будет выглядеть как родительский стиль!

Теперь, как уложить родного брата?

Когда ребенок находится под охраной, родитель тоже, а брат - нет. То же самое касается брата и сестры. Это завершается тремя возможными путями селектора CSS для стилизации родного брата:

parent sibling { }
parent sibling:hover { }
parent:hover sibling { }

Эти разные пути дают хорошие возможности. Например, использование этого трюка на примере в вопросе приводит к этой скрипке :

div {position: relative}
div:hover {background: salmon}
div p:hover {background: white}
div p {padding-bottom: 26px}
div button {position: absolute; bottom: 0}

Пример стиля родительского изображения

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

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


1
Это хорошо для выделения, но не поможет, если вы попытаетесь изменить цвет шрифта, я прав?
Джаханзеб Хан

1
@JahanzebKhan Изменение цвета шрифта не проблема .
NGLN

117

Я знаю, что это старый вопрос, но мне просто удалось сделать это без псевдо-ребенка (но псевдо-оболочки).

Если для родительского элемента задано значение no pointer-events, а для дочернего divэлемента - pointer-eventsset auto, это работает :)
Обратите внимание, что <img>тег (например) не работает.
Также не забудьте установить pointer-eventsдля autoдругих детей , которые имеют свой собственный слушатель событий, или в противном случае они потеряют свою функциональность мыши.

div.parent {  
    pointer-events: none;
}

div.child {
    pointer-events: auto;
}

div.parent:hover {
    background: yellow;
}    
<div class="parent">
  parent - you can hover over here and it won't trigger
  <div class="child">hover over the child instead!</div>
</div>

Изменить:
Как любезно отметил Shadow Wizard : стоит упомянуть, что это не будет работать для IE10 и ниже. (Старые версии FF и Chrome тоже смотрите здесь )


3
Стоит отметить, что это не будет работать для IE10 и ниже. (Старые версии FF и Chrome тоже см. Здесь )
Shadow Wizard - это Ear For You

2
Установка указателей на none также означает, что прослушиватели событий для этого элемента не будут работать!
Разен

1
@ rhazen, ты абсолютно прав. Хотя по моему опыту это использование обычно связано с областью / элементом одного щелчка, поэтому вы можете назначить прослушиватель щелчка для родителя
guy_m

Как насчет того, если у меня есть два уровня, parent, child1 и child of child1. Я добавил указатель-события none к родительскому элементу и auto-событий-указателей auto для дочернего элемента. Я хочу навести
Nam Lê Quý

13

Другой, более простой подход (к старому вопросу) ..
будет размещать элементы как братьев и сестер и использовать:

Селектор соседнего брата ( +) или общий селектор брака ( ~)

<div id="parent">
  <!-- control should come before the target... think "cascading" ! -->
  <button id="control">Hover Me!</button>
  <div id="target">I'm hovered too!</div>
</div>
#parent {
  position: relative;
  height: 100px;
}

/* Move button control to bottom. */
#control {
  position: absolute;
  bottom: 0;
}

#control:hover ~ #target {
  background: red;
}

введите описание изображения здесь

Демо-скрипка здесь .


1
Стоит отметить, что это работает только #targets после #control в DOM (т.е. вы не можете влиять на предыдущих братьев и сестер, только на следующих братьев и сестер)
Gio

10

нет CSS-селектора для выбора родителя выбранного дочернего элемента.

Вы можете сделать это с помощью JavaScript


3
правда. что-то вроде $ (child) .hover (function () {$ (this) .closest (parentSelector) .addClass ('hoverClass')}, function () {$ (this) .closest (parentSelector) .removeClass ('hoverClass' )});
Амир Африди

8
@AamirAfridi Это не чистый JS, но вы должны использовать jQuery с этим.
Ivotje50

6

Как упоминалось ранее, «нет CSS-селектора для выбора родителя выбранного дочернего элемента».

Так что вы либо:


Вот пример для JavaScript / JQuery решения

На стороне JavaScript:

$('#my-id-selector-00').on('mouseover', function(){
  $(this).parent().addClass('is-hover');
}).on('mouseout', function(){
  $(this).parent().removeClass('is-hover');
})

А на стороне CSS у вас будет что-то вроде этого:

.is-hover {
  background-color: red;
}

3

Это решение полностью зависит от дизайна, но если у вас есть родительский div, на который вы хотите изменить фон при наведении на ребенка, вы можете попытаться имитировать родителя с помощью ::after/ ::before.

<div class="item">
    design <span class="icon-cross">x</span>
</div>

CSS:

.item {
    background: blue;
    border-radius: 10px;
    position: relative;
    z-index: 1;
}
.item span.icon-cross:hover::after {
    background: DodgerBlue;
    border-radius: 10px;
    display: block;
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    content: "";
}

Смотрите полный пример скрипки здесь


-1

Простое решение jquery для тех, кто не нуждается в чистом решении CSS:

    $(".letter").hover(function() {
      $(this).closest("#word").toggleClass("hovered")
    });
.hovered {
  background-color: lightblue;
}

.letter {
  margin: 20px;
  background: lightgray;
}

.letter:hover {
  background: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="word">
  <div class="letter">T</div>
  <div class="letter">E</div>
  <div class="letter">S</div>
  <div class="letter">T</div>
</div>


-8

Это очень легко сделать в Sass! Не углубляйтесь в JavaScript для этого. Селектор & в sass делает именно это.

http://thesassway.com/intermediate/referencing-parent-selectors-using-ampersand


6
-1 Sass не добавляет больше функциональности в css, он просто облегчает написание. Все, что вы можете сделать в sass, можно сделать в CSS и наоборот.
Дастур

3
@Dastur Учитывая переменные и миксины, я бы сказал, что Sass очень много добавляет в CSS. Вы можете делать все это в CSS, точно так же, как вы могли бы писать сложные программы, используя простой старый C. Современные языки добавляют много, не позволяя чего-то, чего нельзя было сделать раньше. То же самое с Sass и CSS.
Кобус Крюгер

6
@Cobus Kruger Вы частично правы, но вы не можете сделать это сравнение. Принимая во внимание, что языки как c ++ c # и javascript могут основываться на C, они не превращаются в C до времени выполнения. Sass преобразуется в css перед выполнением, поэтому вы никогда не загружаете таблицу стилей sass, а только css.
Дастур
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.