locomotivemtl / locomotive-scroll

🛤 Detection of elements in viewport & smooth scrolling with parallax.
https://locomotivemtl.github.io/locomotive-scroll
MIT License
7.8k stars 1.12k forks source link

anchor link does not work with scroll locomotive #175

Open GeorgeStudio96 opened 3 years ago

GeorgeStudio96 commented 3 years ago

Hi, everybody, can you please tell me how I can create an anchor link in Header to a certain block that has an ID that is in the data-scroll-container ? I've tried to put my menu FOR the limits of the data-scroll-container, I've tried to put it into this shell and none of the options have helped me :( I'd appreciate it if you could help me write a few lines of code to make it work. Thank you . I have tried for a long time to consider this example, but I cannot understand how it all works. They are fine, when you click on 02.Scroll-direction and the page flips smoothly to the desired block. Help me understand what to do https://locomotivemtl.github.io/locomotive-scroll/

If necessary, I can recreate the example on codepen, but please see my example first to understand what I'm talking about. https://george-studio.webflow.io/ If you click on Home you will be redirected to the right place, but everything breaks down. The script breaks, you can't go back, when you refresh a page, I am immediately redirected to this link. I'm sure I'm doing something wrong, help me understand what it is.

shohinav commented 3 years ago

Any luck finding the fix?

GeorgeStudio96 commented 3 years ago

Any luck finding the fix?

No..:(

shohinav commented 3 years ago

I found a solution for this. You will need to use JS for this and remove the link from the anchor tag just leaving it empty with # only. So something like this:

const slider= document.querySelector('#slider-container');

$('.w-nav-link:first-child').on('click', function() {
    scroll.scrollTo(slider)
});

Not sure if it's the right way, but as long as it works. Hopefully this helps

GeorgeStudio96 commented 3 years ago

I may be doing something wrong but there is no result... I used your code. Where "#slider-container is the block ID" to which should be scrolled. and ".home" is the class of the first link I click on.

ronca85 commented 3 years ago

for now you can try moving the "w-container" outside of the data-scroll-container so it isn't affected by scrolling.

GeorgeStudio96 commented 3 years ago

for now you can try moving the "w-container" outside of the data-scroll-container so it isn't affected by scrolling.

No, this option does not work. You can see that I left just a normal link on the site outside the data-scroll container. and nowhere is there a codepen with a locomotive + anchor link? this is such a big problem... although the task is supposedly simple

GeorgeStudio96 commented 3 years ago

can you show me a demonstration on codepen?

ronca85 commented 3 years ago

@GeorgeStudio96 put href="#slider-container" on one of your anchors. currently it says href="#"

GeorgeStudio96 commented 3 years ago

@ GeorgeStudio96 поместил href = "# slider-container" в одну из ваших якорей. в настоящее время он говорит: href = "#"

https://codepen.io/GeorgeDesign2020/pen/bGeWNOE I created a demonstration where you can see 2 methods yours and @shohinav. I put a #black in link 2 and if you click it will scroll to the desired section, but scrolling the locomotive stops working correctly, look at the demonstration. option @shohinav, for link 3 I left # empty and finished the jquery script, it is written at the very end of JS. In this example there is 0 reaction at all when you click on link 3. What to do? why is it so difficult when it's elementary things? why didn't the locomotive scroll take care to recreate a piece of code for these basic and elementary things? I have a long website and I want the user to quickly switch to the sections he needs.

GeorgeStudio96 commented 3 years ago

another thing, I have an extra gsap code there which I did not recreate in this example, but my site uses a lot of GSAP animation + three js.

shohinav commented 3 years ago

@GeorgeStudio96 I found the issue for link 3(the solution I suggested you), in the JS file your declared the Locomotive Scroll as locoScroll, but for the scrollTo you put scroll instead of putting locoScroll, so it should be as:

const slider= document.querySelector('#about');

$('.anchor__link:nth-child(3)').on('click', function() {
    locoScroll.scrollTo(slider)
});

this worked for me

GeorgeStudio96 commented 3 years ago

@GeorgeStudio96 I found the issue for link 3(the solution I suggested you), in the JS file your declared the Locomotive Scroll as locoScroll, but for the scrollTo you put scroll instead of putting locoScroll, so it should be as:

const slider= document.querySelector('#about');

$('.anchor__link:nth-child(3)').on('click', function() {
    locoScroll.scrollTo(slider)
});

this worked for me

YES! thank you so much, now it works. Yes, it turns out to be my mistake, I did not understand what I was talking about. Now everything works as it should! Now I have the same question as you. is it the right way to do it?)) how can we know if it's the right way to do it? because we are plugging jquery in.

aaamenezes commented 3 years ago

Hello.

I would like contribute with this case.

I did my anchor link works just using the attribute data-scroll-to, like this:

<a href="#end" class="go-to-end" data-scroll-to><i class="fas fa-chevron-down"></i></a>

I got it of the inspect tool of page that @GeorgeStudio96 post here (https://locomotivemtl.github.io/locomotive-scroll/)

GeorgeStudio96 commented 3 years ago

Hello.

I would like contribute with this case.

I did my anchor link works just using the attribute data-scroll-to, like this:

<a href="#end" class="go-to-end" data-scroll-to><i class="fas fa-chevron-down"></i></a>

I got it of the inspect tool of page that @GeorgeStudio96 post here (https://locomotivemtl.github.io/locomotive-scroll/)

What? I don't understand where your link goes. You created data-scroll-to, gave a class to your tag, then logically you have to put an attribute to the element we want to get to, right? for example to the section with the attribute or something. What is it ? oO

aaamenezes commented 3 years ago

In really, you just need put a attribute in the anchor link where the user clicks, and not in the target element.

The anchor link in my example points to element with <div id="end"> ... </div>.

The only diference between anchor link using LocomotiveScroll or not, is that with Locomotive you need put the attribute data-scroll-to inside your anchor link. That's it.

GeorgeStudio96 commented 3 years ago

In really, you just need put a attribute in the anchor link where the user clicks, and not in the target element.

The anchor link in my example points to element with <div id="end"> ... </div>.

The only diference between anchor link using LocomotiveScroll or not, is that with Locomotive you need put the attribute data-scroll-to inside your anchor link. That's it.

I tested your, method, it works, but after I move to my section, I can no longer scroll to the top. There is probably some conflict between the Webflow and locomotive scroll scripts. Too bad...

aaamenezes commented 3 years ago

It is certainly a conflict with LocomotiveScroll. Here at my company, none of us like to use this library, and we use it only because the customer asked.

The behavior you described to me is as if the data-scroll-to attribute has not yet been set. That's how the anchor link used to behave before for me.

In my case, just put this attribute and scrolling is no longer a problem, even if it runs smoothly.

I apologize for any problems with my text. I'm Brazilian and I'm writing with the help of Google Translate.

DoubleMarv commented 3 years ago

Hello friends. I was grappling with this, the solution for me was

<a href="#section6" data-scroll-to>Go to section 6</a>

but this will only work inside this container

<div data-scroll-container>

If this data-scroll-to attribute is outside this link, it explodes. JS solution also did not work for me unfortunately. Was surprised to not see this "data-scroll-to" on the locomotive js docs. Unless I missed it....

jankohlbach commented 3 years ago

this feels a little weird, if I add data-scroll-to, it works on desktop, but not on my smartphone (guess because there's still the e.preventDefault when you click on the anchor, but the smooth scrolling is not enabled), also, if I add the anchor in the url (like localhost:1234#contact) it's scrolling there, but then I cannot scroll up again :(

edit: solution for me was to use href="#id" and data-scroll-to for desktop and a custom js function for mobile, where if the html doesn't have the active smooth class I add scrollIntoView when clicking the anchor links

mykt0ngc0 commented 2 years ago

Here's a little script for you guys.

    /* Locomotive Anchor Scroll */

    const anchorLinks = document.querySelectorAll('a[href^=\\#]:not([href$=\\#])');

    anchorLinks.forEach((anchorLink) => {
        let hashval = anchorLink.getAttribute('href');
        let target = document.querySelector(hashval);

        anchorLink.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            scrollLocomotive.scrollTo(target);
        });
    });

It triggers on all anchor links that have actual target ("/#div_id") and ignore the empty ones ("/#").

mhasan320 commented 2 years ago

Set Active Class into anchor Link.

const anchorLinks = document.querySelectorAll(
    'a[href^=\\#]:not([href$=\\#])'
  );

  anchorLinks.forEach((anchorLink) => {
    let hashval = anchorLink.getAttribute('href');
    let target = document.querySelector(hashval);

    anchorLink.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();

      anchorLinks.forEach((anchorLink) => {
        anchorLink.classList.remove('active');
      });

      e.target.classList.add('active');

      scroll.scrollTo(target);
    });
  });
luxjoshyua commented 1 year ago

I spent ages trying to get this working but eventually reached a solution with the code from @mykt0ngc0 above.

For my html, I needed the fixed-nav outside of the data-scroll container, and needed the data-scroll-to attribute on each of the a tags:

<nav class="fixed-nav">
    <ul>
      <li><a href="#location1"
           class="location location--1"
           data-scroll-to>location one</a></li>
      <li><a href="#location2"
           class="location location--2"
           data-scroll-to>location2</a></li>
      <li><a href="#location3"
           class="location location--3"
           data-scroll-to>
          location3</a></li>
      <li><a href="#location4"
           class="location location--4"
           data-scroll-to>location4</a></li>
      <li><a href="#location5"
           class="location location--5"
           data-scroll-to>location5</a></li>
    </ul>
  </nav>

My js for the nav then looked like this:

const anchorLinks = document.querySelectorAll('.fixed-nav .location');

anchorLinks.forEach((anchorLink) => {
  let hashval = anchorLink.getAttribute('href');
  let target = document.querySelector(hashval);

  anchorLink.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();

    locomotiveScroll.scrollTo(target);
  });
});

This combo seems to work.

Additionally, after the DOM first paints, I was getting another bug with locomotive, so I found this piece of code and slightly reworked it to resolve it, so my full locomotive file looks like this:

import LocomotiveScroll from 'locomotive-scroll';

const locomotiveScroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true,
  getSpeed: true,
  getDirection: true,
  inertia: 0.75,
});

document.addEventListener('DOMContentLoaded', function () {
  function ScrollUpdateDelay() {
    setTimeout(function () {
      locomotiveScroll.update();
    }, 1000);
  }

  ScrollUpdateDelay();
});

const anchorLinks = document.querySelectorAll('.fixed-nav .location');

anchorLinks.forEach((anchorLink) => {
  let hashval = anchorLink.getAttribute('href');
  let target = document.querySelector(hashval);

  anchorLink.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();

    locomotiveScroll.scrollTo(target);
  });
});
artshostak commented 1 year ago

This is beautiful and exactly what I needed, thank you @mykt0ngc0 @mhasan320 and @luxjoshyua!

To reiterate the [data-scroll-to] works perfectly fine inside a [data-scroll-container] but all other instances should reference the code and DOM structure above.

Any ideas how to introduce a little offset for the scrollTo function? Edit, actually appears to be as easy as passing the following offset into that scrollTo function: locomotiveScroll.scrollTo(target, , {offset: -100})

r4sk4t0v commented 1 year ago

Here is the solution if you want to use Locomotive Scroll with Gsap Scroll trigger and also anchor links to work correct.

Be sure you use data-scroll, data-scroll-section and data-scroll-to in your Html.

HTML

Hey

👋

What's up?

😬

JAVASCRIPT

const locoScroll = new LocomotiveScroll({ el: document.querySelector('[data-scroll-container]'), smooth: true, });

/ Add this script if you want to Loco Scroll to work with Gsap scrollTrigger /

locoScroll.on("scroll", ScrollTrigger.update);

ScrollTrigger.scrollerProxy("[data-scroll-container]", { scrollTop(value) { return arguments.length ? locoScroll.scrollTo(value, {duration: 0, disableLerp: true}) : locoScroll.scroll.instance.scroll.y; }, getBoundingClientRect() { return {top: 0, left: 0, width: window.innerWidth, height: window.innerHeight}; }, pinType: document.querySelector("[data-scroll-container]").style.transform ? "transform" : "fixed" }); ScrollTrigger.addEventListener("refresh", () => locoScroll.update()); ScrollTrigger.defaults({ scroller: "[data-scroll-container]" });

/ Add This script For Anchor to work in loco sroll / const anchorLinks = document.querySelectorAll('a[href^=\#]:not([href$=\#])');

anchorLinks.forEach((anchorLink) => {
    let hashval = anchorLink.getAttribute('href');
    let target = document.querySelector(hashval);

    anchorLink.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();

        locoScroll.scrollTo(target);
    });
});
ShadowSlayer03 commented 6 months ago

@GeorgeStudio96 I found the issue for link 3(the solution I suggested you), in the JS file your declared the Locomotive Scroll as locoScroll, but for the scrollTo you put scroll instead of putting locoScroll, so it should be as:

const slider= document.querySelector('#about');

$('.anchor__link:nth-child(3)').on('click', function() {
    locoScroll.scrollTo(slider)
});

this worked for me

Thank you so much dear friend. Tried many different JS methods and such to solve this issue but was not helpful. This worked

smitbhadiyadra commented 2 months ago

Hello.

I would like contribute with this case.

I did my anchor link works just using the attribute data-scroll-to, like this:

<a href="#end" class="go-to-end" data-scroll-to><i class="fas fa-chevron-down"></i></a>

I got it of the inspect tool of page that @GeorgeStudio96 post here (https://locomotivemtl.github.io/locomotive-scroll/)

thanks bro, i really thank you

GeorgeStudio96 commented 2 months ago

I am happy bro. But I recommend you use in 2024 year library Lenis. It’s really cool library for smooth scroll in websites

On Sat, 13 Jul 2024 at 10:52, Samit Bhadiyadra @.***> wrote:

Hello.

I would like contribute with this case.

I did my anchor link works just using the attribute data-scroll-to, like this:

I got it of the inspect tool of page that @GeorgeStudio96 https://github.com/GeorgeStudio96 post here ( https://locomotivemtl.github.io/locomotive-scroll/)

thanks bro, i really thank you

— Reply to this email directly, view it on GitHub https://github.com/locomotivemtl/locomotive-scroll/issues/175#issuecomment-2226812406, or unsubscribe https://github.com/notifications/unsubscribe-auth/APOWWA7JTEK2H5KIB2SF223ZMDMC7AVCNFSM4STXTOD2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TEMRSGY4DCMRUGA3A . You are receiving this because you were mentioned.Message ID: @.***>