skip to Main Content

I’m newer to Javascript and am trying to set up some cards so that when the user’s mouse enters the card div that it adds or removes a class to the button contained within.

The logic would be: when the "version-card" div detects a mouseOver it will add a "active" class with a different background color to the button within.

I’ve tried .querySelector, .querySelectorAll, and .getElementByID but it doesn’t seem to work. I’m missing something small I think but wanted help figuring out what I set up wrong. Do I need to loop something? The missing part is how to apply the class change to multiple/all of the divs and buttons, not just the first one

I’ve successfully used the code to change the color of the button, but it only is set up to change the first card’s button, not every card’s button like I want. (2nd code snippet below).

JSfiddle here: https://jsfiddle.net/rtpzeo0n/

document.querySelectorAll(".version-card").addEventListener("mouseover", mouseOver);
document.querySelectorAll(".version-card").addEventListener("mouseout", mouseOut);

function mouseOver() {
  document.getElementById(".button-primary").classList.add("active");

}

function mouseOut() {
  document.getElementById(".button-primary").classList.remove("active");

}
.active {
  background:red!important;
}
<div class="version-card" style="padding:30px;border:2px solid black;">
<div class="card-content">
<h1>
 header
</h1>
<p>
 blah blah blah
</p>
<a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
</div>
</div>

<div class="version-card" style="padding:30px;border:2px solid black;">
<div class="card-content">
<h1>
 header
</h1>
<p>
 blah blah blah
</p>
<a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
</div>
</div>

<div class="version-card" style="padding:30px;border:2px solid black;">
<div class="card-content">
<h1>
 header
</h1>
<p>
 blah blah blah
</p>
<a class="button-primary" id="button-primary" style="padding:20px; background:green;">Button</a>
</div>
</div>

=====
Code that worked but only changed the first button, not multiple

document.querySelector(".version-card").addEventListener("mouseover", mouseOver);
document.querySelector(".version-card").addEventListener("mouseout", mouseOut);

querySelector(".version-card").classList.add('active');

function mouseOver() {
  document.querySelector(".button-primary").classList.add("active");

}

function mouseOut() {
  document.querySelector(".button-primary").classList.remove("active");

}
.active {
  background:red!important;
}
<div class="version-card" style="padding:30px;border:2px solid black;">
<div class="card-content">
<h1>
 header
</h1>
<p>
 blah blah blah
</p>
<a class="button-primary" style="padding:20px; background:green;">Button</a>
</div>
</div>

2

Answers


  1. To do what you require you can use the CSS :hover pseudo selector.

    .version-card:hover .button-primary {
      background: red !important;
    }
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
      </div>
    </div>
    
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
      </div>
    </div>
    
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" id="button-primary" style="padding:20px; background:green;">Button</a>
      </div>
    </div>

    Also note that the !important modifier is something you should absolutely avoid. Make your CSS selectors more descriptive to increase precedence if you’re trying to override existing styles.

    You would need to move your CSS to an external stylesheet for this to work in this case, which again is something you should absolutely do. JS and CSS shouldn’t be in a HTML file.

    If, for whatever reason, you did want to do this in JS, although I wouldn’t suggest you do, then there’s a few issues in your JS which need to be fixed:

    • querySelectorall() returns a NodeList, not a single Element, therefore you need to loop through them to attach the event handlers.
    • You need to get a reference to the .button-primary within the .version-card that triggered the event. You can use the Event object within the arguments of the handler to get a reference to the target property and selecting the child element from there.
    • Use mouseenter and mouseleave events for this. mouseover fires once for every pixel that the mouse moves over the element, which is overkill in this case.
    const cards = document.querySelectorAll(".version-card")
    const mouseenterHandler = e => e.target.querySelector(".button-primary").classList.add("active");
    const mouseleaveHandler = e => e.target.querySelector(".button-primary").classList.remove("active");
    
    cards.forEach(card => {
      card.addEventListener("mouseenter", mouseenterHandler);
      card.addEventListener("mouseleave", mouseleaveHandler);
    });
    .active {
      background: red!important;
    }
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
      </div>
    </div>
    
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" style="padding:20px; background:green;" id="button-primary">Button</a>
      </div>
    </div>
    
    <div class="version-card" style="padding:30px;border:2px solid black;">
      <div class="card-content">
        <h1>
          header
        </h1>
        <p>
          blah blah blah
        </p>
        <a class="button-primary" id="button-primary" style="padding:20px; background:green;">Button</a>
      </div>
    </div>
    Login or Signup to reply.
  2. Just use querySelectorAll instead of querySelector

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search