-1

i have two images stacking on-top of each other and i am adding some shadow in order to give the a 3d effect. The issue i am running into is, i want the first-of-type to initially have a box-shadow, and when the last-of-type is hovered, this shadow on the first-of-type is removed.

When the first-of-type is hovered however, this shadow grows. How would i go about doing this? I've tried sibling selectors but i found out you cant "go up the sibling tree", so i am looking for a way to do this.

Also tried something like &:not(:hover):first-of-type {}, to no success

CSS

&__image {
    &:hover {
       //do stuff

      //what i want to do
      if(last-child) then first-of-type box-shadow = none
    } 
}

and then if neither is hovered, the first-of-type should return to its initial state ( small shadow ). Note: these components are direct siblings, eg

HTML

<div>
    <img...>
    <img...>
</div>

thanks in advance,

Ryan Turnbull
  • 3,766
  • 1
  • 25
  • 35

3 Answers3

1

You're right that you can't traverse your way up to previous siblings in CSS selectors, but you can do this with some vanilla JavaScript by adding event listeners to toggle a class on mouse events, specifically when the mouse is over and when it leaves a given element.

Something like this will suffice, if you contain your box-shadow to a class:

var firstImg = document.querySelector('.parent img:first-of-type');
var lastImg = document.querySelector('.parent img:last-of-type');

lastImg.addEventListener("mouseover", function() {
  firstImg.classList.toggle('box-shadow');
});

lastImg.addEventListener("mouseout", function() {
  firstImg.classList.toggle('box-shadow');
});

This presupposes a .box-shadow class that's applied by default to the first, but it can be adapted to suit your needs. Note that as written this also assumes a class on the parent (here I called it .parent) but that can also be adapted to your needs.

denmch
  • 1,446
  • 12
  • 20
  • would this work if i have to do this effect twice? i'm using react so i have two components with the same classnames etc. – Ryan Turnbull Feb 09 '18 at 00:18
  • You could do something like use `.querySelectorAll` to grab the set of matching parents. Here's an example: https://codepen.io/denmch/pen/7b48eaccab60c21b76d5109d042748d5 – denmch Feb 10 '18 at 15:47
1

As you've already mentioned, there's currently no CSS selector to change a previous sibling.

Related: Is there a "previous sibling" CSS selector?


I think the best option is to add a 'box-shadow' class to both images, and use jQuery to toggle this class on hover.

$("#gallery img:last-of-type").hover(function() {
  $("#gallery img:first-of-type").toggleClass("box-shadow");
});
#gallery img {
  height: 120px;
  width: auto;
}

.box-shadow {
  box-shadow: 1px 1px 4px #333;
}
<div id="gallery">
  <img class="box-shadow" src="https://www.istockphoto.com/resources/images/IllustrationsLanding/img_33917052.jpg" />
  <img class="box-shadow" src="https://www.istockphoto.com/resources/images/IllustrationsLanding/img_52210298.jpg" />
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Bonus:

You could also use this approach which makes the use of a 'box-shadow'-class obsolete, but it requires more lines of jQuery (makes me prefer the class-solution).

$("#gallery img:last-of-type").hover(function() {
  $("#gallery img:first-of-type").css({
    boxShadow: "none"
  });
}, function() {
  $("#gallery img:first-of-type").css({
    boxShadow: "1px 1px 4px #333"
  });
});
Berendschot
  • 3,026
  • 1
  • 21
  • 43
1

It's possible to do it with just CSS but I'm not sure on your exact situation and what you're trying to do with the box shadows. I made an example on how you can do this using a combination of the first of type and last of type selectors.

The selectors with the transparent borders are the default un-hovered state. The red border is for when the item is active (where you'd apply the box shadow to). I also increased the border by 1px for the first one when hovered.

 
/* initial state for the default one */
div img:first-of-type{
 border: 5px solid red;
}

/* hovered state of the first one */
div:hover img:first-of-type:hover{
 border: 6px solid red;
}

/* state of the default one when the second one is hovered */
div:hover img:first-of-type{
 border: 5px solid transparent;
}

/* initial state of the second one */
div img:last-of-type{
 border: 5px solid transparent;
}

/* state of the second one when hovered */
div img:last-of-type:hover{
 border: 5px solid red;
}


/* styles just for this example */
div{
 display: inline-block;
}
img{
display: block;
}
  
  
<div>
 <img src="https://i.imgur.com/nyljaMX.png" style="width:100px">
 <img src="https://i.imgur.com/nyljaMX.png" style="width:100px">
</div>

Here's a link to a jsfiddle I made: https://jsfiddle.net/jw06at5r/1/

heraldo
  • 187
  • 7