1

I have several identical divs and each of them contains a button that is hidden. I want to make button visible when you hover on the parent div. I wrote this code:

    const cardElements = document.querySelectorAll('.middle_section__president_section');
    const learnButtons = document.querySelectorAll('.president_section__button');

    cardElements.forEach((cardElement) => {
        cardElement.addEventListener('mouseover', () => {
            learnButtons.forEach((learnButton) => {
                learnButton.style.height = "50px";
                learnButton.style.opacity = "1";
                learnButton.style.border = "3px solid rgb(129, 129, 129)";
            });
        });
        
        cardElement.addEventListener('mouseout', () => {
            learnButtons.forEach((learnButton) => {
                learnButton.style.height = "0px";
                learnButton.style.opacity = "0";
                learnButton.style.border = "0px solid rgb(129, 129, 129)";
            });
        });    
    })

carElements is parent, learnButtons - child.

but with this code when i hover on one div buttons appears in every similiar div. How can i make button appear only on hovered div?

  • 3
    A standard for-loop is an alternative, but I don't think `forEach()` is the problem at all. You need to limit what you're looping over. What are `cardElements` and `learnButtons`? Please include the relevant html as well. – mykaf Oct 24 '22 at 15:05
  • 8
    use css `:hover` ! – Mister Jojo Oct 24 '22 at 15:05
  • is it possible to make child element appear when hovering parent? – Stamble Ribis Oct 24 '22 at 15:09
  • 1
    Yes, using [descendant combinators](https://www.w3.org/TR/selectors-3/#descendant-combinators) - use a selector for hovering over a card element, followed by a selector for the learn buttons. The rule applies to the learn buttons in the hovered card. – traktor Oct 24 '22 at 15:13
  • [Event delegation](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation) - you can attach a single event listener, not one per item. – VLAZ Oct 24 '22 at 15:20

3 Answers3

2

Use the Event object

cardElement.addEventListener('mouseover', () => {
    learnButtons.forEach((learnButton) => {

convert this to

cardElement.addEventListener('mouseover', (e) => {
    var learnButton = e.target;
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
1

There's no need to use JS for this. As Mister Jojo/traktor pointed out in their comments you can use the CSS :hover pseudo-class instead.

The key CSS line is .box:hover button { visibility: visible;} which means "when you hover over the parent container make its button visible".

.box { width: 50%; display: flex; flex-direction: column; border: 1px solid lightgray; margin: 0.25em; padding: 0.25em;}
button { visibility: hidden; margin: 0.25em 0; border-radius: 5px;  background-color: lightgreen; }
.box:hover button { visibility: visible;}
.box:hover, button:hover { cursor: pointer; }
<section class="box">
  Some text
  <button>Click for a surprise!</button>
</section>

<section class="box">
  Some text
  <button>Click for a surprise!</button>
</section>

<section class="box">
  Some text
  <button>Click for a surprise!</button>
</section>
Andy
  • 61,948
  • 13
  • 68
  • 95
0

It is bad practice to iterate over all elements and give each an event, as you can add 1 event handler to the parent and when the event happens you can check the affected element by the event parameter in the handler call back

parent.addEVentListener('mouseover', (e) => {
  if(e.target.classList.contains('middle_section__president_section')) {
    // Do 
  }
});
Mustafa Reda
  • 179
  • 5