Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve interaction between enhanced nav and scroll position #51646

Closed
SteveSandersonMS opened this issue Oct 25, 2023 · 24 comments · Fixed by #60296
Closed

Improve interaction between enhanced nav and scroll position #51646

SteveSandersonMS opened this issue Oct 25, 2023 · 24 comments · Fixed by #60296
Assignees
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-enhanced-navigation feature-blazor-navigation Pillar: Complete Blazor Web Priority:1 Work that is critical for the release, but we could probably ship without triaged
Milestone

Comments

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Oct 25, 2023

Enhanced nav produces different scroll position behaviors than normal navigation. Ideally it would be approximately the same.

  • When clicking a link:
    • Current: Regular navigation scrolls to the top, enhanced nav behaves unpredictably:
      • If you're not doing streaming SSR, then it doesn't scroll to the top
      • If you are doing streaming SSR, then whether or not it scrolls depends on how quickly the streaming completes
    • Ideal: Enhanced nav should scroll to top, except if you're staying on the same page, in which case it should leave the scroll position alone (though it's unclear what we should do if there's streaming SSR - do we restore the scroll pos after streaming completes?)
  • When going back/forwards:
    • Current: Regular nav tracks the scroll positions and restores them after backforwards; enhanced nav does not
    • Ideal: Ideally it would somehow track and restore scroll positions
@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Oct 25, 2023
@SteveSandersonMS
Copy link
Member Author

See also #51338 which we closed but is valid

@javiercn
Copy link
Member

@SteveSandersonMS do you think we should patch this behavior? or is it fine being something we potentially tackle in 9.0

@SteveSandersonMS
Copy link
Member Author

I was expecting it would be too big of a feature to put into a patch. What's your view?

@ynnob
Copy link

ynnob commented Oct 30, 2023

@javiercn @SteveSandersonMS
I really dislike the current way this works. So looking at #51338 we should use some js to stop this? But on the other hand i don't think the current behavior of enhanced nav is even correct.

When scrolling down a page and navigating to a link in the footer it is always acting super weird and your scroll position will not even be at the position you were before.

Checkout my page atm. It's running .NET 8 RC2. If you visit my Blazor Page https://ynnob.com/ and go to Privacy Policy and scroll to the footer and navigate to Datenschutz you are not at the bottom anymore. So even that is not working correctly.

EDIT: nvm 🤡 it is working correctly. The Datenschutz page is longer then the privacy policy so it just jumps up. But this is still confusing. So what is the best way to handle this. Always scroll to the top with js?

@Bartmax
Copy link

Bartmax commented Nov 2, 2023

I believe the browser restores scroll when page fully loads, so can't we fake SSR until everything is rendered and let the browser restores the scroll by itself. Actually this will be very aligned to normal (streaming) server render behavior

@ghost
Copy link

ghost commented Nov 2, 2023

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Nov 2, 2023
@fyitec-james
Copy link

fyitec-james commented Nov 18, 2023

I think this needs to be patched in .NET 8. A navigation event should always scroll to the top by default, including same page.

In the linked closed issue, 51338, the comment was made that it would make form submissions weird. The same argument can be made of the current behavior. Regular form submissions almost always scroll to the top when there's an error, where the dotnet Blazor templates even place the validation summary message, or custom scrolling is implemented to jump to a form validation error. Leaving the viewport at the form submit button leaves the user confused on if it went through or not and is a terrible user experience.

The comment was also made that this behavior, not resetting to the top on enhanced navigation, is in line with SPA apps. Which ones exactly? Because React navigation events scroll to the top, and retaining the current position requires implementing additional code:
https://reactrouter.com/en/main/components/scroll-restoration
If this was in reference to just form submissions, which, granted, a React form submission would not cause the scrolling to reset, then at least fix the behavior elsewhere, such as on NavLinks.

Retaining the scroll position should be an optional parameter on NavLinks and NavigationManager.NavigateTo() that defaults to false, and arguably the same on EditForm.

I'm seeing normal scroll position recovery for enhanced navigation on browser back and forward, so no problems there.

Please consider patching this in .NET 8 LTS.

Also, I don't want to sound ungrateful - I appreciate the hard work on .NET 8 Blazor! It's an amazing framework and I'm loving the new Identity pages! ❤️

@ladeak
Copy link
Contributor

ladeak commented Nov 18, 2023

I am trying to migrate a prerendered webassembly application to SSR and a few components InteractiveWebAssembly rendered. I am using non-streaming rendering, and I also notice the scroll position is not reset when clicking on anchor tags. This is really unexpected, I would be happy with a patch or a workaround.

I also notice that some of the JS libraries within the webassembly components don't get rendered correctly on navigation.

@ladeak
Copy link
Contributor

ladeak commented Nov 25, 2023

Is there a workaround? I tried adding an interactive wa rendered component with some JS interop to scroll to the top, but it only works on refresh.

EDIT: I assume one workaround could be:

    <script>
        const observeUrlChange = () => {
            let oldHref = document.location.href;
            const body = document.querySelector("body");
            const observer = new MutationObserver(mutations => {
                if (oldHref !== document.location.href) {
                    oldHref = document.location.href;
                    window.scroll(0, 0);
                }
            });
            observer.observe(body, { childList: true, subtree: true });
        };
        window.onload = observeUrlChange;
    </script>

@vpekarek
Copy link

The previous script did not work for me, not sure why.

So here is different way how to do it using the Blazor enhancedload event:

<script>
    window.interceptNavigation = () => {
        let currentUrl = window.location.href;
        Blazor.addEventListener('enhancedload', () => {
            let newUrl = window.location.href;
            if (currentUrl != newUrl) {
                window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
            }
            currentUrl = newUrl;
        });
    };

    document.onload += window.interceptNavigation();
</script>

Place this script just after <script src="_framework/blazor.web.js"></script>.

@ghost
Copy link

ghost commented Dec 20, 2023

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mkArtakMSFT mkArtakMSFT added the Priority:1 Work that is critical for the release, but we could probably ship without label Jan 16, 2024
@heron1
Copy link

heron1 commented Jan 18, 2024

Clicking a link and scrolling to the top of a new page is a base requirement of a web app. How is this not part of .NET 8 for all its fame and glory? It seems the most simplest of features are always passed to yet another major .NET release, and people wonder why no serious real world app uses blazor yet for B2C.

Scrolling to the top of a new page is very, very much required functionality for how the Internet works, and has worked since the 90s. I must question the overall management decisions of the people in charge of Blazor for thinking maintaining scroll positions on different page navigations without an option to turn it off was a good idea. I mean, seriously?

@vpekarek
Copy link

The thing here is, that for example the Vue.js have the same behavior, but it is easy to override it in the routing middleware.
In the Blazor, I did not find any 100% working solution.

@Fydar
Copy link

Fydar commented Feb 27, 2024

I would greatly appreciate having backwards and forward navigation working correctly. It is so incredibly infuriating to have to scroll down my work-in-progress portfolio every time I click on a project and head back to the home page.

Until then, I will need to disable the enhanced navigation script.

To restore the original browser behaviour (and fix the backward and forward navigation not having the correct scroll positions), you can disable "enhanced navigation" in the App.razor by replacing:

<script src="_framework/blazor.web.js"></script>

With:

<script src="_framework/blazor.web.js" autostart="false"></script>
<script>
    Blazor.start({
        ssr: { disableDomPreservation: true }
    });
</script>

@Bartmax
Copy link

Bartmax commented Apr 6, 2024

It is so incredibly infuriating

I disabled it too, very very very frustrating.

@Kebechet
Copy link

Kebechet commented Jul 7, 2024

I am not able to find any workaround for Blazor hybrid. Try to link this functionality with: history.scrollRestoration property.
https://developer.mozilla.org/en-US/docs/Web/API/History/scrollRestoration

@Quemuel-Nassor
Copy link

@vpekarek's suggestion worked perfectly for me, I made a slightly improved version that provides an event for custom actions when there is a change of parameters on the page

/**
 * get url data
 * @returns { urlBase, filterKeys, filterValues }
 */
function getUrlInfo() {
    let url = new URL(window.location.href);
    let urlBase = `${url.origin}${url.pathname}`;
    let filterKeys = Array.from(url.searchParams.keys());
    let filterValues = Array.from(url.searchParams.values());

    return { urlBase, filterKeys, filterValues };
}

/**
 * handle scroll behavior on enhanced navigation 
 */
window.enhancedNavigationHandler = () => {

    let currentUrl = getUrlInfo();

    Blazor.addEventListener('enhancedload', () => {

        let targetUrl = getUrlInfo();

        /* check if page params has changed */
        let filterKeysHasChanged = currentUrl.filterKeys.filter(e => !targetUrl.filterKeys.includes(e)).length != 0;
        let filterValuesHasChanged = currentUrl.filterValues.filter(e => !targetUrl.filterValues.includes(e)).length != 0;

        /* scroll to top if page url has changed */
        if (currentUrl.urlBase != targetUrl.urlBase)
        {
            window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
        }
        /* trigger pageSearch event if only page url parameters has changed */
        else if (filterKeysHasChanged || filterValuesHasChanged)
        {
            document.dispatchEvent(new Event("pageSearch"));
        }

        currentUrl = targetUrl;
    });
};

/* pageSearch event listener sample */
//document.addEventListener("pageSearch", () => { console.log("search occourred on page") });

document.onload += window.enhancedNavigationHandler();

@alex-fitplans
Copy link

I too had to disable enhanced navigation in order to get normal hyperlink navigation behavior.
Hopefully this can get fixed in .NET 9

@Bartmax
Copy link

Bartmax commented Aug 9, 2024

@Quemuel-Nassor Unfortunately using this kind of hacks doesn't properly handle forward/back buttons and navigation to another page with hash #.

My flawless fix was to remove enhance nav completely and add hotwire turbo for an awesome experience.

@BillyMartin1964
Copy link

Adding this to your links works:

data-enhance-nav="false"

@IngweLand
Copy link

I am new to Blazor but already stuck with this issue. A super basic scenario, where you have a list, each item is an anchor tag. You scroll to the bottom, click on the item, which navigates you to another page... and that new page is already scrolled to the bottom. This is completely unexpected. Putting data-enhance-nav="false" on the list container fixes the issue.

@mkArtakMSFT
Copy link
Member

Related #53996

@javiercn
Copy link
Member

javiercn commented Feb 6, 2025

Ideal: Enhanced nav should scroll to top, except if you're staying on the same page, in which case it should leave the scroll position alone (though it's unclear what we should do if there's streaming SSR - do we restore the scroll pos after streaming completes?)

This might be covered by #60190

@ilonatommy
Copy link
Member

Ideal: Enhanced nav should scroll to top, except if you're staying on the same page, in which case it should leave the scroll position alone (though it's unclear what we should do if there's streaming SSR - do we restore the scroll pos after streaming completes?)

This might be covered by #60190

It's not, the mentioned PR fixed only client side routing navigation. In the fix for this issue we should also include the scenario of enhanced self-navigation and self-navigation with queries that was described in #40190.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-enhanced-navigation feature-blazor-navigation Pillar: Complete Blazor Web Priority:1 Work that is critical for the release, but we could probably ship without triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.