1

I'm displaying a simple box over an image, I want it to highlight when hovered over and change colour when clicked.

I've got it to highlight when hovered over and change colour when clicked.The problem is that after changing colour the first time it no longer highlights when hovered over. It seems when the JS changes the styles it disables the CSS hover selector.

How can I keep the hover highlighting working?

const box = document.getElementsByClassName("box")[0];
box.addEventListener("click", (e) => {
  // console.log(e);
  if (e.target.style.backgroundColor == "rgba(255, 0, 0, 0.1)") {
    e.target.style.backgroundColor = "rgba(0, 255, 0, 0.1)";
    e.target.style.borderColor = "rgba(0, 255, 0, 0.4)";
  } else {
    e.target.style.backgroundColor = "rgba(255, 0, 0, 0.1)";
    e.target.style.borderColor = "rgba(255, 0, 0, 0.4)";
  }
});
.container {
  position: relative;
}

.box {
  width: 40px;
  height: 40px;
  background-color: rgba(0, 255, 0, 0.1);
  border-style: solid;
  border-color: rgb(0, 255, 0);
  position: absolute;
  top: 20px;
  left: 50px;
}

.box:hover {
  background-color: rgba(32, 58, 58, 0.4);
}
<div class="container" style="display: inline-block">
  <img src="https://pixeljoint.com/files/icons/full/tree__r1090291261.gif"></img>
  <div class="box"></div>
</div>

3
  • Your if else statement does not make any sense! You are doing the same thing in both conditions. Commented Apr 11, 2021 at 7:35
  • JavaScript adds inline style, so it gets preference over css style. To rectify this define background colors in css with classes, and just toggle classes on element Commented Apr 11, 2021 at 7:36
  • stackoverflow.com/questions/8949194/… if you want to know why this is happening see here. Commented Apr 11, 2021 at 7:47

3 Answers 3

2

Why not set a class for the borders element in CSS and then toggle the class on click?

The reason your hover element set in CSS is not working is because the inline css you are setting using JS is over riding the psuedo elements styling in the internal CSS. See the second example below.

const box = document.getElementsByClassName("box")[0];
box.addEventListener("click", (e) => {
  e.target.classList.toggle('toggle')
});
.container {
  position: relative;
}

.box {
  width: 40px;
  height: 40px;
  background-color: rgba(0, 255, 0, 0.1);
  border-style: solid;
  border-color: rgb(0, 255, 0);
  position: absolute;
  top: 20px;
  left: 50px;
}

.box:hover {
  background-color: rgba(32, 58, 58, 0.4);
}

.toggle {
  background-color: rgba(0, 255, 0, 0.1);
  border-color: rgba(255 ,0, 0, 0.4);
}
<div class="container" style="display: inline-block">
  <img src="https://pixeljoint.com/files/icons/full/tree__r1090291261.gif"></img>
  <div class="box"></div>
</div>

const changed = document.getElementById('changed')
changed.addEventListener('click', () => {
  changed.style.backgroundColor = 'green';
  changed.textContent = 'This elements inline style will now over ride the CSS style rendering the hover psuedo rule useless'
})
#changed {
  background-color: yellow;
  display: inline-block;
}

#changed:hover {
  background-color: red;
}
<div title="right click me and select the browser inspector to view inline style" id="changed">hover over me to change the background-color style</div> 
<div>Click the element above to add JS inline style to it then hover to see behavior.</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Actually, you don't need to put .classList.toggle() in a conditional. Just call it, it will toggle the class for you (add if the element doesn't have it, or remove if it does).
1

CSS rules set by JS are inline CSS declarations in the element's style attribute.

According to the CSS' cascading rules, they take priority over any <style> elements and <link>ed stylesheets.

So, to change styles from JS, you should always either:

  • Create more CSS classes and toggle them on the element using JS, or...
  • If you need more control over the values in JS, set custom CSS properties directly on the element, that are used by the matching style rules defined in the stylesheets.

In this case, it's much easier to implement the first way:

const box = document.getElementsByClassName("box")[0];
box.addEventListener("click", () => {
  /*
  vvv--- Changed to `box` from `event.target`, so it works even if a child is clicked. This is equivalent to `event.currentTarget`. */
  box.classList.toggle("red");
});
.container {
  position: relative;
}

.box {
  width: 40px;
  height: 40px;
  background-color: rgba(0, 255, 0, 0.1);
  border-style: solid;
  border-color: rgb(0, 255, 0);
  position: absolute;
  top: 20px;
  left: 50px;
}

/* 
vvvv--- The style applies only to `.box` elements, allowing the `.red` class to have different meanings in different contexts. */
.box.red{
  background-color: rgba(255, 0, 0, 0.1);
  border-color: rgba(255, 0, 0, 0.4);
}
/*
vvvvvvvvvv--- This selector should be always of greater specificity than the previous. Currently, they are equal, but this is placed later, so takes a higher priority. */
.box:hover {
  background-color: rgba(32, 58, 58, 0.4);
}
<div class="container" style="display: inline-block">
  <img src="https://pixeljoint.com/files/icons/full/tree__r1090291261.gif"></img>
  <div class="box"></div>
</div>

Comments

-2

In CSS there are several rules for a priorities in case of conflicting styles.

In this case, the inline CSS that you insert takes priority.

you can either set the changed background in a new class and toggle it when clicking, or add !important to the end of the hover selector.

background-color: rgba(32, 58, 58, 0.4) !important;

3 Comments

No, no, no! Don't use !important!!! There is a better way!
There are better ways and I gave one of them in here, but !important is not a bad word when used properly so it would be remiss of me not to mention it.
!important may not be a bad thing when used properly, but it's hard to use properly. I recently came across a project, in which everything was stuffed with !importants, so that several of the CSS rules I wrote got overridden by one. So I looked back at the project's history: the entire !important thing started out from such a small "fix". However, as the project grew, more and more !importants were added to override the previous !importants, and finally the entire project got messed up. While !important can be used as a last resort, it's better to avoid when there's a better way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.