Vuetify导航抽屉滚动至页脚时顶部隐藏问题求助
问题描述
滚动到页面底部显示页脚时,不希望v-navigation-drawer的顶部被隐藏。
滚动状态对比
- 滚动前状态:

- 滚动至底部状态:

相关代码
<template> <div id="app"> <v-app> <v-app-bar>header</v-app-bar> <div class="d-flex flex-0-1-100"> <v-navigation-drawer border="r" permanent fixed class="pa-1 position-sticky" style="max-height: calc(100vh - 64px)" > <div style="border: 2px solid pink; height: 100%"> nav bar <v-text-field v-model.number="contentHeight" min="0" step="400" type="number" label="content height (px)" /> </div> </v-navigation-drawer> <v-main class="bg-grey pl-0"> Main content <div :style="{height: contentHeight + 'px'}" class="bg-brown-darken-2" > content ({{contentHeight}}px) </div> </v-main> </div> <v-footer border="t">footer</v-footer> </v-app> </div> </template> <script setup> import { ref } from 'vue' const contentHeight = ref(1000) </script>
可通过Vuetify在线编辑器查看运行效果。
已尝试方案
移除v-navigation-drawer的position-sticky类后,滚动到页脚时导航顶部不再上移,但导航会横向超出页脚边界:
期望效果
实现类似索尼Pro Bravia指南网站的滚动布局:导航栏始终固定在顶部下方,滚动到页脚时不会被顶部隐藏,也不会超出页脚边界。
当前开发中的额外问题
使用以下v-navigation-drawer代码时,导航高度被减半:
<client-only> <v-navigation-drawer permanent class="position-sticky" :style="{ maxHeight, minWidth }" style=" height: fit-content; margin-top: 64px; " width="250" > <v-row justify="center"> <v-expansion-panels :modelValue="panel" :multiple="true"> <v-expansion-panel v-for="(item, i) in matchedNavObject.children" :key="i" > <v-expansion-panel-title>{{ item.title }}</v-expansion-panel-title> <v-expansion-panel-text v-for="(navItem, j) in item.children" :key="j" > <nuxt-link :to="`${baseUrl}${navItem._path}`" class="text-decoration-none" :class="{ active: `${navItem._path}/` === route.path, }" >{{ navItem.title }}</nuxt-link > </v-expansion-panel-text> </v-expansion-panel> </v-expansion-panels> </v-row> </v-navigation-drawer> </client-only>

解决方案
核心思路
让导航栏的粘性定位基于v-app内部的主容器,同时限制导航栏的最大高度为「视口高度 - 头部高度 - 页脚高度」,确保滚动到页脚时导航不会超出边界。
代码调整(针对第一个示例)
- 移除
v-navigation-drawer的fixed属性,调整position-sticky的定位参考 - 修正导航栏的高度计算,加入页脚高度
- 给导航内部内容添加滚动容器,避免内容溢出
修改后的代码:
<template> <div id="app"> <v-app> <v-app-bar>header</v-app-bar> <!-- 父容器设为relative,作为粘性导航的定位参考 --> <div class="d-flex flex-0-1-100" style="position: relative; min-height: calc(100vh - 64px)"> <v-navigation-drawer border="r" permanent class="pa-1" <!-- 最大高度=视口高度-头部高度-页脚高度(页脚高度需根据实际调整) --> style="max-height: calc(100vh - 64px - 48px); position: sticky; top: 64px;" > <div style="border: 2px solid pink; height: 100%; overflow-y: auto;"> nav bar <v-text-field v-model.number="contentHeight" min="0" step="400" type="number" label="content height (px)" /> </div> </v-navigation-drawer> <v-main class="bg-grey pl-0"> Main content <div :style="{height: contentHeight + 'px'}" class="bg-brown-darken-2" > content ({{contentHeight}}px) </div> </v-main> </div> <v-footer border="t" style="height: 48px;">footer</v-footer> </v-app> </div> </template> <script setup> import { ref } from 'vue' const contentHeight = ref(1000) </script>
针对开发中的导航高度问题调整
移除height: fit-content,改用max-height配合滚动容器,同时保证top和margin-top值一致:
<client-only> <v-navigation-drawer permanent class="position-sticky" :style="{ maxHeight: `calc(100vh - 64px - 48px)`, minWidth }" style=" top: 64px; margin-top: 64px; overflow-y: auto; " width="250" > <v-row justify="center"> <v-expansion-panels :modelValue="panel" :multiple="true"> <v-expansion-panel v-for="(item, i) in matchedNavObject.children" :key="i" > <v-expansion-panel-title>{{ item.title }}</v-expansion-panel-title> <v-expansion-panel-text v-for="(navItem, j) in item.children" :key="j" > <nuxt-link :to="`${baseUrl}${navItem._path}`" class="text-decoration-none" :class="{ active: `${navItem._path}/` === route.path, }" >{{ navItem.title }}</nuxt-link > </v-expansion-panel-text> </v-expansion-panel> </v-expansion-panels> </v-row> </v-navigation-drawer> </client-only>
关键说明
position: sticky的top值必须和margin-top一致,确保导航始终固定在头部下方- 计算
max-height时必须包含页脚高度,避免导航超出页脚边界 - 给导航内部内容添加
overflow-y: auto,当内容过长时可滚动,不会撑破容器
内容的提问来源于stack exchange,提问作者shinya
相关产品推荐
相关产品推荐

