diff --git a/src/components/Editor/TableOfContents.vue b/src/components/Editor/TableOfContents.vue
index 6d25d81bd80..178e56cca4c 100644
--- a/src/components/Editor/TableOfContents.vue
+++ b/src/components/Editor/TableOfContents.vue
@@ -14,7 +14,7 @@
[`editor--toc__item--${heading.level}`]: true,
[`editor--toc__item--previous-${heading.previous}`]: heading.previous > 0,
}">
-
+
{{ heading.text }}
@@ -45,10 +45,10 @@ export default {
},
methods: {
goto(heading) {
- document.getElementById(heading.id).scrollIntoView()
-
+ const element = this.$root.$el.querySelector(`#${heading.id}`)
+ element.scrollIntoView({ block: 'start', behavior: 'smooth' })
this.$nextTick(() => {
- window.location.hash = heading.id
+ window.history.replaceState(window.history.state, '', `#${heading.id}`)
})
},
},
@@ -96,6 +96,10 @@ export default {
color: var(--color-primary-element-hover);
}
+ &-link {
+ scroll-margin-top: calc(var(--default-clickable-area) + 4 * var(--default-grid-baseline));
+ }
+
&--1 {
--padding-left: 0rem;
font-weight: 600;
diff --git a/src/css/prosemirror.scss b/src/css/prosemirror.scss
index 75c2bcc959c..1c14f596c49 100644
--- a/src/css/prosemirror.scss
+++ b/src/css/prosemirror.scss
@@ -110,6 +110,9 @@ div.ProseMirror {
transition-duration: .15s;
transition-property: opacity;
transition-timing-function: cubic-bezier(.4,0,.2,1);
+ scroll-margin-top: calc(
+ var(--default-clickable-area) + 4 * var(--default-grid-baseline)
+ );
}
&:hover .heading-anchor {
diff --git a/src/plugins/headingAnchor.js b/src/plugins/headingAnchor.js
index e1925ad3a4d..33899f8153e 100644
--- a/src/plugins/headingAnchor.js
+++ b/src/plugins/headingAnchor.js
@@ -145,6 +145,7 @@ function anchorForHeading(heading) {
*/
function handleClick(event) {
event.stopPropagation()
- event.target.scrollIntoView()
- window.location.hash = event.target.getAttribute('href')
+ event.preventDefault()
+ event.target.scrollIntoView({ block: 'start', behavior: 'smooth' })
+ window.history.replaceState({}, '', event.target.getAttribute('href'))
}