NuxtUI DropdownMenu opens the menu at the top of the page when scrolling

I use NuxtUI UDropdownMenu in my header navigation. When the user scrolls the page, the header is sticky to the top. When user clicks the menu icon, the DropdownMenu opens but jumps all the header with the menu to the top of the page, so the user needs to scroll all the way to see the menu. If I close it with ESC, the menu returns to the correct position on the page This is how the code looks like
<nav class="hidden md:flex justify-end flex-1 text-center items-center">
<UNavigationMenu :items="baseItems" orientation="horizontal" class="inline-block" />
<div class="p-2">
<div v-if=".."> ... </div>
<div v-else>
<UDropdownMenu
:items="menuItems"
:ui="{
content: 'w-48',
}"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>
</div>
</div>
</nav>
<nav class="hidden md:flex justify-end flex-1 text-center items-center">
<UNavigationMenu :items="baseItems" orientation="horizontal" class="inline-block" />
<div class="p-2">
<div v-if=".."> ... </div>
<div v-else>
<UDropdownMenu
:items="menuItems"
:ui="{
content: 'w-48',
}"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>
</div>
</div>
</nav>
How can I fix it?
28 Replies
kapa.ai
kapa.ai5w ago
Hi @lazygopher. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The issue you're experiencing—where opening the NuxtUI UDropdownMenu causes the page to scroll to the top—can be related to Nuxt's scroll behavior and how navigation or focus is handled when opening overlays or menus. Based on the knowledge sources, here are some steps and considerations to address this: 1. Check scrollToTop Meta Option
If your navigation triggers a route change (even a shallow one), Nuxt may scroll to the top by default. You can prevent this by setting scrollToTop: false in your page's meta:
<script setup lang="ts">
definePageMeta({
scrollToTop: false,
})
</script>

<script setup lang="ts">
definePageMeta({
scrollToTop: false,
})
</script>

This ensures that opening the menu (if it triggers navigation) does not scroll the page to the top. This behavior is confirmed as fixed in recent Nuxt versions and is the recommended approach for preventing unwanted scroll jumps on navigation within the same page component [fix(nuxt): respect the scroll behavior set by scrollToTop]. 2. Check for Focus Management or Scroll Restoration
If the menu or button is programmatically focused, or if the browser's scroll restoration is interfering, you can explicitly set scroll restoration to 'auto' on the client:
onMounted(() => {
if (process.client && window) {
window.history.scrollRestoration = 'auto';
}
})

onMounted(() => {
if (process.client && window) {
window.history.scrollRestoration = 'auto';
}
})

This can help prevent abrupt scroll jumps on certain interactions [How to prevent the scroll from jumping to the top of the web page on Nuxt3 reload]. 3. Ensure the DropdownMenu is Not Causing Navigation
The UDropdownMenu component itself should not trigger navigation unless an item is clicked. If you have links in your menu, ensure they are not causing a full page reload or navigation unless intended. 4. UI Customization
The :ui prop you are using is correct for styling, but it does not affect scroll behavior. If you have custom logic that programmatically scrolls the page when opening the menu, review and remove it. Summary:
Set scrollToTop: false in your page meta to prevent Nuxt from scrolling to the top when opening the menu. Also, ensure that no navigation or focus logic is causing the scroll jump. If the issue persists, it may be related to a specific bug or interaction in your layout, but the above steps address the most common causes based on the available knowledge sources. If you need more targeted help, please provide details about any custom navigation or focus logic you have in your header or menu components. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
lazygopher
lazygopherOP5w ago
@kapa.ai it didn't help. Nuxt or the browser don't scroll up the page. Just the menu opens at position 0 (top of the page even if it's not visible). So the UX is as follows User scrolls down the page, menu stays on top of the visible screen User clicks the menu, just the menu header + dropdown shifts to the top of the page. It is invisible to the user until they scroll to the top.
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Thank you for clarifying the behavior. Based on your description, the issue is not with Nuxt's scroll behavior or browser scroll restoration, but rather with the positioning of the UDropdownMenu—it renders at the top of the page (position 0), regardless of where the button is on the screen. From the NuxtUI documentation, the UDropdownMenu uses a floating positioning system, and you can control its placement using the content prop. This prop allows you to specify options like side, sideOffset, align, and more, which determine where the dropdown appears relative to its trigger button. By default, it should position itself relative to the button, not the top of the page [DropdownMenu Props]. Possible causes and solutions: 1. Portal or Positioning Issue
If the dropdown is rendered in a portal (the default), but the reference element is not correctly detected, the menu might appear at the top of the page. You can try disabling the portal to see if it fixes the issue:
<UDropdownMenu
:items="menuItems"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

<UDropdownMenu
:items="menuItems"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

2. Reference Element Issue
If your header or navigation is using unusual CSS (e.g., transforms, overflow, or stacking contexts), the floating UI library might not be able to calculate the correct position. Make sure your header is not using CSS that interferes with positioning. 3. Custom Content Positioning
You can explicitly set the content prop to control the dropdown's alignment and offset. For example:
<UDropdownMenu
:items="menuItems"
:content="{ side: 'bottom', align: 'start', sideOffset: 8 }"
:ui="{ content: 'w-48' }"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

<UDropdownMenu
:items="menuItems"
:content="{ side: 'bottom', align: 'start', sideOffset: 8 }"
:ui="{ content: 'w-48' }"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

This should ensure the dropdown appears below the button [DropdownMenu Props]. 4. Sticky Header Compatibility
If your header is sticky, ensure that the dropdown is not being clipped or mispositioned due to parent overflow or stacking context issues. Summary:
- Try setting :portal="false" on UDropdownMenu. - Adjust the content prop for explicit positioning. - Check your header's CSS for anything that might interfere with floating positioning. If these steps do not resolve the issue, the knowledge sources do not provide further details on this specific bug. In that case, it may be a bug or limitation in the floating UI library used by NuxtUI, and you may want to open an issue on the NuxtUI GitHub repository with a minimal reproduction [DropdownMenu Props]. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
lazygopher
lazygopherOP5w ago
@kapa.ai My header is indeed sticky. Defined in a container
<div class="sticky top-0 z-10"> .. </div>
<div class="sticky top-0 z-10"> .. </div>
How do I make the dropdown compatible with it?
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- The NuxtUI documentation for UDropdownMenu does not explicitly mention special handling for sticky headers. However, it does provide detailed options for positioning the dropdown menu using the content prop, which controls how and where the dropdown appears relative to its trigger [DropdownMenu Props]. Key points from the docs: - By default, the dropdown uses a floating positioning system and renders in a portal (portal: true). - The content prop allows you to set position, side, sideOffset, align, and more. - If the dropdown is not positioned correctly (e.g., appears at the top of the page), it may be due to the portal rendering context or stacking context issues with sticky containers. What you can try: 1. Disable Portal Rendering
Set :portal="false" on your UDropdownMenu. This will render the dropdown in the same DOM context as the button, which often resolves issues with sticky or transformed parents:
<UDropdownMenu
:items="menuItems"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

<UDropdownMenu
:items="menuItems"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

This approach is suggested in the documentation for similar floating components, and is the most direct way to address issues with sticky headers [DropdownMenu Props]. 2. Adjust Content Positioning
You can further control the dropdown's position with the content prop:
<UDropdownMenu
:items="menuItems"
:content="{ side: 'bottom', align: 'start', sideOffset: 8, position: 'inline' }"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

<UDropdownMenu
:items="menuItems"
:content="{ side: 'bottom', align: 'start', sideOffset: 8, position: 'inline' }"
:ui="{ content: 'w-48' }"
:portal="false"
>
<UButton color="neutral" variant="outline" :trailing-icon="Icons.menu" aria-label="Open menu" />
</UDropdownMenu>

If these steps do not resolve the issue, the knowledge sources do not provide further guidance on making UDropdownMenu compatible with sticky headers. In that case, it may be necessary to consult the NuxtUI community or file an issue for more specific support. Summary:
Set :portal="false" on UDropdownMenu and adjust the content prop as needed to ensure compatibility with sticky headers, as per the documented API [DropdownMenu Props]. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
lazygopher
lazygopherOP5w ago
@kapa.ai I tried both ways without success. any other suggestions?
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I'm sorry, but the knowledge sources do not contain enough information to provide additional solutions for making UDropdownMenu fully compatible with a sticky header when :portal="false" and content positioning adjustments have not resolved the issue. The documentation covers the use of the portal and content props for positioning, but does not address further troubleshooting or advanced compatibility with sticky containers beyond these options DropdownMenu Props. If these documented approaches have not worked, the knowledge sources do not provide further guidance on this specific scenario. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
lazygopher
lazygopherOP5w ago
@kapa.ai maybe you can figure something from the element. When I click the dropdown menu, the portal opens in this html element
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Thank you for providing more context. However, the knowledge sources do not contain specific information about the internal structure or behavior of the portal element used by UDropdownMenu, nor do they describe troubleshooting steps for issues where the dropdown portal appears at the top of the page when used inside a sticky header. The documentation only confirms that you can control the portal behavior with the portal prop (set to true, false, a string, or an HTMLElement), and that the content prop allows for detailed positioning options. There is no further detail about how the portal attaches to the DOM or how it interacts with sticky containers or stacking contexts DropdownMenu Props. I'm sorry, but there's no information in the knowledge sources that would allow me to provide a more specific solution based on the portal's HTML element. If you need more advanced troubleshooting, you may need to consult the NuxtUI community or file an issue with a minimal reproduction. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
WiFi Plug
WiFi Plug5w ago
I haven't had that issue I use a dropdownmenu inside a navigation menu inside my navbar which is sticky to the top it remains sticky and the dropdown opens up normally preventing scrolling
lazygopher
lazygopherOP5w ago
I guess something wrong with my setup. Otherwise on the docs it wouldn't work either. I just can't pinpoint what it is
WiFi Plug
WiFi Plug5w ago
https://nuxt.new you can setup a fresh nuxt ui to test out a basic version
lazygopher
lazygopherOP5w ago
If I share a link to a demo version of the app, does that can help?
WiFi Plug
WiFi Plug5w ago
maybe ideally try to recreate a basic version of your navbar in that and see if you can recreate the issue or just remake your navbar piece by piece until you encounter the issue in your project
lazygopher
lazygopherOP5w ago
I'll try to create it with the starter kit I couldn't reproduce it on stackblitz. The main diff is that it bootstraps nuxt4 and I'm using nuxt3 but I don't think it's related
WiFi Plug
WiFi Plug5w ago
hmm, imo your best bet would be to simplify your navbar component with just the dropdown and see if that works remove any complexity and see if that has the issue still
lazygopher
lazygopherOP5w ago
thanks for the help, i'll try that tomorrow and see how it goes. I simplified the logic to this
// default.vue (layout)
<script setup lang="ts">
const desktopItems = [{ label: "Home", icon: "i-lucide-home", type: "link", to: "/" }]
</script>

<template>
<div class="min-h-screen flex flex-col bg-default container mx-auto">
<div class="sticky top-0 z-10 bg-default/95">
<UDropdownMenu
:items="desktopItems"
:ui="{
content: 'w-48',
}"
arrow
>
<UButton color="neutral" variant="outline" trailing-icon="i-lucide-menu" aria-label="Open menu" />
</UDropdownMenu>
</div>
</div>
</template>
// default.vue (layout)
<script setup lang="ts">
const desktopItems = [{ label: "Home", icon: "i-lucide-home", type: "link", to: "/" }]
</script>

<template>
<div class="min-h-screen flex flex-col bg-default container mx-auto">
<div class="sticky top-0 z-10 bg-default/95">
<UDropdownMenu
:items="desktopItems"
:ui="{
content: 'w-48',
}"
arrow
>
<UButton color="neutral" variant="outline" trailing-icon="i-lucide-menu" aria-label="Open menu" />
</UDropdownMenu>
</div>
</div>
</template>
However, it still happens. I upgraded nuxt to 3.18 and nuxtui to 3.3
lazygopher
lazygopherOP5w ago
lazygopher
lazygopherOP4w ago
@WiFi Plug I found what it is. When clicking the menu, something inject these styles to the body element:
<body style="padding-right: 14px; margin-right: 0px; --scrollbar-width: 14px; overflow: hidden; pointer-events: none;">
<body style="padding-right: 14px; margin-right: 0px; --scrollbar-width: 14px; overflow: hidden; pointer-events: none;">
If I disable the overflow: hidden problem solved.
WiFi Plug
WiFi Plug4w ago
oh that'll be because the dropdown is technically a modal so it disabled scrolling the main page (to hide the scrollbar etc) although i haven't had the issue you had my navbar stays sticky even with it open you can set the modal prop to false on the dropdownmenu maybe that would solve it as then it won't act like a modal
lazygopher
lazygopherOP4w ago
YAYYYY This solved the problem. omg how much time I had spend on this.
WiFi Plug
WiFi Plug4w ago
nice! still a weird issue and I feel like the root cause will be something else in your setup maybe higher up as i haven't had issues with something similar
lazygopher
lazygopherOP4w ago
I know. In the docs it behaves the same and it's working properly But I really have no idea what can cause this. I've added this to my css to prevent the shift when the modal opens but this aint the issue
body[style*="overflow: hidden"] {
padding-right: 0 !important;
margin-right: 0 !important;
}
body[style*="overflow: hidden"] {
padding-right: 0 !important;
margin-right: 0 !important;
}
Thanks for your help. I appreciate it!

Did you find this page helpful?