You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) is a great API.
19
-
But it may not be the one-size-fits-all solution to highlight nav/sidebar links. Most likely because you want to:
13
+
But it may not be the one-size-fits-all solution to highlight TOC/sidebar links as it makes hard if not impossible to:
20
14
21
15
- Highlight any clicked link even if it will never intersect
22
16
- Always highlight first/last link once reached the top/bottom of the page
@@ -28,11 +22,9 @@ But it may not be the one-size-fits-all solution to highlight nav/sidebar links.
28
22
29
23
### Do you really need it?
30
24
31
-
If you don't care about the above gotchas, then no, please **don't use this package** because it adds a couple of KBs to your JS bundle that you don't need.
32
-
33
-
You can achieve a good result with the Intersection Observer API as well. The [Astro docs TOC](https://github.com/withastro/docs/blob/main/src/components/RightSidebar/TableOfContents.tsx) is a great example in just 30 lines of code.
25
+
If you and your users don't care about the above gotchas, then no, please **don't use this package** because it adds a couple of unnecessary KBs to your bundle.
34
26
35
-
Moreover, this package is meant for highlighting links in vertical sidebars and may be overkill for other use cases lik menu header links.
27
+
You can achieve an acceptable result with the Intersection Observer API as well. Alternatively, you can build an accurate scroll observer that acts similar to this package by looking at the [SvelteKit Website's TOC](https://github.com/sveltejs/site-kit/blob/master/packages/site-kit/src/lib/docs/DocsOnThisPage.svelte) source code in 100-150 lines of code.
36
28
37
29
<br />
38
30
@@ -56,13 +48,9 @@ Moreover, this package is meant for highlighting links in vertical sidebars and
56
48
57
49
<br />
58
50
59
-
## Requirements
51
+
## Getting Started
60
52
61
-
If scrolling to anchors, Vue Router (RouterLink / NuxtLink) is required.
62
-
63
-
<br />
64
-
65
-
## Installation
53
+
### Installation
66
54
67
55
```bash
68
56
pnpm add vue-use-active-scroll
@@ -72,6 +60,45 @@ pnpm add vue-use-active-scroll
72
60
# bun add vue-use-active-scroll
73
61
```
74
62
63
+
> [!WARNING]
64
+
> If you plan to use this package with scroll to anchors (e.g. docs TOC) and you're not using Nuxt, Vue Router is required and `scrollBehavior` must be configured in the router instance by following the next section.
65
+
66
+
### Configure `scrollBehavior`
67
+
68
+
> [!NOTE]
69
+
> If using **Nuxt**, you can skip to the [next section](#set-css-scroll-behavior) as it's already taken care for you by the framework.
70
+
71
+
As explained in the above warning, Vue Router needs to be configured in order to scroll to anchors.
72
+
73
+
```js
74
+
constrouter=createRouter({
75
+
// Add this method 👇
76
+
scrollBehavior(to) {
77
+
if (to.hash) {
78
+
return {
79
+
el:to.hash,
80
+
}
81
+
}
82
+
},
83
+
})
84
+
```
85
+
86
+
The above is the bare minimum required to get started and it will make sure that when clicking on a `RouterLink` that has an anchor in its `href` the window will scroll to that element.
87
+
88
+
> Later on, see the [Vue Router Section](#vue-router---additional-configurations) for additional configurations (container scroll, fixed header offsets, etc.).
89
+
90
+
### Set CSS `scroll-behavior`
91
+
92
+
Somewhere in your global CSS, add the following rule to enable smooth scrolling:
93
+
94
+
```css
95
+
html {
96
+
scroll-behavior: smooth; /* or 'auto' if you prefer instant scrolling */
97
+
}
98
+
```
99
+
100
+
> Later on, see the [Scroll Behavior Section](#configure-scrollbehavior) for additional scroll configurations or on how to use JS-based scrolling.
101
+
75
102
<br />
76
103
77
104
## Usage
@@ -90,10 +117,6 @@ The composable returns an object with properties to react to the active link and
> :warning: In case you setup Vue Router from scratch (e.g. Vite SPA), please make sure that you have configured [scroll behavior](#vue-router---scroll-to-and-from-hash) in your router instance.
94
-
>
95
-
> This is not required if using Nuxt as it's already configured by the framework.
| overlayHeight |`number`| 0 | Height in pixels of any **CSS fixed** content that overlaps the top of your scrolling area (e.g. fixed header). Must be paired with a CSS [scroll-margin-top](#setting-scroll-margin-top-for-fixed-headers) rule. |
276
306
| minWidth |`number`| 0 | Whether to toggle listeners and functionalities within a specific width. Useful if hiding the sidebar using `display: none`. |
| activeIndex |`Ref<number>`| Index of the active target in offset order, `0` for the first target and so on. |
287
317
288
-
<br />
289
-
290
-
## Defining scroll behavior
318
+
### Scroll behavior and types
291
319
292
-
You're free to choose between CSS (smooth or auto), [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) or even a library like [animated-scroll-to](https://github.com/Stanko/animated-scroll-to).
320
+
You're free to choose between CSS _scroll-behavior_(smooth or auto), [scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) or even a JS library like [animated-scroll-to](https://github.com/Stanko/animated-scroll-to).
@@ -342,15 +370,13 @@ function scrollTo(event, id) {
342
370
</template>
343
371
```
344
372
345
-
<br />
346
-
347
-
## Vue Router - Scroll to and from anchors
373
+
</details>
348
374
349
-
> :warning: If using Nuxt, Vue Router is already configured to scroll to and from anchors on page load or back/forward navigation. **So you don't need to do follow the steps below**. Otherwise rules must be defined manually.
375
+
### Vue Router - Additional Configurations
350
376
351
-
### Scrolling to anchors
377
+
####Scrolling to anchors inside a container
352
378
353
-
For content scrolled by the window, simply return the target element. To scroll to a target scrolled by a container, use _scrollIntoView_ method.
379
+
To scroll to a target inside of a container, use _scrollIntoView_ method and pass the target's ID.
354
380
355
381
```js
356
382
constrouter=createRouter({
@@ -376,7 +402,7 @@ const router = createRouter({
376
402
377
403
> :bulb: There's no need need to set overlayHeight if using `scrollIntoView` as the method is aware of target's `scroll-margin-top` property.
378
404
379
-
### Scrolling from anchor back to the top of the page
405
+
####Scrolling from anchors back to the page root
380
406
381
407
To navigate back to the top of the same page (e.g. clicking on browser's back button from hash to the page root), use the _scroll_ method for containers and return _top_ for content scrolled by the window.
You may noticed that when clicking on a link, a new entry is added to the history. When navigating back, the page will scroll to the previous target and so on.
406
432
407
-
If you don't like that, choose to replace instead of pushing the hash:
433
+
To disable this, choose to replace instead of pushing the hash:
408
434
409
435
```vue
410
436
<template>
@@ -420,11 +446,23 @@ If you don't like that, choose to replace instead of pushing the hash:
420
446
</template>
421
447
```
422
448
423
-
<br />
449
+
### Setting scroll-margin-top for fixed headers
424
450
425
-
## Server-side rendering
451
+
You might noticed that if you have a fixed header and defined an `overlayHeight`, once clicked to scroll, the target may be underneath the header. In this case, add `scroll-margin-top` to your targets:
426
452
427
-
Since `useActiveScroll` won't kick in until the page is hydrated, if you're using Nuxt, you might want to render the first link as active if on the server.
453
+
```js
454
+
useActiveScroll(targets, { overlayHeight:100 })
455
+
```
456
+
457
+
```css
458
+
.target {
459
+
scroll-margin-top: 100px;
460
+
}
461
+
```
462
+
463
+
### Server-side rendering
464
+
465
+
Since `useActiveScroll` won't kick in until the page is hydrated, you probably want to render the first link as active on the server.
You might noticed that if you have a fixed header and defined an `overlayHeight`, once clicked to scroll, the target may be underneath the header. You must add `scroll-margin-top` to your targets:
0 commit comments