I'm trying to create a sidebar which contains 2 sticky elements. The issue is when the screen size is changed, the elements start to overlapping each other. I wanted to find a way to prevent that overlapping and add some minimal 'margin between' them.
body {
height: 200vh;
}
.sidebar {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100vh;
}
.topSticky {
position: sticky;
top: 2rem;
padding-bottom: 2rem;
width: 100px;
height: 100px;
border: 1px solid black;
}
.bottomSticky {
position: sticky;
bottom: 2rem;
width: 100px;
height: 100px;
border: 1px solid black;
}
<div class="sidebar">
<aside class="topSticky">Top sticky</aside>
<aside class="bottomSticky">Bottom sticky</aside>
</div>
I also tried several ways to detect collisions but it was too complex to observe and cover all cases.
There are a few issues and limitations -
How can I achieve that behaviour? In essence, I should find a way to avoid the overlapping.
Thanks.
I made a fiddle. Is this what you are trying to achieve?
https://jsfiddle.net/g7y04dv5/
I only modified the JavaScript but made some styling changes via JavaScript to make it visually more clear that is happening...
// get the sticky elements and their container
const first = document.querySelector('.topSticky');
const second = document.querySelector('.bottomSticky');
const sideBar = document.querySelector('.sidebar');
// make some temporary styling amends so we can see what is happening better
sideBar.style.background = 'linear-gradient(20deg, pink, #6275ff)';
sideBar.style.height = '2000px';
sideBar.style.borderBottom = '300px solid beige';
document.querySelector('body').style.margin = 0;
function stickyMe() {
const aRem = 16; // roughly a rem
const marginBetween = aRem * 2; // roughly 2 rem
const containerHeight = window.innerHeight; // height of the window
const firstHeight = first.offsetHeight; // height of first sticky element
const secondHeight = second.offsetHeight; // height of second sticky element
const minimimGap = firstHeight + secondHeight + marginBetween + (aRem * 4); // height of both sticky elements plus their gaps between eachother and the window
if (containerHeight <= minimimGap) { // if the window height is less or equal to the minimimGap
const newTopPosition = containerHeight - minimimGap;
first.style.transform = 'translateY(' + newTopPosition + 'px)'; // pull the first sticky element up by the amount smaller the window is compared to the minimumGap
}
else {
first.style.transform = 'none'; // if the gap is large enough for the 2 elements to not overlap then return to normal state
}
}
window.addEventListener('DOMContentLoaded', stickyMe);;
window.addEventListener('scroll', stickyMe);
window.addEventListener('resize', stickyMe);