1

I have 3 elements on my page. When the user hovers over 1 of the elements i want to be able to target the other 2 elements individualy and add a CSS animation.

I have tried all day to accomplish this but just cant in plain HTML CSS, and so have started exploring javascript.

Essentially when i am hovering over an element like #flip-box-2 i want to be able to target #flip-box-1 and #flip-box-3 individualy. So that i could then use the animation property and @keyframes to animate the 2 flip cards which are not being hovered over.

I am really struggling with this and would massively apreciate some assistance. Many thanks !

#container {
  display: flex;
  justify-content: space-around;
  height: 100vh;
  align-items: center;
}

#flip-box-1 {
  background-color: transparent;
  width: 300px;
  height: 200px;
  perspective: 1000px;
  /* Remove this if you don't want the 3D effect */
  z-index: 2;
}


/* This container is needed to position the front and back side */

#flip-box-inner-1 {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}


/* Do an horizontal flip when you move the mouse over the flip box container */

#flip-box-1:hover #flip-box-inner-1 {
  transform: rotateY(180deg);
}


/* Position the front and back side */

#flip-box-front-1,
#flip-box-back-1 {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  /* Safari */
  backface-visibility: hidden;
}


/* Style the front side */

#flip-box-front-1 {
  background-image: url("//picsum.photos/300/200?c=f1");
  background-size: contain;
  background-repeat: no-repeat;
}


/* Style the back side */

#flip-box-back-1 {
  background-image: url("//picsum.photos/300/200?c=b1");
  background-size: contain;
  background-repeat: no-repeat;
  transform: rotateY(180deg);
}

#flip-box-2 {
  background-color: transparent;
  width: 300px;
  height: 200px;
  perspective: 1000px;
  /* Remove this if you don't want the 3D effect */
  z-index: 3;
}


/* This container is needed to position the front and back side */

#flip-box-inner-2 {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}


/* Do an horizontal flip when you move the mouse over the flip box container */

#flip-box-2:hover #flip-box-inner-2 {
  transform: rotateY(180deg);
}


/* Position the front and back side */

#flip-box-front-2,
#flip-box-back-2 {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  /* Safari */
  backface-visibility: hidden;
}


/* Style the front side */

#flip-box-front-2 {
  background-image: url("//picsum.photos/300/200?c=f2");
  background-size: contain;
  background-repeat: no-repeat;
}


/* Style the back side */

#flip-box-back-2 {
  background-image: url("//picsum.photos/300/200?c=b2");
  background-size: contain;
  background-repeat: no-repeat;
  transform: rotateY(180deg);
}

#flip-box-3 {
  background-color: transparent;
  width: 300px;
  height: 200px;
  perspective: 1000px;
  /* Remove this if you don't want the 3D effect */
}


/* This container is needed to position the front and back side */

#flip-box-inner-3 {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}


/* Do an horizontal flip when you move the mouse over the flip box container */

#flip-box-3:hover #flip-box-inner-3 {
  transform: rotateY(180deg);
}


/* Position the front and back side */

#flip-box-front-3,
#flip-box-back-3 {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  /* Safari */
  backface-visibility: hidden;
}


/* Style the front side */

#flip-box-front-3 {
  background-image: url("//picsum.photos/300/200?c=f3");
  background-size: contain;
  background-repeat: no-repeat;
}


/* Style the back side */

#flip-box-back-3 {
  background-image: url("//picsum.photos/300/200?c=b3");
  background-size: contain;
  background-repeat: no-repeat;
  transform: rotateY(180deg);
}
<div id="container">

  <div id="flip-box-1">
    <div id="flip-box-inner-1">
      <div id="flip-box-front-1"></div>
      <div id="flip-box-back-1"></div>
    </div>
  </div>


  <div id="flip-box-2">
    <div id="flip-box-inner-2">
      <div id="flip-box-front-2"></div>
      <div id="flip-box-back-2"></div>
    </div>
  </div>


  <div id="flip-box-3">
    <div id="flip-box-inner-3">
      <div id="flip-box-front-3"></div>
      <div id="flip-box-back-3"></div>
    </div>
  </div>

</div>
Reyno
  • 6,119
  • 18
  • 27
Luke Cody
  • 13
  • 5
  • http://jsfiddle.net/38mqhda2/6/ This is my best strating point but i just cant figure out how to apply it for my use case – Luke Cody Dec 01 '21 at 15:54
  • I've created a [Stack Snippet](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) for you. Feel free to edit! PS: I replaced your images with placeholder images to show the effect of your animation – Reyno Dec 01 '21 at 15:56
  • This might help: https://stackoverflow.com/a/4502693/17175441 – aerial Dec 01 '21 at 15:56
  • @Reyno Thankyou!! – Luke Cody Dec 01 '21 at 16:10
  • @aerial301 Unfortunetly this seems to only work if the element being hovered on comes first and the other 2 elements come after (in the DOM). So it works on flip-card-1 and i can then animate flip-card-2 and flip-card-3 ... but if i hover on flip-card-2 then i can only animate #flip-card-3 -_- – Luke Cody Dec 01 '21 at 16:13

2 Answers2

2

First of all I suggest moving (most of) your CSS to classes. This way we don't have to repeat everything for each box.

To toggle the CSS animation we can just add and remove a class from the element. In my case its flip-box-active.

Then instead of listening for a hover we can just listen to the mouseenter and mouseleave events.

// Get all elements from the DOM
const flipBoxes = document.querySelectorAll('.flip-box');
// If you don't want to use classes you can use the next line instead
// const flipBoxes = document.querySelectorAll('#flip-box-1, #flip-box-2, #flip-box-3');

// Apply events to each box
for(const flipBox of flipBoxes) {
  flipBox.addEventListener('mouseenter', showBackside, false);
  flipBox.addEventListener('mouseleave', showFrontside, false);
}

// Show backside when mouse enters element
function showBackside() {
  for(const flipBox of flipBoxes) {
    // Skip if it is the box we currently hover over
    if(this === flipBox) continue;
    
    flipBox.classList.add('flip-box-active');
  }
}

// Show frontside when mouse leaves element
function showFrontside() {
  for(const flipBox of flipBoxes) {
    flipBox.classList.remove('flip-box-active');
  }
}
#container {
  display: flex;
  justify-content: space-around;
  height: 100vh;
  align-items: center;
}

.flip-box {
  background-color: transparent;
  width: 300px;
  height: 200px;
  perspective: 1000px;
}

/* This container is needed to position the front and back side */

.flip-box-inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}

/* Do an horizontal flip when you move the mouse over the flip box container */

.flip-box-active .flip-box-inner {
  transform: rotateY(180deg);
}

/* Position the front and back side */

.flip-box-front,
.flip-box-back {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  /* Safari */
  backface-visibility: hidden;
}

/* Style the front side */

.flip-box-front {
  background-size: contain;
  background-repeat: no-repeat;
}

/* Style the back side */

.flip-box-back {
  background-size: contain;
  background-repeat: no-repeat;
  transform: rotateY(180deg);
}

/* Apply different images */

#flip-box-front-1 {
  background-image: url("//picsum.photos/300/200?c=f1");
}

#flip-box-back-1 {
  background-image: url("//picsum.photos/300/200?c=b1");
}

#flip-box-front-2 {
  background-image: url("//picsum.photos/300/200?c=f2");
}

#flip-box-back-2 {
  background-image: url("//picsum.photos/300/200?c=b2");
}

#flip-box-front-3 {
  background-image: url("//picsum.photos/300/200?c=f3");
}

#flip-box-back-3 {
  background-image: url("//picsum.photos/300/200?c=b3");
}
<div id="container">

  <div class="flip-box" id="flip-box-1">
    <div class="flip-box-inner">
      <div class="flip-box-front" id="flip-box-front-1"></div>
      <div class="flip-box-back" id="flip-box-back-1"></div>
    </div>
  </div>

  <div class="flip-box" id="flip-box-2">
    <div class="flip-box-inner">
      <div class="flip-box-front" id="flip-box-front-2"></div>
      <div class="flip-box-back" id="flip-box-back-2"></div>
    </div>
  </div>

  <div class="flip-box" id="flip-box-3">
    <div class="flip-box-inner">
      <div class="flip-box-front" id="flip-box-front-3"></div>
      <div class="flip-box-back" id="flip-box-back-3"></div>
    </div>
  </div>

</div>
Reyno
  • 6,119
  • 18
  • 27
  • This is so awesome thank you so much! Im a newbie and so i dont have enough rep yet to 1up you -_- Struggling with brain fog right now but i will continue to try and get my head around this for my use case which will be to slide the cards that are not being hovered over under the card that is. I have some illustrations of the front and back of envelopes and its going to look really nice. :)))) – Luke Cody Dec 01 '21 at 16:21
  • I am really having a hard time to get the flip box's that are not being hovored over to slide under the flipbox that is ... sorry i am a designer rather than a developer but am really trying my best to figure things out – Luke Cody Dec 01 '21 at 18:13
0

I wasted some time putting your css code back in order ...

document.querySelectorAll('.flip-box').forEach((fb,_,all) =>
  {
  fb.onmouseenter =_=> all.forEach(fbx=>fbx.classList.toggle('activ', fbx!==fb))
  fb.onmouseleave =_=> all.forEach(fbx=>fbx.classList.remove('activ'))
  })
#container {
  display         : flex;
  justify-content : space-around;
  height          : 100vh;
  align-items     : center;
  }
.flip-box {
  background-color : transparent;
  width            : 300px;
  height           : 200px;
  perspective      : 1000px;  /* Remove this if you don't want the 3D effect */
  }
.flip-box > div { /* This container is needed to position the front and back side */
  position        : relative;
  width           : 100%;
  height          : 100%;
  text-align      : center;
  transition      : transform 0.8s;
  transform-style : preserve-3d;
  }
.flip-box.activ > div { /* Do an horizontal flip  (flip-box:hover > div) */
  transform : rotateY(180deg);
  }
.flip-box > div > div {
  position                    : absolute;
  width                       : 100%;
  height                      : 100%;
  -webkit-backface-visibility : hidden; /* Safari */
  backface-visibility         : hidden;
  background-size             : contain;
  background-repeat           : no-repeat;
  } 
.flip-box > div > div:nth-of-type(2) {
  transform: rotateY(180deg);
  }
#flip-box-1>div>div:nth-of-type(1) { background:url("//picsum.photos/300/200?c=f1") }
#flip-box-2>div>div:nth-of-type(1) { background:url("//picsum.photos/300/200?c=f2") }
#flip-box-3>div>div:nth-of-type(1) { background:url("//picsum.photos/300/200?c=f3") }
#flip-box-1>div>div:nth-of-type(2) { background:url("//picsum.photos/300/200?c=b1") }
#flip-box-2>div>div:nth-of-type(2) { background:url("//picsum.photos/300/200?c=b2") }
#flip-box-3>div>div:nth-of-type(2) { background:url("//picsum.photos/300/200?c=b3") }
<div id="container">
  <div class="flip-box" id="flip-box-1">
    <div><div></div><div></div></div>
  </div>
  <div class="flip-box" id="flip-box-2">
    <div><div></div><div></div></div>
  </div>
  <div class="flip-box" id="flip-box-3">
    <div><div></div><div></div></div>
  </div>
</div>
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
  • Thank you sir :) – Luke Cody Dec 01 '21 at 18:11
  • I am a designer rather than a developer, but really want to pull this animation off XD – Luke Cody Dec 01 '21 at 18:12
  • Would you have any idea how to get the flip box's that arent being hovered over to slide under the flip box that is – Luke Cody Dec 01 '21 at 18:12
  • @LukeCody sorry, but I do not understand anything at all what you ask me...!? – Mister Jojo Dec 01 '21 at 19:02
  • Sorry, i am new here. I mean that when the user hovers over flip card 1 (for example) i want flip card 2 and 3 to move left so that they are both hiding under flip card 1. When the user hovers over flip card 2 in the middle then flip card 1 would move right and flip card 3 would move left to again both be hiding under the flip card thats beign viewed. Originaly i was going to use CSS animation with @keyframes and tranform:translate() but now the code has evolved so much i no longer understand it XD – Luke Cody Dec 02 '21 at 07:25