elementor / elementor

The most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.
https://elementor.com/
GNU General Public License v3.0
6.59k stars 1.42k forks source link

scroll-margin-top not working in elementor #13177

Open Micu22 opened 3 years ago

Micu22 commented 3 years ago

Description

scroll-margin-top css property not working on pages/posts made with elementor (some shenanigan js probably intrudes) On sites where I have a sticky header I would like the anchor scrolling to stop before the target element hides underneath the header. I guessed it's a js intrusion, because scrolling to anchor links fells less stappy than on no-elementor pages. Then I went through the functions called in DevTools/Sources although I am a backend dev, not frontend I think it's something attached to jQuery that is causing the problem.

Steps to reproduce

  1. Add to custom css this:
    [id] {
    scroll-margin-top: 80px; /*80px is the height of the header + some whitespace*/
    }
  2. Test anchor links

Isolating the problem

Environment

https://pastebin.com/TAnNKb8M

mattfoolery commented 3 years ago

This issue is being caused by frontend.min.js which is located in plugins/elementor/assets/js. This is a smooth scroll issue and unfortunately there is no ability to turn it off within WP/Elementor options.

For a quick fix see https://wordpress.org/support/topic/scroll-effects-conflicts-with-elementor-scrolling/

Micu22 commented 3 years ago

Thank you Matt, the second code under the link you provided worked for me. LINK But this is a temporary solution. I also can't imagine using elementor without control of scroll with a sticky header. If things get hidden under the header it's bad UX. I see two solutions for Elementor Team:

  1. Add an option to the smooth scrolling script in elementor that would allow us to set "a top offset of scroll to anchor". or
  2. Let us disable the elementor smooth scrolling.

Could someone from the team update us here on when we can see a solution?

neurohost commented 3 years ago

Still no solution for this?

scroll-margin-top still not working

danceb commented 3 years ago

I have found this right in the help of the elementor website: https://elementor.com/help/menu-anchor-widget/ (section "Adjust Sticky Header Offset for Anchor Links").

This worked for me.

WebAtelier47 commented 2 years ago

I think the dev teams don't really care about this kind of little problem, it's really a shame...

danceb commented 2 years ago

The section "Adjust Sticky Header Offset for Anchor Links" could not be found at the mentioned website anymore, so maybe this works now? (have not tested it). @WebAtelier47 don't blame the elementor dev team in this way! They do a really really god job. Don't forget, what you get from them without paying anything...

SamIvory1 commented 2 years ago

I'm seeing this problem on v3.6.6.

danceb commented 2 years ago

So this is the solution, which was mentioned on the elementor help page. Add this to your custom css. You have to play with the height and margin values regarding to your header height.

/* top spacing above anchor links*/
body:not(.elementor-editor-active) .elementor-menu-anchor:before {
  content: "";
  display:block;
  height: 150px; 
    /* fixed header height*/
  margin: -150px 0 0; 
    /* negative fixed header height */
  visibility: hidden;
  pointer-events: none;
}

/* sticky header */
#top-bar-wrap {
        position: fixed !important;
        top: 0px !important;
        width:100% !important;
}
#site-header {
        position: fixed;
        top: 40px;
    }
#main {
        margin-top: 120px;
    }
WebAtelier47 commented 2 years ago

Yes but you need to use anchor element for that and add an element only for an anchor...

misticx commented 2 years ago

Such a shame that this problem still persist :/

bouveng commented 1 year ago
/* scroll offset to account header */
.elementor-menu-anchor {
    scroll-margin-top: 148px;
}

Works fine when linking to anchors on different pages.

Br.

/J

didierCH commented 1 year ago

It does not work on same site (scrolling down). This is caused because the url-fragment is not updated as described in this issue #9162

didierCH commented 1 year ago

We looked further into this issue, and it seems that some Elementor-Scripts are intercepting anchor links set with Elementor widgets. Because of this finding, we were able to come up with a simple solution: put the anchor links as pure HTML in an HTML-widget. That way, Elementor scripts won't catch the link and the URL-fragment will not be removed and scroll-margin-top also works. The only drawback of this method is that it makes the website harder to change for inexperienced users.

rwattner commented 11 months ago

So "put the anchor links as pure html" would be an html widget with something like this? <span id="anchor"></span>

I've been using the anchor widget set to position:absolute so the offset can be adjusted individually and responsively. It's a little tedious but works well. I'd like to see if scroll-margin-top is easier.

didierCH commented 11 months ago

So "put the anchor links as pure html" would be an html widget with something like this? <span id="anchor"></span>

Exactly that.

Bamstian commented 11 months ago

Wow Elementor needed three years for that! (And it´s just a workaround, not a real fix) We´re switching all clients and own pages to Bricks starting next year! No $ for the very very slow dev team of Elementor.

Shame on you Elementor!

Bamstian commented 11 months ago
Bildschirmfoto 2023-12-06 um 13 22 25 Bildschirmfoto 2023-12-06 um 13 22 55
erickarbe commented 11 months ago

If you place this snippet in the Custom Code (body end section) it will fix it. Just change the number (110 in my example) to what you need. Only caveat is that it's global. But I suppose you could just run this code on the pages you need or change it on a per page basis if you need different values.

<script>
window.addEventListener('elementor/frontend/init', function() {
  elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
    return scrollTop - 110;
  })
})
</script>
Kretsul-Vitaliy commented 10 months ago

Thanks for the given hook, it worked for me too, I modified the code and only used the hook and added the condition and it only works on my container and on my phone and tablet.

var hookCalled = false; if ( target.classList.contains('elementor-toc__list-item-text') && target.classList.contains('elementor-item-active') && !hookCalled ) { var viewportWidth = window.innerWidth; var fixedContainerElementHeight = element.querySelector( '.elementor-widget-container' ); var fixedElementHeight = fixedContainerElementHeight.offsetHeight

      if (viewportWidth >= 320 && viewportWidth <= 1024) {

        elementorFrontend.hooks.addFilter(
          'frontend/handlers/menu_anchor/scroll_top_distance',

          function (scrollTop) {
                hookCalled = true;
                return scrollTop - fixedElementHeight; 
          }

        );
      }
    }
daniel-akinyemi commented 10 months ago

If there is spacing between the anchor target elements on your site you can also swap margin-top for padding-top (make sure padding top is the same size as the fixed header or more). This will fix it.

tomas-eklund commented 10 months ago

Wow. I've wastes hours and hours trying to get scroll-margin-top and scroll-padding-top to work. If Elementor really breaks the browser standard behavior like this, at least they should add an option to specify a scroll padding in the site options, and document the behavior.

chestnutsoftech commented 8 months ago

If you place this snippet in the Custom Code (body end section) it will fix it. Just change the number (110 in my example) to what you need. Only caveat is that it's global. But I suppose you could just run this code on the pages you need or change it on a per page basis if you need different values.

<script>
window.addEventListener('elementor/frontend/init', function() {
  elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
    return scrollTop - 110;
  })
})
</script>

this worked, thanks!

rwattner commented 8 months ago

Here is a responsive version with variables to make it even easier. I stuck with the default three breakpoints but it's easily expandable if needed.

Custom Code: body - end

 <script>
    window.addEventListener('elementor/frontend/init', function() {
        elementorFrontend.hooks.addFilter('frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
            // Get viewport width
            var viewportWidth = window.innerWidth;

            // Define scroll top distances for different viewport widths
            var desktop = 120; // Scroll top distance for desktop (viewport width >= 1025px)
            var tablet = 100; // Scroll top distance for tablet (viewport width between 768px and 1024px)
            var mobile = 80; // Scroll top distance for mobile (viewport width below 768px)

            // Define scroll top distance based on viewport width
            if (viewportWidth >= 1025) {
                // Desktop
                return scrollTop - desktop;
            } else if (viewportWidth >= 768 && viewportWidth <= 1024) {
                // Tablet
                return scrollTop - tablet;
            } else {
                // Mobile
                return scrollTop - mobile;
            }
        });
    });
</script>
saifurpro commented 7 months ago

scroll-margin-top still not working

saifurpro commented 7 months ago

If you place this snippet in the Custom Code (body end section) it will fix it. Just change the number (110 in my example) to what you need. Only caveat is that it's global. But I suppose you could just run this code on the pages you need or change it on a per page basis if you need different values.

<script>
window.addEventListener('elementor/frontend/init', function() {
  elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
    return scrollTop - 110;
  })
})
</script>

this is also not working on my here.

BennySchwancke commented 7 months ago

The code works fine, if im already on the page where the anchor link is on. But if im on another page and then click on the menu anchor, it ignores this code. Do you know why this is?

tomas-eklund commented 7 months ago

The code works fine, if im already on the page where the anchor link is on. But if im on another page and then click on the menu anchor, it ignores this code. Do you know why this is?

This was my experience as well. I just gave up and added an actual margin on top of all the anchors.

EugeneTheSage commented 6 months ago

Here is a responsive version with variables to make it even easier. I stuck with the default three breakpoints but it's easily expandable if needed.

Custom Code: body - end

 <script>
    window.addEventListener('elementor/frontend/init', function() {
        elementorFrontend.hooks.addFilter('frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
            // Get viewport width
            var viewportWidth = window.innerWidth;

            // Define scroll top distances for different viewport widths
            var desktop = 120; // Scroll top distance for desktop (viewport width >= 1025px)
            var tablet = 100; // Scroll top distance for tablet (viewport width between 768px and 1024px)
            var mobile = 80; // Scroll top distance for mobile (viewport width below 768px)

            // Define scroll top distance based on viewport width
            if (viewportWidth >= 1025) {
                // Desktop
                return scrollTop - desktop;
            } else if (viewportWidth >= 768 && viewportWidth <= 1024) {
                // Tablet
                return scrollTop - tablet;
            } else {
                // Mobile
                return scrollTop - mobile;
            }
        });
    });
</script>

I want the margin be set not by pixels but by vh. How do I do that? I'm not experienced with javascript

Craigeniah commented 4 months ago

I wanted to add my two cents here as well with a use case for why this is an issue. I am using Elementor's Table of Contents Widget and because we have a sticky nav when I click one of the headings in my table of contents it scrolls into view and is now covered by the navigation menu so that the heading cannot be seen.

Ideally I would be able to add custom css for scroll-margin-top so that when scrolled into view it would not over lap this heading.

Like: .elementor-menu-anchor { scroll-margin-top: 150px; scroll-snap-margin-top: 150px; /* iOS 11 and older */ }

This is a situation where the content of each of the anchors is generated by elementor, so I don't have access to each of the individual headings when they are being added newly for each new post by a content editor.

Hope this generates more of a feature request / user story for this issue to be resolved.

Mouhamadou-Soumare commented 3 months ago

I'd like to share my solution that worked for me when using Prestashop with Elementor.

Problem: The CSS property scroll-margin-top does not work on pages created with Elementor due to interference from a JavaScript script.

Solution: To work around this problem, here’s a one-step solution.

Add Custom JS:

document.addEventListener('DOMContentLoaded', function() {
    // Disable default click events on anchor links handled by Elementor
    jQuery(document).off('click', 'a[href*="#"]');

    // Add a new click event handler for anchor links
    jQuery('a[href*="#"]').on('click', function(e) {
        e.preventDefault();
        var targetId = jQuery(this).attr('href').split('#')[1];
        var targetElement = document.getElementById(targetId);

        if (targetElement) {
            var topOffset = 80; // Adjust this based on the height of your sticky header
            var elementPosition = targetElement.getBoundingClientRect().top;
            var offsetPosition = elementPosition + window.pageYOffset - topOffset;

            window.scrollTo({
                top: offsetPosition,
                behavior: 'smooth'
            });
        }
    });
});
cabmaxi commented 2 months ago

If you place this snippet in the Custom Code (body end section) it will fix it. Just change the number (110 in my example) to what you need. Only caveat is that it's global. But I suppose you could just run this code on the pages you need or change it on a per page basis if you need different values.

<script>
window.addEventListener('elementor/frontend/init', function() {
  elementorFrontend.hooks.addFilter( 'frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
    return scrollTop - 110;
  })
})
</script>

After spending 3 days looking for a solution, it works! Thanks man!

cabmaxi commented 2 months ago

Here is a responsive version with variables to make it even easier. I stuck with the default three breakpoints but it's easily expandable if needed.

Custom Code: body - end

 <script>
    window.addEventListener('elementor/frontend/init', function() {
        elementorFrontend.hooks.addFilter('frontend/handlers/menu_anchor/scroll_top_distance', function(scrollTop) {
            // Get viewport width
            var viewportWidth = window.innerWidth;

            // Define scroll top distances for different viewport widths
            var desktop = 120; // Scroll top distance for desktop (viewport width >= 1025px)
            var tablet = 100; // Scroll top distance for tablet (viewport width between 768px and 1024px)
            var mobile = 80; // Scroll top distance for mobile (viewport width below 768px)

            // Define scroll top distance based on viewport width
            if (viewportWidth >= 1025) {
                // Desktop
                return scrollTop - desktop;
            } else if (viewportWidth >= 768 && viewportWidth <= 1024) {
                // Tablet
                return scrollTop - tablet;
            } else {
                // Mobile
                return scrollTop - mobile;
            }
        });
    });
</script>

F*cking genius!!!! I needed this code <3 thank you too dude

TIIUNDER commented 1 week ago

Looks like the hook "frontend/handlers/menu_anchor/scroll_top_distance" is not working anymore since the last update. Can somebody confirm this?

Kacpeerrr commented 4 days ago

@TIIUNDER From version 3.25, elementor used a different solution. You can set an anchor offset on the sticky element. Anchor offset