How to toggle the display property of two sibling elements on hover of one?

Viewed 164

I am trying to toggle the display of two sibling elements when I hover on the first sibling. I want to change the display of the hovered first sibling element from block to none while its immediate or next sibling element's style changes to block from none. I was able to write a css code for that but on hover, the elements constantly flicker and alternate in a never ending loop. Below is my html and css code:

.box {
  display: inline-block;
  width: 300px;
  height: 150px;
  margin: 20px 40px;
  border-radius: 4px;
  cursor: pointer;
}

.box-one {
  background: green;
}

.box-two {
  background: whitesmoke;
  display: none;
}

.box-one:hover {
  display: none;
}

.box-one:hover+.box-two {
  display: block;
}
<div class="box box-one"></div>
<div class="box box-two"></div>

1 Answers

Wrap the two boxes with another div (.container) and toggle them when hovering the container:

.box {
  display: inline-block;
  width: 300px;
  height: 150px;
  margin: 20px 40px;
  border-radius: 4px;
  cursor: pointer;
}

.box-one {
  background: green;
}

.box-two {
  background: whitesmoke;
}

.container {
  width: fit-content;
}

.container:hover>.box-one {
  display: none;
}

.container:not(:hover)>.box-two {
  display: none;
}
<div class="container">
  <div class="box box-one"></div>
  <div class="box box-two"></div>
</div>

Using JS mouseenter and mouseleave events, you can add the event listener with the once: true option only to the current item. As soon as the mouse enter, you show the new item, and only when the user leaves the current item, you add the new mouseenter event listener to the current item, and so on...

const showNext = evt => {
  const current = evt.target
  const next = current.nextElementSibling

  if(!next || !next.classList.contains('box')) return
  
  current.classList.remove('show')

  next.classList.add('show')
  
  next.addEventListener('mouseleave', () => {
    next.addEventListener('mouseenter', showNext, { once: true })
  }, { once: true })
}

document.querySelector('.box')
  .addEventListener('mouseenter', showNext, { once: true })
.box {
  display: none;
  width: 300px;
  height: 150px;
  margin: 20px 40px;
  border-radius: 4px;
  cursor: pointer;
}

.show {
  display: inline-block;
}

.box-one {
  background: green;
}

.box-two {
  background: whitesmoke;
}

.box-three {
  background: red;
}

.box-four {
  background: blue;
}

.container {
  width: fit-content;
}
<div class="box box-one show"></div>
<div class="box box-two"></div>
<div class="box box-three"></div>
<div class="box box-four"></div>

Related