Skip to content

Commit 0c0beef

Browse files
committed
Scroll to top on nav, but not back/forward
Related to Issue #32
1 parent 2ce8d16 commit 0c0beef

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

layouts/default.vue

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export default Vue.extend({
1616
head(): Required<Pick<MetaInfo, 'htmlAttrs'|'link'|'meta'>> {
1717
return this.$nuxtI18nHead({ addSeoAttributes: true });
1818
},
19+
watch: {
20+
$route(): void {
21+
this.$scroll();
22+
},
23+
},
1924
mounted(): void {
2025
// Provide calls to this.$gtag here to update Analytics
2126
},

nuxt.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default {
3333
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
3434
'plugins': [
3535
{ src: '~/plugins/google-gtag.client.ts', mode: 'client' },
36+
{ src: '~/plugins/scroll.client.ts', mode: 'client' },
3637
],
3738

3839
// Auto import components: https://go.nuxtjs.dev/config-components

plugins/scroll.client.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Plugin } from '@nuxt/types';
2+
3+
declare module 'vue/types/vue' {
4+
interface Vue {
5+
$scroll(): void;
6+
}
7+
}
8+
9+
/**
10+
* How does this work? A good question. It may be buggy.
11+
*
12+
* When user navigation occurs, history is written to the browser to be used by
13+
* the back/forward buttons. This history maintains an immutable state for each
14+
* page. We are referencing one of the values of that state stack, the key. In
15+
* Chrome and Firefox, this /appears/ to be a monotonically increasing
16+
* string-encoded number. Possibly the number of milliseconds since the
17+
* page/website was first navigated to. More testing is required.
18+
*
19+
* We detect when the value on the page we're on is higher than the largest
20+
* value we've seen before. If it is, it's a new page, and we scroll. If it's
21+
* not, we rely on the user's browser settings to decide to scroll to their
22+
* previous position or not, depending on preferences.
23+
*
24+
* This function is called universally by watching to see when $route changes
25+
* in the layout for the pages. If it's broken, first confirm your page's
26+
* layout does call this.$scroll() inside of watch on $route.
27+
*/
28+
const scrollPlugin: Plugin = (_, inject) => {
29+
let historyKeyMax = 0;
30+
31+
inject('scroll', () => {
32+
const historyKey = +history.state.key;
33+
if (historyKeyMax < historyKey) {
34+
historyKeyMax = historyKey;
35+
window.scrollTo(0, 0);
36+
}
37+
});
38+
};
39+
40+
export default scrollPlugin;

0 commit comments

Comments
 (0)