最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - event.preventDefault() Causing :hover pseudo class to stick - Stack Overflow

programmeradmin0浏览0评论

I am trying to implement a document navigation, similar to that on the Bootstrap site for their documentation. I've got it working on the whole, but there is one little aspect of it which is bugging me.

Like on Bootstrap, I am using a bination of the affix.js and scrollSpy.js, and this is working. See the following JSFiddle.

        $('#doc_nav').on( "click", "a", function( e ){
//            e.preventDefault();
            var target = this.hash;
            var $target = $(target);
            var offset = $target.offset().top;
            console.log(offset);
            offset = offset - 100;
            console.log(offset);

            $('html, body').scrollTop( offset );


        });

With the e.preventDefault() mented out, the behavior of the navigation menu is as expected. Scrolling down the window results in the displayed div being highlighted on the menu. Clicking on an item in the menu list, takes you directly to corresponding div on the page and when you then scroll away from that section on the page, the menu updates accordingly.

On my 'real' page, I have a fixed header of height 100px. So currently, when I click on a menu link, the pages jumps to the required section and places it at the top of the page where the header obscures it slightly. The scrollTop part of the code above doesn't seem to work unless I use e.preventDefault(). If you unment this line in the fiddle and run it again, click on 'Heading 3' link on the menu, and you will see that it now puts the Heading 3 content in the page offset by 100px from the top. Perfect.

However, now scroll back up the page towards the top. You will see that the 'Heading 3' list item, remains in its :hover state, even when the mouse is no where near it. Its as though the e.preventDefault() has prevented the browser from detecting that the mouse is no longer hovering on the item.

Mouseclicking anywhere outside the browser window, corrects the problem.

Can anyone shed any light on what I'm doing wrong here? How can I prevent the default behavior of the anchor click so I can control the page scroll placement, without stopping the correct CSS painting in the process?

The problem arises because I am preventing the browsers default behavior, using e.preventDefault(), as I want to control the scroll to the anchored element.

I've tested this in Firefox and IE10.

I am trying to implement a document navigation, similar to that on the Bootstrap site for their documentation. I've got it working on the whole, but there is one little aspect of it which is bugging me.

Like on Bootstrap, I am using a bination of the affix.js and scrollSpy.js, and this is working. See the following JSFiddle.

        $('#doc_nav').on( "click", "a", function( e ){
//            e.preventDefault();
            var target = this.hash;
            var $target = $(target);
            var offset = $target.offset().top;
            console.log(offset);
            offset = offset - 100;
            console.log(offset);

            $('html, body').scrollTop( offset );


        });

With the e.preventDefault() mented out, the behavior of the navigation menu is as expected. Scrolling down the window results in the displayed div being highlighted on the menu. Clicking on an item in the menu list, takes you directly to corresponding div on the page and when you then scroll away from that section on the page, the menu updates accordingly.

On my 'real' page, I have a fixed header of height 100px. So currently, when I click on a menu link, the pages jumps to the required section and places it at the top of the page where the header obscures it slightly. The scrollTop part of the code above doesn't seem to work unless I use e.preventDefault(). If you unment this line in the fiddle and run it again, click on 'Heading 3' link on the menu, and you will see that it now puts the Heading 3 content in the page offset by 100px from the top. Perfect.

However, now scroll back up the page towards the top. You will see that the 'Heading 3' list item, remains in its :hover state, even when the mouse is no where near it. Its as though the e.preventDefault() has prevented the browser from detecting that the mouse is no longer hovering on the item.

Mouseclicking anywhere outside the browser window, corrects the problem.

Can anyone shed any light on what I'm doing wrong here? How can I prevent the default behavior of the anchor click so I can control the page scroll placement, without stopping the correct CSS painting in the process?

The problem arises because I am preventing the browsers default behavior, using e.preventDefault(), as I want to control the scroll to the anchored element.

I've tested this in Firefox and IE10.

Share Improve this question edited Apr 29, 2015 at 11:51 Boidy asked Apr 29, 2015 at 11:45 BoidyBoidy 1671 silver badge10 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 6

The issue is not the :hover state, but the :focus state.

When you click on a link, that link gains focus so you apply the :focus styling (that is the same as the :hover styling in your code). By preventing the default behavior, that link stays active and doesn't lose the focus.

One quick solution would be to unfocus/blur the element by using: $(this).blur().

In your code it would look like this:

    $('#doc_nav').on( "click", "a", function( e ){
        e.preventDefault();
        var target = this.hash;
        var $target = $(target);
        var offset = $target.offset().top;
        console.log(offset);
        offset = offset - 100;
        console.log(offset);
        $(this).blur();
        $('html, body').scrollTop( offset );
    });

You can see a demo here: https://jsfiddle/z32rpe3b/30/


Why did it work fine with e.preventDefault() but incorrectly without it?

The answer to this has to do with the order of execution. The onclick event happens before the href redirection happens in the browser:

  • Without the e.preventDefault(), the code is executed, and the browser scrolled correctly to the target offset - 100 position (in the onclick), but then it executed the link href and scrolled to the target offset. It just happens so fast that it seems that it goes directly to the target position.
  • With e.preventDefault(), the code is executed (scrolling to offset - 100), and the browser doesn't execute the href action (so it stays at offset - 100).
发布评论

评论列表(0)

  1. 暂无评论