Skip to main
a head full of software engineering by
Timo Mämecke
Jump to navigation
· 1 minute read

URL Fragments and pushState() are weeeiiird

Yesterday I learned two weird things that happen when you use pushState() to navigate to a page with a URL fragment:

  1. The CSS :target selector doesn’t work. You can use :target to style an element that is the current URL fragment when doing a full document load, but not with pushState! This is also documented on MDN:

    The target element is set at document load and history.back(), history.forward(), and history.go() method calls. But it is not changed when history.pushState() and history.replaceState() methods are called.

    But that’s weird! Why not? I would argue that it makes :target a little bit unusable in modern web applications. Even though it’s such a useful feature!

  2. The hashchange event doesn’t fire. Even though the hash changes, the event doesn’t fire. This is also documented on MDN, but oddly enough it’s documented in the pushState docs, and not in the hashchange docs.

    Note that pushState() never causes a hashchange event to be fired, even if the new URL differs from the old URL only in its hash.

    That’s weird! And unexpected. This note should be included in the hashchange docs. Might be a good opportunity to open a small pull request.


Update: I did indeed open a small pull request and the hashchange docs now also explain this behavior.