62

Is there a way to modify the css for one class when hovering on an element from another class using only css ?

Something like:

.item:hover .wrapper { /*some css*/ }

Only 'wrapper' is not inside 'item', it's somewhere else.

I really don't want to use javascript for something this simple, but if I have to, how would I do it ? Here's my failed attempt:

document.getElementsByClassName('item')[0].onmouseover="document.getElementsByClassName('wrapper')[0].style.background="url('some url')";";

There's only one element of each class. Don't know why they didn't use IDs when they made the template, but that's just how it is and I can't change it.

[Edit]

It's a menu. Each menu element has a distinct class. When you hover on the element a submenu pops up to the right. It's like an overlay, when I use the 'Inspect Element' tool I can see that the whole website html changes when the submenu is active(meaning there's nothing but the submenu). The class I call 'wrapper' has the css that controls the background for the submenu. There's really no connection that I can see between the two classes.

Kesarion
  • 2,808
  • 5
  • 31
  • 52

5 Answers5

125

There are two approaches you can take, to have a hovered element affect (E) another element (F):

  1. F is a child-element of E, or
  2. F is a later-sibling (or sibling's descendant) element of E (in that E appears in the mark-up/DOM before F):

To illustrate the first of these options (F as a descendant/child of E):

.item:hover .wrapper {
    color: #fff;
    background-color: #000;
}​

To demonstrate the second option, F being a sibling element of E:

.item:hover ~ .wrapper {
    color: #fff;
    background-color: #000;
}​

In this example, if .wrapper was an immediate sibling of .item (with no other elements between the two) you could also use .item:hover + .wrapper.

JS Fiddle demonstration.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
12

It's not possible in CSS at the moment, unless you want to select a child or sibling element (trivial and described in other answers here).

For all other cases you'll need JavaScript. jQuery and frameworks like Angular can tackle this problem with relative ease.

[Edit]

With the new CSS (4) selector :has() guide from CSS4.Rocks (archived by Wayback Machine) and :has() guide from MDN Web Docs, you'll be able to target parent elements/classes, making a CSS-Only solution viable in the near future!

Kesarion
  • 2,808
  • 5
  • 31
  • 52
  • After briefly reading up on `:has` it leaves me with the impression that it only operates on the children in the current scope. How would you target a parenting element using `:has`? – Marcus Riemer Jan 04 '19 at 14:23
  • @MarcusRiemer This is a rather old question of mine, I might not have worded the description very well back then, but what would have helped me is something like the following: `.common_parrent:has(.item:hover) .content {/*...*/}` – Kesarion Apr 26 '19 at 11:46
10

You can do it by making the following CSS. you can put here the css you need to affect child class in case of hover on the root

.root:hover    .child {
   
}
Mohammad Gabr
  • 221
  • 2
  • 5
6

Provided .wrapper is inside .item, and provided you're either not in IE 6 or .item is an a tag, the CSS you have should work just fine. Do you have evidence to suggest it isn't?

EDIT:

CSS alone can't affect something not contained within it. To make this happen, format your menu like so:

<ul class="menu">
    <li class="menuitem">
        <a href="destination">menu text</a>
        <ul class="menu">
            <li class="menuitem">
                <a href="destination">part of pull-out menu</a>
... etc ...

and your CSS like this:

.menu .menu {
    display: none;
}

.menu .menuitem:hover .menu {
    display: block;
    float: left;
    // likely need to set top & left
}
robrich
  • 13,017
  • 7
  • 36
  • 63
-3

You can do this.
When hovering to the .item1, it will change the .item2 element.

.item1 {
  size:100%;
}

.item1:hover
{
   .item2 {
     border:none;
   }
}

.item2{
  border: solid 1px blue;
}
Azametzin
  • 5,223
  • 12
  • 28
  • 46
TJZ
  • 25
  • 3