diff -u b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css --- b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css +++ b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css @@ -11,33 +11,20 @@ font-size: 1.266rem; font-weight: 400; line-height: 1.2; - max-height: 18.75rem; overflow: hidden; padding: 0; + transition: height 0.5s ease-in-out; + height: 0; } -.menu-main--collapsed { - /** - * An exact max-height value must be set to make possible to animate the menu display. - * It my not be much larger than the content because that would break the animation. - * See: https://css-tricks.com/using-css-transitions-auto-dimensions/ - */ - max-height: 0; +@media screen and (prefers-reduced-motion: reduce) { + .menu-main { + transition: height 0s; + } } + .menu-main--collapsed li { visibility: hidden; - transition: visibility 0.5s ease-in; -} - -.menu-main--transition { - transition: max-height 0.5s ease-in; -} - - -@media screen and (prefers-reduced-motion: reduce) { - .menu-main--transition { - transition: 0s; - } } .menu-main-toggle { @@ -97,11 +84,11 @@ display: flex; justify-content: flex-end; flex-wrap: wrap; - max-height: none; overflow: auto; + height: auto !important; } .menu-main--collapsed li { - visibility: visible; + visibility: unset; } .menu-main-toggle { display: none; diff -u b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.es6.js b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.es6.js --- b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.es6.js +++ b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.es6.js @@ -13,19 +13,58 @@ toggler.setAttribute('aria-expanded', 'false'); toggler.setAttribute('aria-controls', menu.getAttribute('id')); + function collapseSection(element) { + // get the height of the element's inner content, regardless of its actual size + var sectionHeight = element.scrollHeight; + + // temporarily disable all css transitions + var elementTransition = element.style.transition; + element.style.transition = ''; + + // on the next frame (as soon as the previous style change has taken effect), + // explicitly set the element's height to its current pixel height, so we + // aren't transitioning out of 'auto' + requestAnimationFrame(function() { + element.style.height = sectionHeight + 'px'; + element.style.transition = elementTransition; + + // on the next frame (as soon as the previous style change has taken effect), + // have the element transition to height: 0 + requestAnimationFrame(function() { + element.style.height = 0 + 'px'; + + requestAnimationFrame(function() { + // remove "height" from the element's inline styles, so it can return to its initial value + element.style.height = null; + }); + }); + }); + } + + function expandSection(element) { + // get the height of the element's inner content, regardless of its actual size + var sectionHeight = element.scrollHeight; + + // have the element transition to the height of its inner content + element.style.height = sectionHeight + 'px'; + + // when the next css transition finishes (which should be the one we just triggered) + element.addEventListener('transitionend', function(e) { + // remove this event listener so it only gets triggered once + element.removeEventListener('transitionend', arguments.callee); + }); + } + function toggleMenu() { const expanded = toggler.getAttribute('aria-expanded'); - // We want to avoid showing a collapse on page load, so don't enable the CSS - // transitions until the button is actually pressed for the first time. This - // class should remain in place during subsequent presses. - menu.classList.add('menu-main--transition'); - if (expanded === 'false') { toggler.setAttribute('aria-expanded', 'true'); menu.classList.remove('menu-main--collapsed'); + expandSection(menu); } else { toggler.setAttribute('aria-expanded', 'false'); + collapseSection(menu); menu.classList.add('menu-main--collapsed'); } } diff -u b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.js b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.js --- b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.js +++ b/core/profiles/demo_umami/themes/umami/js/components/navigation/menu-main/menu-main.js @@ -13,16 +13,46 @@ toggler.setAttribute('aria-expanded', 'false'); toggler.setAttribute('aria-controls', menu.getAttribute('id')); + function collapseSection(element) { + var sectionHeight = element.scrollHeight; + + var elementTransition = element.style.transition; + element.style.transition = ''; + + requestAnimationFrame(function () { + element.style.height = sectionHeight + 'px'; + element.style.transition = elementTransition; + + requestAnimationFrame(function () { + element.style.height = 0 + 'px'; + + requestAnimationFrame(function () { + element.style.height = null; + }); + }); + }); + } + + function expandSection(element) { + var sectionHeight = element.scrollHeight; + + element.style.height = sectionHeight + 'px'; + + element.addEventListener('transitionend', function (e) { + element.removeEventListener('transitionend', arguments.callee); + }); + } + function toggleMenu() { var expanded = toggler.getAttribute('aria-expanded'); - menu.classList.add('menu-main--transition'); - if (expanded === 'false') { toggler.setAttribute('aria-expanded', 'true'); menu.classList.remove('menu-main--collapsed'); + expandSection(menu); } else { toggler.setAttribute('aria-expanded', 'false'); + collapseSection(menu); menu.classList.add('menu-main--collapsed'); } }