Home > Net >  Javascript Target Specific Elements on Mouse Hover | CSS HTML JS
Javascript Target Specific Elements on Mouse Hover | CSS HTML JS

Time:12-02

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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

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>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related