2

I'm trying to create a menu where the currently selected (clicked) element has a different background color than the other elements (I'm trying to achieve this using JavaScript). I also use the CSS :hover pseudoclass to make the hovered element stand out by highlighting it. However, I have encountered a strange problem: when I set the background color of any element with JavaScript, its CSS hover behavior no longer works. That is, I can't highlight the element by hovering it anymore. I have checked that in Firefox and Chromium. This is the case for both jQuery and plain JavaScript.

The code is below. I have simplified it a lot to narrow down the problem. First try hovering any of the menu items, then click the "Set background color" link and hover one of the menu elements again. What I expect is the element getting red (#f00) when hovered, regardless of whether the "Set background color" button was clicked or not. For jsfiddle links, go to the bottom.

Vanilla JavaScript:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <style>
            p#links a {
                display: inline-block;
                width: 80px;
                height: 22px;
                line-height: 22px;
                background-color: #00f;
                color: #fff;
                text-decoration: none;
                text-align: center;
                font-family: sans-serif;
            }

            p#links a:hover {
                background-color: #f00;
            }       
        </style>
        <title>Background color</title> 
    </head>
    <body>
        <p id="links">
            <a href="#">Link 1</a>
            <a href="#">Link 2</a>
            <a href="#">Link 3</a>
            <a href="#">Link 4</a>
        </p>
        <a href="#" id="setbgcolor">Set background color</a>

        <script>
            document.getElementById('setbgcolor').onclick = function() {
                var p = document.getElementById('links');
                var elements = p.getElementsByTagName('a');
                for (var i = 0; i < elements.length; i++)
                    elements[i].style.backgroundColor = '#ff0';
            };
        </script>
    </body>
</html>

jQuery:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="jquery-1.11.0.js"></script>
        <style>
            p#links a {
                display: inline-block;
                width: 80px;
                height: 22px;
                line-height: 22px;
                background-color: #00f;
                color: #fff;
                text-decoration: none;
                text-align: center;
                font-family: sans-serif;
            }

            p#links a:hover {
                background-color: #f00;
            }       
        </style>
        <title>Background color</title> 
    </head>
    <body>
        <p id="links">
            <a href="#">Link 1</a>
            <a href="#">Link 2</a>
            <a href="#">Link 3</a>
            <a href="#">Link 4</a>
        </p>
        <a href="#" id="setbgcolor">Set background color</a>

        <script>
            $('a#setbgcolor').click(function() {
                $('p#links a').css('background-color', '#ff0');
            });
        </script>
    </body>
</html>

And here are jsfiddle.net links for the purpose of convenience:
Pure JavaScript: http://jsfiddle.net/5yQFM/1/
jQuery: http://jsfiddle.net/5yQFM/

5 Answers 5

6

The jQuery css() method maps onto the style property which maps onto the style attribute.

Rules inside a style attribute are more specific then rules in a stylesheet, so will always come after them in the cascade.

Instead of altering the CSS on the element directly, alter it by changing the classes the element belongs to and having a pre-prepared stylesheet.

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

1 Comment

i like the fact that you're explaining it, though i have a hard time to follow... how would your recommendation look "code-wise"? (note, i'm not the OP, just curious)
6

you need to use !important on hover, basically it will increase its priority.

Try this,

p#links a:hover {
    background-color: #f00 !important;
}

DEMO


As Quentin said it looks like a dirty one, so in that situation we can make use of the class priority concepts.

HTML:

<a class='normal' href="#">Link 1</a>
<a class='normal' href="#">Link 1</a>

CSS:

.normal { background-color: blue; } 
.abnormal{ background-color: yellow; }

.normal:hover { background-color: #f00; }

JS:

$('p#links a').attr('class', 'abnormal normal');

DEMO Non-Dirty one

3 Comments

Quick but dirty. Avoid !important rules. They only go one layer deep. You get better control (and separation of concerns) by careful application of specificity.
@Quentin yes sure, I thought , for handling this kind of situations the !important is made for. :)
Upvoted. Quick and NOT dirty on this specific situation.
5

How about keeping the style in CSS and not in Javascript, by adding classes ?

so the line :

elements[i].style.backgroundColor = '#ff0';

Change to

elements[i].className = 'myClassForBackgrounds';

or in the jQ version

$('p#links a').css('background-color', '#ff0');

to :

$('p#links a').addClass('myClassForBackgrounds');

That way you can set your :hover as you would normally

#links a:hover, .myClassForBackgrounds:hover { background-color:#ff0; }

Comments

1

Just for a more simple answer, in able to just re-enable css rules just have it toggle between the color and "", so

document.getElementById("id").style.backgroundColor = "rgb(255, 125, 15)";

would be if the element wasn't already colored via javascript. Now, if your element was already colored the code would look like this:

document.getElementById("id").style.backgroundColor = "";

That re-enables CSS so then your selectors will work.

Comments

0

I encountered the same problem and solved it by doing this:

I set a onmouseover event to change the background color to what the hover color is.

I set a onmouseout event to change the background color to the default color.

This way I have set a hover event with pure javascript

Comments

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.