admin管理员组

文章数量:1410717

I'm wondering if it's possible to write a CSS selector that will target an element in a separate div when the current element within a sibling div is hovered over.

In my specific case, referencing the exact HTML below, I want to hover over the first h3 and apply style to the preceding img (in this case, picsum.photos/200/300 img). Yes, I can do this via JavaScript or if I restructure the HTML but I'm trying to do a pure CSS selector with this exact DOM structure.

<div>
  <img src="/200/400" />
  <div>
    <a href="">
      <figure>
        <img src="/200/300" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
  <div>
    <a href="">
      <figure>
        <img src="/200/500" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
</div>

I'm wondering if it's possible to write a CSS selector that will target an element in a separate div when the current element within a sibling div is hovered over.

In my specific case, referencing the exact HTML below, I want to hover over the first h3 and apply style to the preceding img (in this case, picsum.photos/200/300 img). Yes, I can do this via JavaScript or if I restructure the HTML but I'm trying to do a pure CSS selector with this exact DOM structure.

<div>
  <img src="https://picsum.photos/200/400" />
  <div>
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/300" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
  <div>
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/500" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
</div>
Share edited Mar 6 at 19:21 TylerH 21.1k79 gold badges79 silver badges114 bronze badges asked Mar 5 at 17:48 user10229301user10229301 212 bronze badges 2
  • Are you targeting modern browsers (e.g. the latest Firefox, Chrome, Edge, etc.?) :has() will be your only hope here, if you can't modify the markup and want to do it in CSS. – TylerH Commented Mar 5 at 17:51
  • @TylerH I have tried numerous ways with :has() but to no avail. Are you able to make it work? I'd love to see your working solution. – user10229301 Commented Mar 5 at 17:55
Add a comment  | 

2 Answers 2

Reset to default 2

This is as @TylerH mentioned above using :has() mdn docs After updated html snippet, as written in the comment made by @Fract

div:has(+ div h3:hover) img will target images the way you were looking for.

img {
  transition: all 0.3s ease;
}
div:has(+ div h3:hover) img {
  transform: scale(0.9);
  filter: grayscale(100%);
}
<div>
  <div>
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/300" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
</div>

<div>
  <img src="https://picsum.photos/200/400" />
  <div>
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/300" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
  <div>
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/500" />
      </figure>
    </a>
  </div>
  <div>
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
</div>

I doubt it is possible. So if it is possible, then I will be more than happy to remove this answer. This is how you can do it with Javascript, if you end up reaching the conclusion that it's impossible/unfeasible. Not much of a refactoring is needed:

let imageContainers = document.querySelectorAll(".image-container");
let hoverContainers = document.querySelectorAll(".hover-container")
for (let i = 0; i < hoverContainers.length; i++) {
    hoverContainers[i].addEventListener('mouseenter', function() {
        imageContainers[i].classList.add('hovered');
    });
    hoverContainers[i].addEventListener('mouseleave', function() {
        imageContainers[i].classList.remove('hovered');
    });
}
.image-container.hovered img {
    border: 10px solid blue;
}
<div>
  <img src="https://picsum.photos/200/400" />
  <div class="image-container">
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/300" />
      </figure>
    </a>
  </div>
  <div class="hover-container">
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
  <div class="image-container">
    <a href="">
      <figure>
        <img src="https://picsum.photos/200/500" />
      </figure>
    </a>
  </div>
  <div class="hover-container">
    <a href="">
      <h3>Hover me.</h3>
    </a>
    <p>Lorem.</p>
    <p>Ipsum.</p>
  </div>
</div>

The only needed change on the HTML is to make sure we know what the container is for the reason to be able to differentiate similar, but different elements. A refactoring you'll likely need anyway.

本文标签: css selectorsHow to select the child of an indirect preceding ancestor using CSSStack Overflow