When the menu and the panel with subcategories are open, the panel with subcategories disappears faster when closed.

  1. How to synchronize the animation of hiding panels mob. menu?
  2. Why are they hiding at different speeds if everyone has the same duration?
  3. Why is there an animation when the page loads?

$('.trigger-menu').on('click', function() { $('body').toggleClass('menu-open'); }); $('.bg').on('click', function() { $("#mobile-menu-trigger:checked,.menu-inner-trigger:checked").prop("checked", false).change(); $('body').toggleClass('menu-open'); }); 
 ul, li { list-style: none; margin: 0; padding: 0; } .container { width: 500px; height: auto; margin: auto; padding: 15px; overflow: hidden; border: 1px solid lightgrey; position: relative; height: 300px; } .mobile-menu { width: 80%; max-width: 300px; position: fixed; top: 0; right: auto; bottom: 0; animation-name: slidemenuback; animation-duration: 0.3s; animation-timing-function: easy-in-out; animation-fill-mode: forwards; transform: translateX(-100%); left: 0; z-index: 5; box-shadow: 3px 0 4px lightgrey; background: #fff; } .mobile-menu__header { width: 100%; padding: 10px 0; border-bottom: 1px solid #ff4081; background: #fff; } .mobile-menu__logo-wrapper { width: 150px; margin: 0 auto; } .mobile-menu__list { width: 100%; height: 100%; } .mobile-menu__item { border-bottom: 1px solid lightgrey; } .mobile-menu__link { padding: 5px; display: block; } .mobile-menu__inner { background: #f78a8a; width: 100%; position: fixed; top: 0; left: 0; right: auto; bottom: 0; transform: translateX(-100%); animation-name: slidemenuback; animation-duration: 0.3s; animation-timing-function: easy-in-out; animation-fill-mode: forwards; } #mobile-menu-trigger:checked + .mobile-menu { animation-name: slidemenu; animation-duration: 0.3s; animation-timing-function: easy-in-out; animation-fill-mode: forwards; } input[data-menu="menu"]:checked + .mobile-menu__inner { animation-name: slidemenu; animation-duration: 0.3s; animation-timing-function: easy-in-out; animation-fill-mode: forwards; } .display-hidden { display: none; } .trigger-menu { background: #91a2f7; float: right; } .bg { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: rgba(255, 255, 255, 0.8); z-index: 1; visibility: hidden; opacity: 0; } .menu-open .bg { opacity: 1; visibility: visible; } .logo { width: 100%; height: auto; } .menu-back-trigger { border-bottom: 1px solid #ff4081; } @keyframes slidemenu { 0% { transform: translateX(-100%); } 100% { transform: translateX(0); } } @keyframes slidemenuback { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="container"> <label class="trigger-menu" for="mobile-menu-trigger">Trigger</label> <input id="mobile-menu-trigger" class="display-hidden" type="checkbox"> <nav class="mobile-menu"> <header class="mobile-menu__header"> <div class="mobile-menu__logo-wrapper"> </div> </header> <ul class="mobile-menu__list"> <li class="mobile-menu__item"> <label class="mobile-menu__link" for="menu-inner-trigger-1">Category</label> <input id="menu-inner-trigger-1" class="menu-inner-trigger display-hidden" type="checkbox" data-menu="menu"> <div class="mobile-menu__inner"> <label class="mobile-menu__link menu-back-trigger" for="menu-inner-trigger-1">Category</label> <ul class="mobile-menu__inner-list"> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category2 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category3 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category4 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category5 </a> </li> </ul> </div> </li> <li class="mobile-menu__item"> <label class="mobile-menu__link" for="menu-inner-trigger-2">Category2</label> <input id="menu-inner-trigger-2" class="menu-inner-trigger display-hidden" type="checkbox" data-menu="menu"> <div class="mobile-menu__inner"> <label class="mobile-menu__link" for="menu-inner-trigger-2">Category2</label> <ul class="mobile-menu__inner-list"> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category2 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category3 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category4 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category5 </a> </li> </ul> </div> </li> <li class="mobile-menu__item"> <a href="#" class="mobile-menu__link"> Delivery </a> </li> <li class="mobile-menu__item"> <a href="#" class="mobile-menu__link"> About </a> </li> </ul> </nav> <div class="bg"></div> </div> 

  • Set animations to animation-timing-function: linear . And it disappears in different ways then that the width of the submenu is smaller than the menu itself - Yuri

2 answers 2

  1. Specifically, in this case, there is no need for animation, just a transition . With JS, you only need to turn off the #mobile-menu-trigger checkbox, then track the transtionend for the menu, and only then turn off the checkbox for the internal menu to hide it invisibly.

Note: since transtionend works on any transtion inside the block, and we need to determine the end of the animation only in the external menu, it is necessary to check which block finished the animation (1) .

  1. Desynchronization of animations occurred due to the fact that the category menu was inside the element to which the animation is applied and, accordingly, its speed was doubled. Explanation : when the animation was launched, the external menu began to move to the left at a speed of 100pcs / 0.3s; at the same time, the internal menu started moving to the left with the same speed plus its own speed of 100px / 0.3s, respectively, its speed was (100pcs / 0.3s) * 2.

  2. Because initially the menu is in the visible area, and then the animation begins and takes the menu beyond the limits of the visible area.

 $('.trigger-menu').on('click', function() { $('body').toggleClass('menu-open'); }); $('.bg').on('click', function() { $("#mobile-menu-trigger:checked").prop("checked", false); // по клику на .bg выключаем чекбокс, который связан с внешним меню $('body').toggleClass('menu-open'); }); $('.mobile-menu').on('transitionend', function(e) { // вешаем обработчик на событие "transitionend" для внешнего меню if ( $(e.target).attr('class') === 'mobile-menu' ) { // (1) // поскольку событие "transitionend", несмотря на то, что навешено только на внешнее меню, срабатывает также при окончании transition у .mobile-menu__inner, нам надо отделить .mobile-menu. // e.target позволяет определить элемент, на котором происходит событие transitionend. Затем мы проверяем есть ли у него класс mobile-menu и, если есть, выключаем чекбокс, который связан с внутренним меню, т. о. скрывая его $('input[data-menu="menu"]').prop("checked", false); } }); 
 ul, li { list-style: none; margin: 0; padding: 0; } .container { width: 500px; height: auto; margin: auto; padding: 15px; overflow: hidden; border: 1px solid lightgrey; position: relative; height: 300px; } .mobile-menu { width: 80%; max-width: 300px; position: fixed; top: 0; right: auto; bottom: 0; transform: translateX(-100%); transition: .5s; left: 0; z-index: 5; box-shadow: 3px 0 4px lightgrey; background: #fff; } .mobile-menu__header { width: 100%; padding: 10px 0; border-bottom: 1px solid #ff4081; background: #fff; } .mobile-menu__logo-wrapper { width: 150px; margin: 0 auto; } .mobile-menu__list { width: 100%; height: 100%; } .mobile-menu__item { border-bottom: 1px solid lightgrey; } .mobile-menu__link { padding: 5px; display: block; } .mobile-menu__inner { background: #f78a8a; width: 100%; position: fixed; top: 0; left: 0; bottom: 0; transform: translateX(-100%); transition: .5s; } #mobile-menu-trigger:checked + .mobile-menu, input[data-menu="menu"]:checked + .mobile-menu__inner { transform: translateX(0); } .display-hidden { display: none; } .trigger-menu { background: #91a2f7; float: right; } .bg { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: rgba(255, 255, 255, 0.8); z-index: 1; visibility: hidden; opacity: 0; } .menu-open .bg { opacity: 1; visibility: visible; } .logo { width: 100%; height: auto; } .menu-back-trigger { border-bottom: 1px solid #ff4081; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="container"> <label class="trigger-menu" for="mobile-menu-trigger">Trigger</label> <input id="mobile-menu-trigger" class="display-hidden" type="checkbox"> <nav class="mobile-menu"> <header class="mobile-menu__header"> <div class="mobile-menu__logo-wrapper"> </div> </header> <ul class="mobile-menu__list"> <li class="mobile-menu__item"> <label class="mobile-menu__link" for="menu-inner-trigger-1">Category</label> <input id="menu-inner-trigger-1" class="menu-inner-trigger display-hidden" type="checkbox" data-menu="menu"> <div class="mobile-menu__inner"> <label class="mobile-menu__link menu-back-trigger" for="menu-inner-trigger-1">Category</label> <ul class="mobile-menu__inner-list"> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category2 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category3 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category4 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category5 </a> </li> </ul> </div> </li> <li class="mobile-menu__item"> <label class="mobile-menu__link" for="menu-inner-trigger-2">Category2</label> <input id="menu-inner-trigger-2" class="menu-inner-trigger display-hidden" type="checkbox" data-menu="menu"> <div class="mobile-menu__inner"> <label class="mobile-menu__link" for="menu-inner-trigger-2">Category2</label> <ul class="mobile-menu__inner-list"> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category2 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category3 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category4 </a> </li> <li class="mobile-menu__inner-item"> <a href="#" class="mobile-menu__link"> Inner category5 </a> </li> </ul> </div> </li> <li class="mobile-menu__item"> <a href="#" class="mobile-menu__link"> Delivery </a> </li> <li class="mobile-menu__item"> <a href="#" class="mobile-menu__link"> About </a> </li> </ul> </nav> <div class="bg"></div> </div> 

  • animation is used because the mob. devices transition was performed with jerks. Did I understand correctly that all the effects of the embedded fields always run 2 times faster? Please explain what happens in this part of the code if ($ (e.target) .attr ('class') ===' mobile-menu ') {// (1) $ (' input [data-menu = " menu "] '). prop (" checked ", false); } I understand that he turns off the checkbox, but I don’t understand how he addresses the right one and I can’t explain this part of $ (e.target) .attr ('class') ===' mobile-menu ' - E_K
  • updated the answer, added comments to the code and the text itself. - Sasha Omelchenko

Try this:

 $('#Trigger').click( function(){ $('.sidebar').toggleClass('active'); }) 
 * { box-sizing: border-box; } .container { position: relative; border: 1px solid #f2f2f2; width: 400px; height: 400px; margin: 30px auto; overflow: hidden; } .container .trigger { display: inline-block; background: #d5d5d5; padding: 10px; width: 30px; cursor: pointer; position: absolute; right: 0; top: 0; } .container .trigger:hover { opacity: 0.8; } .container .sidebar { position: absolute; width: 100px; background: #f2f2f2; height: 100%; -webkit-transform: translateX(-100%); transform: translateX(-100%); -webkit-transition: cubic-bezier(0.11, 0.94, 0.32, 0.97) 400ms; transition: cubic-bezier(0.11, 0.94, 0.32, 0.97) 400ms; } .container .sidebar.active { -webkit-transform: translateX(0); transform: translateX(0); } .container .sidebar .option_menu { border-bottom: 1px solid #d5d5d5; margin: 2px 4px; padding: 5px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="container"> <div id="Trigger" class="trigger"> ! </div> <div class="sidebar"> <div class="option_menu">1</div> <div class="option_menu">2</div> <div class="option_menu">3</div> <div class="option_menu">4</div> <div class="option_menu">5</div> </div> </div>