diff --git a/examples/scroll-behavior/app.js b/examples/scroll-behavior/app.js
index 617ce6a4f..af555e8b5 100644
--- a/examples/scroll-behavior/app.js
+++ b/examples/scroll-behavior/app.js
@@ -10,7 +10,8 @@ const Bar = {
bar
-
Anchor
+
Anchor
+
Anchor2
`
}
@@ -29,6 +30,11 @@ const scrollBehavior = (to, from, savedPosition) => {
// scroll to anchor by returning the selector
if (to.hash) {
position.selector = to.hash
+
+ // specify offset of the element
+ if (to.hash === '#anchor2') {
+ position.offset = { y: 100 }
+ }
}
// check if any matched route config has meta that requires scrolling to top
if (to.matched.some(m => m.meta.scrollToTop)) {
@@ -64,6 +70,7 @@ new Vue({
/foo
/bar
/bar#anchor
+ /bar#anchor2
diff --git a/src/util/scroll.js b/src/util/scroll.js
index c7a6a7805..18b62ee18 100644
--- a/src/util/scroll.js
+++ b/src/util/scroll.js
@@ -45,7 +45,9 @@ export function handleScroll (
if (isObject && typeof shouldScroll.selector === 'string') {
const el = document.querySelector(shouldScroll.selector)
if (el) {
- position = getElementPosition(el)
+ let offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {}
+ offset = normalizeOffset(offset)
+ position = getElementPosition(el, offset)
} else if (isValidPosition(shouldScroll)) {
position = normalizePosition(shouldScroll)
}
@@ -76,13 +78,13 @@ function getScrollPosition (): ?Object {
}
}
-function getElementPosition (el: Element): Object {
+function getElementPosition (el: Element, offset: Object): Object {
const docEl: any = document.documentElement
const docRect = docEl.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
return {
- x: elRect.left - docRect.left,
- y: elRect.top - docRect.top
+ x: elRect.left - docRect.left - offset.x,
+ y: elRect.top - docRect.top - offset.y
}
}
@@ -97,6 +99,13 @@ function normalizePosition (obj: Object): Object {
}
}
+function normalizeOffset (obj: Object): Object {
+ return {
+ x: isNumber(obj.x) ? obj.x : 0,
+ y: isNumber(obj.y) ? obj.y : 0
+ }
+}
+
function isNumber (v: any): boolean {
return typeof v === 'number'
}
diff --git a/test/e2e/specs/scroll-behavior.js b/test/e2e/specs/scroll-behavior.js
index 4955ef146..7075f681b 100644
--- a/test/e2e/specs/scroll-behavior.js
+++ b/test/e2e/specs/scroll-behavior.js
@@ -3,7 +3,7 @@ module.exports = {
browser
.url('http://localhost:8080/scroll-behavior/')
.waitForElementVisible('#app', 1000)
- .assert.count('li a', 4)
+ .assert.count('li a', 5)
.assert.containsText('.view', 'home')
.execute(function () {
@@ -47,6 +47,11 @@ module.exports = {
.assert.evaluate(function () {
return document.getElementById('anchor').getBoundingClientRect().top < 1
}, null, 'scroll to anchor')
+
+ .click('li:nth-child(5) a')
+ .assert.evaluate(function () {
+ return document.getElementById('anchor2').getBoundingClientRect().top < 101
+ }, null, 'scroll to anchor with offset')
.end()
}
}