I’ve got mmenu up and running and doing everything I need it to do, except that it’s breaking my sticky footer because it is automatically wrapping all code inside <body>
.
My script has
page: { selector: "#page" }
and I have the content I want to be wrapped inside <div id="page"></div>
and yet it still wraps around everything.
I am using the latest version from mmenujs.com.
Here’s an example layout of what I’ve got:
<html>
<head>
<link href="mmenu/mmenu.css" rel="stylesheet" />
</head>
<body style="min-height: 100vh; display: flex; flex-direction: column;">
<div id="page">All the page content</div>
<div id="footer" style="padding-top: 30px; padding-bottom: 20px; margin-top: auto;">My sticky footer</div>
<nav id="navmenu">
<ul>
<li><span>HOME</span></li>
<li><span>Example</span>
<ul>
<li><span>Test</span></li>
</ul>
</li>
</ul>
</nav>
<script src="mmenu/mmenu.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
function mediaqueryresponse(mql) {
var mmenuOptions = {
navbar: {
title: "My Menu"
},
offCanvas: {
page: {
selector: "#page"
},
position: "left-front"
},
pageScroll: {
scroll: true,
update: true
},
setSelected: {
current: "detect",
hover: true
},
sidebar: {
collapsed: {
use: "(min-width: 50px)"
},
expanded: {
use: "(min-width: 1024px)"
}
},
theme: "dark-contrast"
};
if (mql.matches) {
mmenuOptions.navbars = [
{
position: "top",
content: [
"prev",
"title",
"close"
]
}
];
} else {
mmenuOptions.navbars = [
{
position: "top",
content: [
"prev",
"title"
]
}
];
}
new Mmenu("#navmenu", mmenuOptions);
}
const mql = window.matchMedia("screen and (max-width: 900px)");
mediaqueryresponse(mql);
mql.addListener(mediaqueryresponse);
});
</script>
</body>
</html>
What happens is this:
<div id="mm-4" class="mm-page mm-slideout">
<div id="page"></div>
<div id="footer"></div>
</div>
which breaks my sticky footer.
I need it to be:
<div id="mm-4" class="mm-page mm-slideout">
<div id="page"></div>
</div>
<div id="footer"></div>
I know offCanvas is working because I can change position to be "right-front" and the menu appears on the right. I also have confirmed that #page is in the DOM before the function runs.
Of course without mmenu, my sticky footer works perfectly.
Not sure what I’m doing wrong, but appreciate any help. Thanks!
2
Answers
Turns out that while Shweta Mishra's answer was not the correct way to solve the problem, her idea of display: flex; flex-direction: column; min-height: 100vh; ended up being very helpful.
For anyone else having this issue, here's what needed to be done.
A complete rewrite of the mmenu firing script. The reason for this is apparently if you have media queries in mmenu, it breaks in a variety of different and very bad ways. So, I simplified it and made it work without the use of js media queries.
The offCanvas call for page is no longer in the options and is instead in the configuration, which means you need to write it separately as the second parameter when initializing the menu. As soon as I did that, it used #page for the menu as it should.
If you are trying to write responsive code (and you should), you need to use the mmenu offCanvas configuration option of clone: true. This prevents the menu's contents from disappearing when the orientation changes or the browser window is resized.
There were still a few CSS styles I needed to override but going back to Shweta's answer regarding the footer sticking to the bottom, I used her suggestion on #page and put the footer inside #page. This was the only way to get things working properly across all browsers and devices.
That code ended up looking like:
Hoping this answer helps others!
It appears that the issue is caused by the way Mmenu wraps the content inside the off-canvas element. To resolve the problem and prevent Mmenu from wrapping the footer inside the off-canvas element. By moving the footer div outside the body element, it will not be wrapped inside the off-canvas element, and your sticky footer should work as expected.