Trouble with a responsive menu and jQuery’s slideToggle

I’m building a responsive navigation menu and I’m having trouble getting the nav items to become visible upon calling jQuery’s slideToggle(). The menu items (.nav_item) collapse appropriately, and then become invisible when the viewport is <640px, the first menu item (#nav_menu) “Menu” then becomes the only item visible. Upon clicking, I’d like the buttons to reappear and slide down below the menu button. When I click, however, nothing happens and the menu items remain invisible. If I take out display: none !important; from the menu items, they successfully toggle (but are visible the whole time). Does anyone know what’s going wrong? Thanks.

CSS (Compass):

#navUL {
  @include background-image(linear-gradient($blue_dark, $blue_light));
  text-align: center;
}
#navUL li {
  a:link, a:visited {
    color: white;
    text-decoration: none;
    display: block;
    height: 40px;
    padding: 0 25px 0 25px;
  }
  a:hover {
    @include background-image(linear-gradient($red_dark, $red_light));
  }
  display: inline-block;
  color: white;
  line-height: 40px;
  font-family: Helvetica;
}
#nav_menu {
  display: none !important;
}
@media only screen and (max-width: 640px) {

  #nav_menu {
    display: inline !important;
  }

  .nav_item {
    display: none !important;
  }

  #navUL li {
    display: inline;
  }
}

HTML:

<!DOCTYPE HTML>
<html>
<head>
<link href="stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" />
<!--[if IE]>
<link href="/stylesheets/ie.css" media="screen, projection" rel="stylesheet" type="text/css" />
<![endif]-->
</head>
<body>
  <div class="wrapper">
    <header>
        <img src="top_banner.jpg">
    </header>
    <nav>
        <ul id="navUL">
            <li id="nav_menu"><a href="#">Menu</a></li>
            <li class="nav_item"><a href="#">Home</a></li>
            <li class="nav_item"><a href="#">Search</a></li>
            <li class="nav_item"><a href="#">Submit</a></li>
            <li class="nav_item"><a href="#">News</a></li>
            <li class="nav_item"><a href="#">Blog</a></li>
            <li class="nav_item"><a href="#">About</a></li>
        </ul>
    </nav>
    <div id="main">
    </div>
  </div>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</body>
</html>

JS:

$(document).ready(function(){
    $('#nav_menu').on('click', function(e){
        e.preventDefault();
        $('.nav_item').slideToggle('slow');
    });
});

solution

It was basically just a specificity issue.

Even though jQuery’s .slideToggle() method adds inline styling, it still wasn’t having an effect when the screen size was less than 640px because you were using !important.

@media only screen and (max-width: 640px)
  .nav_item {
    display: none !important;
  }
}

More specifically, the above styling in your media query was overwriting the styling added by jQuery:

<li class="nav_item" style="display: list-item;"><a href="#">Home</a></li>

To solve this, remove all instances of !important in your stylesheet and re-structure the styling with the specificity issues in mind. If I were you, I would avoid using id’s like this. Simple classes would suffice and help avoid future issues like this. Without changing any HTML, though, this would work:

#navUL #nav_menu {
  display: none;
}

@media only screen and (max-width: 640px) {
#navUL #nav_menu {
    display: inline-block;
  }
#navUL .nav_item {
    display: none;
  }
}

Since you’re already using jQuery, use the resize event to remove the jQuery styling when the screen size wider than 640px.

$(window).on("resize", function () {
  if ($(window).width() > 640) {
    $('.nav_item').css('display','');
  }
}).resize();

This should take care of everything. Take a look at this working example.