Skip to Content


Animate the scroll to an element on the same page (automatically or manually).

JavaScript February 8, 2021


nebula.scrollTo(element, offset, speed, onlyWhenBelow, callback)


(Required) (Object) The jQuery object of the element to scroll to
Default: None

(Optional) (Integer) Pixel offset of the element
Default: None

(Optional) (Integer) How long the animated scroll should take in milliseconds
Default: 500

(Optional) (Boolean) Only scroll if the viewport is below the element (with offset)
Default: false

(Optional) (Function) A function to run after the scroll animation has completed
Default: None

Parameter Notes

offset is automatically subtracted from the element top, so positive numbers are above the element and negative numbers are below it.

Note: if a  scroll-padding-top CSS property is applied to the <body> element, it will be accounted for as well and added to the offset automatically.

Request or provide clarification »


Scroll to a specific element.


Scroll to 100px above an element only when the viewport is below that point (triggered on a Bootstrap carousel slide).

jQuery('#example-bootstrap-carousel').on('', function(){
    nebula.scrollTo(jQuery('#signup-form'), 500, 100, true);

Automatically scroll to an element.

<a href="#lower-element">Click here to scroll</a>

Automatically scroll with an offset

<a href="#lower-element" data-offset="200">Click here to scroll</a>

Alternate way to automatically scroll to an element.

<a class="nebula-scrollto" href="#" data-scrollto="#lower-element" data-offset="200">Click here to scroll</a>


Click here to scroll (via href)

Click here to scroll (via JS method)

Click here to scroll (via class/attribute)

Additional Notes

This function can be called specifically to scroll to an element, but it also runs automatically on any links where the href is an ID that starts with # (unless the class no-scroll is added to the element) or when the class nebula-scrollto is present.

After scrolling, the element will be “focused” on to maintain keyboard navigability. If you’re seeing borders on elements after scrolling, this is what is happening. You can modify your CSS to change this.

It is highly recommended to use scroll-padding-top in CSS to ensure the browser accounts for the fixed header on the page if used.

Was this page helpful? Yes No

    A feedback message is required to submit this form.

    Please check that you have entered a valid email address.

    Enter your email address if you would like a response.

    Thank you for your feedback!

    Source File

    Located in /assets/js/modules/helpers.js on line 283.

    No Hooks

    This function does not have any filters or actions available. Request one?
    nebula.scrollTo = function($element, offset = 0, speed = 500, onlyWhenBelow = false, callback){
        if ( !offset ){
            offset = nebula.scroll.offset || 0; //Note: This selector should be the height of the fixed header, or a hard-coded offset.
        //Account for the scroll-padding-top CSS property on the body element
        let scrollPaddingTop = parseInt(nebula.dom.body.css('scroll-padding-top'), 10); //Parse the CSS value as a base-10 integer
        if ( !isNaN(scrollPaddingTop) ){
            offset += scrollPaddingTop; //Add the scroll padding top to the offset
        //Call this function with a jQuery object to trigger scroll to an element (not just a selector string).
        if ( $element ){
            if ( typeof $element === 'string' ){
                $element = jQuery.find($element); //Use find here to prevent arbitrary JS execution
            } else if ( !$element.jquery ){ //Check if it is already a jQuery object
                $element = jQuery($element);
            if ( $element.length ){
                let willScroll = true;
                if ( onlyWhenBelow ){
                    let elementTop = $element.offset().top-offset;
                    let viewportTop = nebula.dom.document.scrollTop();
                    if ( viewportTop-elementTop <= 0 ){
                        willScroll = false;
                if ( willScroll ){
                    if ( !speed ){
                        speed = nebula.scroll.speed || 500;
                    jQuery('html, body').animate({
                        scrollTop: $element.offset().top-offset
                    }, speed, function(){
                        if ( callback ){
                            return callback();
            return false;


    To override or disable this JavaScript function, simply redeclare it with the exact same function name. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).


    For non-module import functions:

    nebula.scrollTo = function(element, offset, speed, onlyWhenBelow, callback){
        //Write your own code here, leave it blank, or return false.

    For dynamically imported module function overrides:

    jQuery(window).on('load', function(){
        nebula.scrollTo = function(element, offset, speed, onlyWhenBelow, callback){
            //Write your own code here, leave it blank, or return false.

    Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:

    jQuery(document).on('nebula_module_loaded', function(module){
        //Note that the module variable is also available to know which module specifically was imported
        if ( typeof nebula.scrollTo === 'function' ){
            nebula.scrollTo = function(element, offset, speed, onlyWhenBelow, callback){
                //Write your own code here, leave it blank, or return false.