1(function IIFE() { 2 3 let bodyElementWasChanged = false; 4 let fixedMenuSelector = `.navbar[data-type="fixed-top"]`; 5 6 /** 7 * anchor scroll: 8 * Add the target style before anchor navigation 9 * otherwise the content is below the menubar 10 */ 11 window.addEventListener("DOMContentLoaded", function () { 12 13 let fixedNavbar = document.querySelector(fixedMenuSelector) 14 if (fixedNavbar == null) { 15 return; 16 } 17 let offsetHeight = fixedNavbar.offsetHeight; 18 // correct direct navigation via fragment to heading 19 let style = document.createElement("style"); 20 style.classList.add("menubar-fixed-top") 21 // textContent and not innerText (it adds br elements) 22 style.textContent = `:target { 23 scroll-margin-top: ${offsetHeight}px; 24}`; 25 document.head.appendChild(style); 26 }) 27 28 /** 29 * We do the work after the first scroll 30 * to prevent a bad cls (content layout shift) metrics 31 * from Google search 32 */ 33 window.addEventListener("scroll", function () { 34 35 if (bodyElementWasChanged) { 36 return; 37 } 38 // Case on mobile when the menu is expanded 39 // in this case, we don't calculate the offset 40 // otherwise it would take the height of the menu bar 41 let activeElement = document.activeElement; 42 if( 43 activeElement.classList.contains('navbar-toggler') 44 && activeElement.getAttribute("aria-expanded")==="true" 45 ){ 46 return; 47 } 48 bodyElementWasChanged = true; 49 50 /** 51 * The request animation frame is there to 52 * update the class on the navbar and the padding on the 53 * body at the same time to not have any layout shift 54 */ 55 window.requestAnimationFrame(function () { 56 let fixedNavbar = document.querySelector(fixedMenuSelector) 57 if (fixedNavbar == null) { 58 return; 59 } 60 let offsetHeight = fixedNavbar.offsetHeight; 61 fixedNavbar.classList.add("fixed-top") 62 // correct body padding 63 document.body.style.setProperty("padding-top", offsetHeight + "px"); 64 }); 65 66 }); 67})(); 68