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')) }