Reputation: 67
I'm running into a situation where I'm trying to have a slide in side menu that's also sticky. Whenever I add position: sticky to my menu container, it makes the entire menu display (rather than being shoved off the screen via a negative left value) and the button used to open and close the menu no longer works.
The menu animation works totally fine with the container on absolute by the way. So I'm wondering if I'm missing something in order to have both work, or you just can't do both at all (or at least not the way I'm trying to do it.
Here's a link a codepen I made to show the issue:
Here's a snippet of the css:
#side-menu-container{
width: 100%;
max-width: 300px;
height: 100%;
min-height: 1000px;
position: absolute;
left: 0;
top: 0;
}
/* if I change the positioning here, the event will work */
#side-menu{
width: 100%;
max-width: 330px;
padding: 1rem 0;
background: #cccccc;
position: sticky;
left: -300px;
top: 100px;
}
#side-menu ul{
text-align: center;
}
#side-menu li{
list-style-type: none;
margin: 1rem;
}
#side-menu-btn{
width: 50px;
height: 50px;
position: absolute;
left: 100%;
background: #cccccc;
cursor: pointer;
}
#side-menu.side-menu-open{
left: 0;
}
Oh I should mention I've tried having my main container element, housing both the button and the menu, set to relative, and I've also tried adding z-index:0 and z-index: 99999 to the main container, button, and menu to no avail. Which makes me think there isn't an element covering it.
Upvotes: 0
Views: 475
Reputation: 643
Issue
The reason why #side-menu's negative left value does not work is because position sticky still sets the element in the normal flow. It means that the element cannot go outside the ancestor like absolute / fixed elements.
Solution
The solution is simply set #side-menu-container's left value to -300px, and edit your JS to change #side-menu-container's value instead of #side-menu. This works the way you intend because #side-menu-container is positioned absolute which means it can be located outside the window / the nearest ancestor that is set relative.
The explanation of postion relative from MDN:
The element is positioned according to the normal flow of the document, and then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor), including table-related elements, based on the values of top, right, bottom, and left. The offset does not affect the position of any other elements.
https://developer.mozilla.org/en-US/docs/Web/CSS/position
I edited the code.
CSS
#side-menu-container{
width: 100%;
max-width: 300px;
height: 100%;
min-height: 1000px;
position: absolute;
left: -300px;
top: 0;
}
/* if I change the positioning here, the event will work */
#side-menu{
width: 100%;
max-width: 330px;
padding: 1rem 0;
background: #cccccc;
position: sticky;
top: 100px;
}
#side-menu ul{
text-align: center;
}
#side-menu li{
list-style-type: none;
margin: 1rem;
}
#side-menu-btn{
width: 50px;
height: 50px;
position: absolute;
left: 100%;
background: #cccccc;
cursor: pointer;
}
#side-menu-container.side-menu-open{
left: 0;
}
JS
const sideMenu = document.querySelector('#side-menu-container');
const sideMenuBtn = document.querySelector('#side-menu-btn');
sideMenuBtn.addEventListener('click', () => {
sideMenu.classList.toggle('side-menu-open');
});
Upvotes: 1
Reputation: 94
I list all your problems in this code.
left: 0
;main
have css height
remove it.javascript
will not open the added class side-menu-open
because of your parent.I hope it helps, if you have question just comment below. 😊
const sideMenu = document.querySelector('#side-menu-container');
const sideMenuBtn = document.querySelector('#side-menu-btn');
sideMenuBtn.addEventListener('click', () => {
sideMenu.classList.toggle('side-menu-open');
})
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
main{
width: 100%;
}
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 2rem auto;
position: relative;
}
h1{
width: 100%;
max-width: 750px;
margin-bottom: 2rem;
text-align: center;
}
section p{
width: 100%;
max-width: 750px;
margin-bottom: 1rem;
line-height: 25px;
}
#side-menu-container{
width: 100%;
max-width: 300px;
height: 100%;
position: absolute;
left: -300px;
top: 0;
}
/* if I change the positioning here, the event will work */
#side-menu{
width: 100%;
max-width: 330px;
padding: 1rem 0;
background: #cccccc;
position: sticky;
top: 100px;
}
#side-menu ul{
text-align: center;
}
#side-menu li{
list-style-type: none;
margin: 1rem;
}
#side-menu-btn{
width: 50px;
height: 50px;
position: absolute;
left: 100%;
background: #cccccc;
cursor: pointer;
}
#side-menu-container.side-menu-open{
left: 0;
}
<main>
<section>
<div id="side-menu-container">
<div id="side-menu">
<div id="side-menu-btn">Open</div>
<ul>
<li><a href="">Some Link</a></li>
<li><a href="">Some Link</a></li>
<li><a href="">Some Link</a></li>
<li><a href="">Some Link</a></li>
<li><a href="">Some Link</a></li>
<li><a href="">Some Link</a></li>
</ul>
</div>
</div>
<h1>I'm Just Here to be Here</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sit amet finibus neque. Praesent fermentum consequat neque, ac iaculis eros maximus et. Suspendisse aliquet non sem sed eleifend. Sed pretium arcu id nulla sollicitudin venenatis. Nullam posuere ipsum eget pharetra ultrices. Aliquam erat volutpat. Duis quam tortor, dignissim at efficitur vel, volutpat eget orci. Nulla tristique mi odio, viverra rutrum odio molestie sed. Maecenas faucibus justo non rhoncus consequat. Vestibulum quis elementum purus.</p>
<p>Suspendisse eu leo egestas, euismod justo at, blandit risus. Nam dapibus ac ante vitae pellentesque. Etiam congue ligula ut ante mollis mollis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut egestas laoreet pulvinar. Cras sed neque nec est scelerisque maximus in eget turpis. Etiam pharetra accumsan justo, ac pellentesque libero dignissim et. Curabitur id egestas ligula, nec tristique elit. Aenean fringilla urna justo, a congue felis feugiat quis.</p>
<p>Praesent vehicula consequat enim ac consectetur. Suspendisse eget sem nec mi posuere volutpat sit amet nec eros. Pellentesque et laoreet velit, ut ultricies sapien. Integer hendrerit lorem arcu, in consequat arcu accumsan quis. Sed diam nisl, fermentum id tristique sed, placerat vitae eros. Fusce pulvinar mi urna, in ultrices justo suscipit eget. Proin ut nunc arcu. Nullam dictum ut nulla pulvinar tempus. Sed enim sapien, lacinia vitae ullamcorper non, tempor sed velit. Duis euismod, turpis sed gravida euismod, odio purus finibus tortor, nec euismod libero risus porttitor velit. Duis suscipit erat a fermentum malesuada. Maecenas quam lacus, accumsan sed nunc id, fermentum lobortis augue. Etiam id tortor eros. Ut tincidunt iaculis felis, et efficitur arcu elementum et.</p>
</section>
</main>
Upvotes: 2