Вопрос

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/

Это было полезно?

Решение

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.

Другие советы

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

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; }

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.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top