.CategoryBlock {
margin-top: 0.5rem;
gap: 1rem;
display: flex;
overflow-x: scroll;
scrollbar-width: thin;
}
.CategoryBlock>*:first-child {
margin-left: auto;
}
.CategoryBlock>*:last-child {
margin-right: auto;
}
.CategoryBlock button {
font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: 2rem;
border: 0;
color: #2e652d;
background-color: white;
position: relative;
}
.CategoryBlock button:hover {
color: #51b44f
}
.Categories {
position: absolute;
display: none;
border: #2e652d;
background-color: hsl(0, 0%, 95%);
border-color: #2e652d;
border-style: solid;
border-width: thin;
max-width: 10rem;
}
.DropDown a {
display: block;
text-decoration: none;
color: #63815f;
font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: 1.125rem;
margin: 0rem 0.5rem 1rem 0.5rem;
}
.DropDown a:hover {
text-decoration: underline;
}
.DropDown:hover .Categories {
display: block;
}
<nav class="CategoryBlock">
<div class="DropDown">
<button>
Articles
</button>
<nav class="Categories">
<a></a>
<a href="">Feature articles</a>
<a href="">Opinion articles</a>
<a href="">Informative</a>
</nav>
</div>
<div class="DropDown">
<button>
Short stories
</button>
<nav class="Categories">
<a></a>
<a href="">Narratives</a>
<a href="">Retellings</a>
<a href="">Poetic</a>
</nav>
</div>
<div class="DropDown">
<button>
Essays
</button>
<nav class="Categories">
<a></a>
<a href="">Persuassive</a>
<a href="">Summaries</a>
<a href="">Book reviews</a>
</nav>
</div>
<div class="DropDown">
<button>
Debates
</button>
</div>
<div class="DropDown">
<button>
Scientific reports
</button>
<nav class="Categories">
<a></a>
<a href="">Physics</a>
<a href="">Chemistry</a>
</nav>
</div>
<div class="DropDown">
<button>
Devlogs
</button>
<nav class="Categories">
<a></a>
<a href="">Physom</a>
<a href="">Automatic Page Generator</a>
</nav>
</div>
<div class="DropDown">
<button>
Programs
</button>
<nav class="Categories">
<a></a>
<a href="">Physom</a>
<a href="">Automatic Page Generator</a>
<a href="">Raytracer</a>
<a href="">3D renderer</a>
</nav>
</div>
<div class="DropDown">
<button>
Math
</button>
<nav class="Categories">
<a></a>
<a href="">Discrete</a>
<a href="">Linear Algebra</a>
<a href="">PreCalculus</a>
<a href="">Calculus</a>
</nav>
</div>
</nav>
I have a dropdown box that won't move with the buttons as they are scrolled into a different position, this is because the dropdown box is absolute,and I have no idea how to: keep the absolute behaviour, but sort of anchor it to the button itself, rather than its own absolute positioning, basically I want to create a dropdown box that is under the button, but also acts absolute and effects no margins, i tried making the category block relative, but that just added a overflow-y rather than the effect I was looking for.
It would be very helpful if someone pointed me in the right direction!
The problem you are facing is that when you scroll past the right fold on the page horizontally, the browser is calculating the position of the absolute dropdown element prior to the scroll, in relation to the element before it was scrolled. It then places the dropdown elements list in that position relative to the browser window despite whether you have scrolled the button element to the right.
To fix this you can use some javascript to detect where the button element is on mouseover
. Then pass that to your CSS left position for the child dropdown elements with a cssStyleDeclaration method, setProperty()
using a CSS variable.
The snippet below is a rough example of how you can control the dropdown elements position with Javascript using the position of the buttons element taken on mouseover, whether the NAV buttons are scrolled or not. I have included a scrollIntoView() method for button elements that are hovered while overflow is present.
I have included further explanation within the snippet.
// get the dropdown nodeLists
const dropBtns = document.querySelectorAll('.DropDown button');
// iterate over the nodelist
dropBtns.forEach(btn => {
// add a mouseover eventListener and pass the event
btn.addEventListener('mouseover', (e) => {
// query the Categories within the eventListeners parent element
// using closest()
const category = btn.closest('.DropDown').querySelector('.Categories');
// get the height of the NAV so the dropdowns top position
// nca be placed just below the scroller for the NAV buttons
const navHeight = e.target.closest('.CategoryBlock').getBoundingClientRect().height;
// skip the elements (buttons) without a dropdown
if (category) {
// buffer for elements on the edge of the windows page
const buffer = 8;
// get the boundingClientRect for the eventTarget
const categoryRect = e.target.getBoundingClientRect();
// get the boundingClientRect for the dropdown elements
const dropdownWidth = category.getBoundingClientRect().width
// set the initial left position for elements
let categoryPosition = categoryRect.left;
// conditional to check for overflowing dropdown elements
// is the dropdown elements width overflowing past
// the left edge of the window?
if (window.innerWidth < categoryRect.left + dropdownWidth) {
// if true, set the right edge of the dropdown element to a
// buffer set to the left of windows innerWidth
categoryPosition = window.innerWidth - dropdownWidth - buffer;
// move any nav buttons overflowed element into view
btn.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
// else if the scrolled button is left of the windows fold
} else if (categoryRect.left < 0) {
// set the left of the dropdown to the buffer
categoryPosition = buffer;
// move any nav buttons overflowed element into view
btn.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" })
}
// pass the left position to a CSS variable using the root
// this will be used in CSS to set the .Categories left position
// var(--scrolled-left)
document.documentElement.style.setProperty('--scrolled-left', `${categoryPosition}px`);
// set the position of the top of the dropdown
// to below the scrollbar on the nav section
document.documentElement.style.setProperty('--top-pos', `${navHeight + buffer}px`);
}
})
})
.CategoryBlock {
margin-top: 0.5rem;
gap: 1rem;
display: flex;
overflow-x: scroll;
scrollbar-width: thin;
}
.CategoryBlock>*:first-child {
margin-left: auto;
}
.CategoryBlock>*:last-child {
margin-right: auto;
}
.CategoryBlock button {
font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: 2rem;
border: 0;
color: #2e652d;
background-color: white;
position: relative;
}
.CategoryBlock button:hover {
color: #51b44f
}
.Categories {
position: absolute;
left: var(--scrolled-left);
top: var(--top-pos);
display: none;
border: #2e652d;
background-color: hsl(0, 0%, 95%);
border-color: #2e652d;
border-style: solid;
border-width: thin;
max-width: 10rem;
}
.DropDown a {
display: block;
text-decoration: none;
color: #63815f;
font-family: "Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: 1.125rem;
margin: 0rem 0.5rem 1rem 0.5rem;
}
.DropDown a:hover {
text-decoration: underline;
}
.DropDown:hover .Categories {
display: block;
}
<nav class="CategoryBlock">
<div class="DropDown">
<button>
Articles
</button>
<nav class="Categories">
<a></a>
<a href="">Feature articles</a>
<a href="">Opinion articles</a>
<a href="">Informative</a>
</nav>
</div>
<div class="DropDown">
<button>
Short stories
</button>
<nav class="Categories">
<a></a>
<a href="">Narratives</a>
<a href="">Retellings</a>
<a href="">Poetic</a>
</nav>
</div>
<div class="DropDown">
<button>
Essays
</button>
<nav class="Categories">
<a></a>
<a href="">Persuassive</a>
<a href="">Summaries</a>
<a href="">Book reviews</a>
</nav>
</div>
<div class="DropDown">
<button>
Debates
</button>
</div>
<div class="DropDown">
<button>
Scientific reports
</button>
<nav class="Categories">
<a></a>
<a href="">Physics</a>
<a href="">Chemistry</a>
</nav>
</div>
<div class="DropDown">
<button>
Devlogs
</button>
<nav class="Categories">
<a></a>
<a href="">Physom</a>
<a href="">Automatic Page Generator</a>
</nav>
</div>
<div class="DropDown">
<button>
Programs
</button>
<nav class="Categories">
<a></a>
<a href="">Physom</a>
<a href="">Automatic Page Generator</a>
<a href="">Raytracer</a>
<a href="">3D renderer</a>
</nav>
</div>
<div class="DropDown">
<button>
Math
</button>
<nav class="Categories">
<a></a>
<a href="">Discrete</a>
<a href="">Linear Algebra</a>
<a href="">PreCalculus</a>
<a href="">Calculus</a>
</nav>
</div>
</nav>