jQuery accordion menu: scroll to active menu item
I have made an accordion menu intended to serve as an efficient mobile phone menu. I have used the
jQuery 2.1.1 library for this purpose. The part that does not work as I want it to is that concerning the body tag animation. I want the document to scroll to the active menu item.
This is what I came up with:
The HTML:
- <nav id="menu">
- <ul>
- <li><a href="#" class="menu-item">Software</a>
- <ul class="sub-menu">
- <li><a href="#">Operating systems</a></li>
- <li><a href="#">MS Office</a></li>
- <li><a href="#">Web development tools</a></li>
- </ul>
- </li>
- <li><a href="#" class="menu-item">Monitors & screens</a>
- <ul class="sub-menu">
- <li><a href="#">Monitors</a></li>
- <li><a href="#">LCD</a></li>
- <li><a href="#">TV</a></li>
- <li><a href="#">DVD players</a></li>
- </ul>
- </li>
- <li><a href="#" class="menu-item">Networking</a>
- <ul class="sub-menu">
- <li><a href="#">Routers</a></li>
- <li><a href="#">Network Adapters</a></li>
- <li><a href="#">Modems</a></li>
- <li><a href="#">Cables</a></li>
- </ul>
- </li>
- <li><a href="#" class="menu-item">Print & scan</a>
- <ul class="sub-menu">
- <li><a href="#">Printers</a></li>
- <li><a href="#">3D printers</a></li>
- <li><a href="#">Scanners</a></li>
- </ul>
- </li>
- </ul>
- </nav>
The jQuery:
- $('#menu').children('ul').on('click', '.menu-item', function(e) {
- if ($(window).width() < 640) {
- e.preventDefault();
- var $menu_item = $(this).closest('li');
- var $sub_menu = $menu_item.find('.sub-menu');
- var $other_sub_menus = $menu_item.siblings().find('.sub-menu');
- if ($sub_menu.is(':visible')) {
- $sub_menu.slideUp(200);
- $menu_item.removeClass('selected');
- } else {
- $other_sub_menus.slideUp(200);
- $sub_menu.slideDown(200);
- $menu_item.siblings().removeClass('selected');
- $menu_item.addClass('selected');
- }
- }
- $('html,body').animate({
- scrollTop: $(this).offset().top
- }, 500);
- console.log($(this).offset().top);
- });
The CSS:
- nav ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- }
- #menu {
- max-width: 640px;
- }
- #menu ul {
- background: #069;
- }
- #menu ul.sub-menu {
- display: none;
- background: #fefefe;
- }
- #menu ul li a {
- text-decoration: none;
- display: block;
- font-size: 13px;
- color: #fff;
- padding: 0 10px;
- height: 32px;
- line-height: 30px;
- position: relative;
- border-top: 1px solid rgba(0, 0, 0, 0.1);
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- }
- #menu ul.sub-menu li a {
- padding-left: 25px;
- color: #555;
- }
- #menu > ul > li > a:after {
- display: inline-block;
- vertical-align: middle;
- content: "\2304";
- position: absolute;
- right: 0;
- font-size: 20px;
- line-height: 20px;
- padding-bottom: 10px;
- width: 30px;
- text-align: center;
- top: 0;
- color: #fff;
- }
- #menu li.selected a:after {
- -webkit-transform: rotate(180deg);
- -moz-transform: rotate(180deg);
- -ms-transform: rotate(180deg);
- -o-transform: rotate(180deg);
- }
Console logging the top offset gives an
aberrant value if you click multiple menu items
successively. As a consequence, the page does not scroll to the begginning of the active item. What ce I do?