After loading a page, a browser automatically scrolls to the element identified by its id in the fragment part of the URL. It does the same when you click on an anchor with an href of the kind #element-id.
The page load behavior doesn't work for a Blazor Server because the element doesn't exist yet on page load.
The solution is to manually create a scroller using javascript and a razor component:
First of all, create a razor component like this
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@implements IDisposable
@code {
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await ScrollToFragment();
}
public void Dispose()
{
NavigationManager.LocationChanged -= OnLocationChanged;
}
private async void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
await ScrollToFragment();
}
private async Task ScrollToFragment()
{
var uri = new Uri(NavigationManager.Uri, UriKind.Absolute);
var fragment = uri.Fragment;
if (fragment.StartsWith('#'))
{
// Handle text fragment (https://example.org/#test:~:text=foo)
// https://github.com/WICG/scroll-to-text-fragment/
var elementId = fragment.Substring(1);
var index = elementId.IndexOf(":~:", StringComparison.Ordinal);
if (index > 0)
{
elementId = elementId.Substring(0, index);
}
if (!string.IsNullOrEmpty(elementId))
{
await JSRuntime.InvokeVoidAsync("BlazorScrollToId", elementId);
}
}
}
}
Then add this javascript code somewhere before the Blazor script renders. You can wrap it with script tags and place it in the head.
function BlazorScrollToId(id) {
const element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
}
Finally implement it in your pages if needed. You can also place it inside your layouts, so it will work for every page you create.
@page "/"
<PageTitle>Index</PageTitle>
<a href="#my-id">
<h1>Hello, world!</h1>
</a>
<SurveyPrompt Title="How is Blazor working for you?" />
<div style="height: 2000px">
</div>
<div id="my-id">
Hello!
</div>
<AnchorNavigation />
Source: link