admin管理员组

文章数量:1289483

When I click on a list item with an "href" or "to" link to an anchor tag, I would expect the navigation to take the app-bar's height into account so that the very top of the section is shown, below the app bar. But instead, the top of the section is hidden by the app bar. It looks like the Vuetify docs handles this issue (example link), and I am trying to understand how it does it.

Simple example of it not working for me: Vuetify Play link

FYI, I also posted this as the Vuetify Q&A Discussion a few days ago, but haven't seen any responses there: Question in Vuetify Q&A

Thanks for the help!

When I click on a list item with an "href" or "to" link to an anchor tag, I would expect the navigation to take the app-bar's height into account so that the very top of the section is shown, below the app bar. But instead, the top of the section is hidden by the app bar. It looks like the Vuetify docs handles this issue (example link), and I am trying to understand how it does it.

Simple example of it not working for me: Vuetify Play link

FYI, I also posted this as the Vuetify Q&A Discussion a few days ago, but haven't seen any responses there: Question in Vuetify Q&A

Thanks for the help!

Share Improve this question asked Feb 20 at 17:48 KeithKeith 3394 silver badges9 bronze badges 1
  • These aren't just anchor links in the example. You can open it in new tab and see it doesn't compensate top bar height. It uses a router with hash strategy, which you can use too, sidebar links are router links. Vue router has scrollBehavior to calculate scroll position – Estus Flask Commented Feb 20 at 19:05
Add a comment  | 

1 Answer 1

Reset to default 1

Thanks to @EstusFlask for pointing out that opening up the links from Vuetify docs in a brand new window/tab does not appropriately compensate for the app bar's height. This led me to the following scroll behavior setup (Note: I'm actually making a Nuxt app, so I added the following code at app/router.options.ts):

import type { RouterConfig } from "@nuxt/schema";

export default <RouterConfig>{
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
    return savedPosition
  }
  else if (to.hash && from.name != null) {
    return {
      el: to.hash,
      top: 64,
    }
  }
  else {
    return null
  }
};

If from.name == null, we are in a brand new window. In that case, Nuxt will not be able to find the element designated by the hash - it hasn't rendered yet. So I created a separate plugin to handle this case:

// plugins/anchors.ts

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('app:mounted', () => {
    const { hash } = nuxtApp._route
    if (hash) {
      const el = document.querySelector(hash)
      if (el) {
        const rect = el.getClientRects()
        if (rect.length > 0) {
          const [{ top }] = rect
          if (top) {
            window.scrollTo({
              top: top - 64,
            })
          }
        }
      }
    }
  })
})

The one problem this solution does not solve is the fact that I'm also trying to use v-intersect to highlight a list item in the nav bar, and v-intersect assumes that a section is visible even if it is covered by the app bar. ETA: I was able to fix the v-intersection issue by including a rootMargin option:

const { mainRect } = useLayout()
// use (negative) app bar height, with 2 px for margins/padding
const rootMargin = computed(() => `-${mainRect.value.top + 2}px`)

function getIntersectOptions(index: number) {
  return {
    handler: (isIntersecting: boolean) => onIntersect(index, isIntersecting),
    options: {
      rootMargin: rootMargin.value,
    }
  }
}

The index parameter allows me to use the same code for multiple list items, e.g.:

<div v-intersect="getIntersectOptions(0)">
  <FirstSection />
</div>
<div v-intersect="getIntersectOptions(1)">
  <SecondSection />
</div>
<div v-intersect="getIntersectOptions(2)">
  <ThirdSection />
</div>
<div v-intersect="getIntersectOptions(3)">
  <FourthSection />
</div>

本文标签: vuejsVuetifyhow do anchor links take the app bar into accountStack Overflow