9

let's say I have the follwing function:

window.smoothScroll = function(target) {
  var scrollContainer = target;
  scrollContainer.scrollIntoView(true);
}

How can I make the page scroll 20px above the element instead of scrolling to the element itself?

Thank you

itailitai
  • 429
  • 1
  • 4
  • 15

5 Answers5

12

Get the dimensional information for your element and then rather than scrolling it into view, tell the window to scroll to your element's top minus 20:

function scrollToJustAbove(element, margin=20) {
  let dims = element.getBoundingClientRect();
  window.scrollTo(window.scrollX, dims.top - margin);
}
Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
  • 3
    Thank you, this seems to work. but instead of the getBoundingClientRect() I used .offsetTop which seemed to work fine. – itailitai Sep 29 '18 at 16:50
  • 3
    It only _seems_ to work fine, but the offsetX/Y properties are _relative_ values, measured with respect to the parent's bounds. If your intention is reliable scroll, based on where the element _actually is_, then don't make that change, and stick with `getBoundingClientRect` =) – Mike 'Pomax' Kamermans Sep 29 '18 at 18:13
  • 1
    There's a more fully fleshed out answer/demo for this at https://stackoverflow.com/questions/49820013/javascript-scrollintoview-smooth-scroll-and-offset – tarskiandhutch Jul 02 '20 at 20:55
  • For anyone that will use this answer, keep in mind that it work only when using the window scrollbar and similar cases. If you use it in a content inside a popup/popper, for example, it won't work. – Lucas Basquerotto Dec 01 '22 at 20:32
  • doesn't work for me – Waleed Ahmad Mar 31 '23 at 06:29
0

If you are scrolling to a target from a non-fixed position on the page (say, from a sticky navigation bar) you have to take into account the current position that you're scrolling from. To do this, add window. scrollY to the y number in scrollTo (borrowing Mike's code):

function scrollToJustAbove(element, margin=20) {
   let dims = element.getBoundingClientRect();
   window.scrollTo(window.scrollX, dims.top - margin + window.scrollY);
}
JON
  • 965
  • 2
  • 10
  • 28
Kenny
  • 9
  • 2
0

You can also add a negative margin-top and the same amount of padding-top. For example:

.element {
  margin-top:-20px;
  padding-top:20px;
}

or even better

.element {
  scroll-margin-top: 45px;
}
Alireza
  • 5,444
  • 9
  • 38
  • 50
-1

Well, for smooth scroll you can use jQuery animate(). Check the code below:

window.smoothScroll = function(target, above, speed) {
  let $scrollContainer = $target;
  jQuery('html, body').animate({
    scrollTop: jQuery(scrollContainer).offset().top - above
  }, speed);
}

[Note: above will be your 20 (as you wanted 20px above the target), speed will be any number say: 900 like that.]

If it helps...!

rony2k6
  • 75
  • 5
-3

Please change variables definations. $scrollContainer and target vars are not same, you can use at below

window.smoothScroll = function(target, above, speed) {
    let scrollContainer = target;
    $('html, body').animate({
        scrollTop: jQuery(scrollContainer).offset().top - above
    }, speed);}