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

Anchor with #hash not showing :target CSS after history.back() #10550

Closed
hyunbinseo opened this issue Aug 14, 2023 · 3 comments
Closed

Anchor with #hash not showing :target CSS after history.back() #10550

hyunbinseo opened this issue Aug 14, 2023 · 3 comments
Labels
router wontfix This will not be worked on

Comments

@hyunbinseo
Copy link
Contributor

hyunbinseo commented Aug 14, 2023

Describe the bug

  1. Goto /#target
  2. Goto /temp
  3. Return to the previous page
  4. URL is /#target and the #target:target styles are not shown.

In this state, clicking <a href="#target"> should show #target:target styles, but it does not.

Reproduction

https://stackblitz.com/edit/github-ymws75?file=src%2Froutes%2F%2Bpage.svelte

System Info

  • Chrome 버전 115.0.5790.170(공식 빌드) (arm64)
  • Firefox 116.0.2 (64-비트)
System:
  OS: Linux 5.0 undefined
  CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Memory: 0 Bytes / 0 Bytes
  Shell: 1.0 - /bin/jsh
Binaries:
  Node: 16.20.0 - /usr/local/bin/node
  Yarn: 1.22.19 - /usr/local/bin/yarn
  npm: 9.4.2 - /usr/local/bin/npm
  pnpm: 8.6.10 - /usr/local/bin/pnpm
npmPackages:
  @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
  @sveltejs/kit: ^1.20.4 => 1.22.5 
  svelte: ^4.0.5 => 4.2.0 
  vite: ^4.4.2 => 4.4.9

Severity

annoyance

Additional Information

  1. Using <a href="#target" data-sveltekit-reload> fixes the :target CSS issue.
  2. Possibly related to Hash links to new pages don't focus the correct element #3770
@whataboutpereira
Copy link
Contributor

This is what I'm using to work around it without reloading the page.

const navigate = (navigation?: Navigation) => {
	if (navigation) {
		if (navigation.to?.url.hash && navigation.to.url.hash !== '#') {
			// history.replaceState() needed by Firefox to navigate back.
			const state = history.state;
			location.replace(navigation.to.url);
			history.replaceState(state, '', location.href);
		}
	}
};

afterNavigate(navigate);

@eltigerchino
Copy link
Member

eltigerchino commented Oct 8, 2023

This seems to be a limitation of client-side routing / rendering. The browser navigates to the new URL but cannot find the element with the corresponding id as it has not been rendered through javascript yet. You can observe a similar behaviour when navigating from /#one to / as mentioned in #10524 . The native browser behaviour would be a full page reload when navigating from a hash to a non-hash URL.

I'm not sure what the solution here is. history.replaceState and history.pushState have no effect. location.replace(navigation.to.url) mentioned in #10550 (comment) is a notable hack as it works without reloading, but we can't stop it from emitting a popstate event (which already occurs once when we hit the back button). I've looked at next.js and nuxt.js to see if they have a solution but the same issue occurs.

Adding data-sveltekit-reload to the <body> and enabling SSR ensures the most consistent behaviour when using :target styles.

If you prefer a hacky alternative, #10550 (comment) and using an empty hash /# instead of / ensures that the :target style is cleared without a full page reload.

Related #3177 (with some good findings inside the PR and issues linked)

@eltigerchino eltigerchino added router wontfix This will not be worked on labels Oct 8, 2023
@eltigerchino eltigerchino closed this as not planned Won't fix, can't repro, duplicate, stale Oct 8, 2023
@hyunbinseo
Copy link
Contributor Author

hyunbinseo commented Jul 8, 2024

Now that $page.url.hash is fixed and reactive, it might be best to toggle class-names.

<script lang="ts">
  import { page } from '$app/stores';
</script>

<p id="secret-code" class:hidden={$page.url.hash !== '#secret-code'} class="target:block">
  Hidden Message Block
</p>

<a href="#secret-code">Show Message</a>

Not that this REQUIRES JavaScript to work.

:target CSS could be provided as a fallback as shown above.


<!-- ShowOnTarget.svelte -->

<script lang="ts">
  import { page } from '$app/stores';

  export let id: string;
</script>

<div {id} class:hidden={$page.url.hash !== `#${id}`} class="target:block">
  <slot></slot>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
router wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants