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>