sazr
sazr

Reputation: 25928

FadeIn() breaks CSS hover functionality

Why does jQuery's .fadeIn() function break my CSS hover functionality? My div should show its menu when you hover over it. When my page shows I am going to make the menu fade in then it should have my regular hover functionality.

This JSFiddle demonstrates the problem nicely.

Why does it break my hover functionality and how can I keep both the fade in and hover functionality?

Note I need to keep display: flex to ensure the menu div doesn't wrap if its wider than its parent div.

.widget {
  position: relative;
  width: 300px;
  height: 300px;
  background-color: #ddd;
}
.widget-menu {
  width: 400px;
  height: 100px;
  background-color: #555;
  position: absolute;
  top: 0;
  display: none;
}
.widget:hover .widget-menu {
  display: flex;
  /* used to ensure wrapping doesn't occur if the menu is wider than the widget container */
}
.widget:enabled .widget-menu {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="widget">
  <div class="widget-menu">
    <button>Btn 1</button>
  </div>
  <br/>
  <br/>
  <br/>
  <br/>
  <br/>
  <p>Hover me to see menu appear. Then click the below button. Now my hovering is screwed up after the animation is complete.</p>
</div>

<br/>
<button>Fade In</button>

Upvotes: 1

Views: 138

Answers (3)

Pete
Pete

Reputation: 58422

You need to activate the fadeIn with flex:

$('.widget-menu').css('display', 'flex').hide(); // do this on doc ready or before you call the fadeIn

$('.widget-menu').fadeIn('slow'); // fade in will now use flex instead of block

Updated fiddle

Update

Sorry, thought you just wanted the fadeIn to work with flex. If you want the hover to work after you have done the fadeIn, you need to remove the style from menu when you next hover

var menu = $('.widget-menu');
menu.css('display', 'flex').hide();
$('body > button').click(function() {
  menu.fadeIn('slow');
});

$('.widget').on('mouseover', function() {
  $(this).find('.widget-menu').hide();
})

New Fiddle

Upvotes: 1

Shnibble
Shnibble

Reputation: 110

The problem is that JQuery runs after the CSS is loaded, so any attributes that JQuery touches will now be overridden. Instead of applying the changes to show the menu directly, try using JQuery to toggle a class that mimics the :hover pseudo class such as .hover and add that class to your html. Then use JQuery to remove the .hover class once the mouse enters and then leaves the area. This way JQuery doesn't touch your initial CSS and it will work as intended once the .hoverclass is removed.

Here is a fiddle demonstrating: https://jsfiddle.net/2dbr2bs3/.

Upvotes: 0

roberrrt-s
roberrrt-s

Reputation: 8210

It's because of jQuery's .fadeIn() method that adds an inline style that overrides the hover. I have updated your code with some explanation to do exactly what you want:

// When document is ready...
$(document).ready(function() {
    // Fade in the menu, to show the user it's there.
    $('.widget-menu').fadeIn('slow', function() {
        // Fade out the menu, like you want
        $('.widget-menu').fadeOut('slow', function() {
            // Reset the inline style to not mess with the :hover
            $('.widget-menu').attr('style', '');
        });
    }); 
});

Upvotes: 0

Related Questions