[csswg-drafts] [selectors] New pseudo-class that matches the current URL fragment (#6942)

domenic has just created a new issue for https://github.com/w3c/csswg-drafts:

== [selectors] New pseudo-class that matches the current URL fragment ==
Original issue: https://github.com/WICG/app-history/issues/162; /cc @jakearchibald @stephband.

Currently the `:target` pseudo-class [is defined](https://drafts.csswg.org/selectors/#the-target-pseudo) as such:

> The :target pseudo-class matches the document’s target elements.

HTML then [defines](https://html.spec.whatwg.org/#selector-target) this based on a [target element](https://html.spec.whatwg.org/#target-element) pointer, which is updated at specific points when the [scroll to the fragment](https://html.spec.whatwg.org/#scroll-to-the-fragment-identifier) algorithm is run during navigation/history traversal.

This approach of updating a pointer at specific points in time is *not* equivalent to "`:target` always matches the first document-tree element with an ID corresponding to the document's URL's fragment component". This is true in several regards:

1. You can update a document's URL's fragment via `history.pushState(null, "", "#foo")`. (Or by using [cursed magics](https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#:~:text=If%20document%20is%20fully,with%20document%20and%20newURL.).) This does not trigger "scroll to the fragment" and so does not update the target element.

1. Inserting a new element does not trigger "scroll to the fragment". So if the current URL fragment is `#foo`, but no element currently has ID `foo`, then adding such an element will not cause that element to match `:target`. Adding such an element can _sometimes_ work, if you do so early in the document lifecycle before "scroll to a fragment" has completed. But usually it does not.

1. There are various legacy-seeming string processing tricks going on that make the fragment/ID matching non-exact. E.g. special processing for `#top` (not sure if this impacts `:target`), and how the algorithm first tries exact match and then tries to do an extra round of percent-decoding (so, `#%66oo` will cause an element with ID `#foo` to match, unless there is another element with ID `#%66oo` somewhere in the DOM).

1. Similarly, there is a presumably-legacy affordance for `<a>` elements with `name=""` attributes.

@stephband has expressed that he much prefers the "always matches the first document-tree element with an ID corresponding to the document's URL's fragment component" model, mentioning specifically (1)-(2). ((3) and (4) were just things I noticed reviewing the algorithms, which maybe are worth considering while we're here.) And this use case makes sense to me.

I strongly suspect changing `:target`'s behavior is not web-compatible, and further I think there are probably people who _want_ the currently-specified target behavior. E.g. if you use `:target` to highlight an element after the user scrolls to it via a fragment hyperlink, with some sort of fading-out flash, you might not want that fading-out flash effect for newly-inserted elements, even if they have an ID that happens to match the current URL fragment.

But introducing a new pseudo-class, with the always-match semantics, might be worthwhile. My strawperson names are `:current-url-fragment` or `:location-hash`.

It's not clear to me how much of a problem this is. So far only @stephband has expressed this to be an issue for their applications. Lots of developers "liked" [my corresponding tweet](https://twitter.com/i/timeline) but nobody else showed up to the original issue on WICG/app-history or replied with comments. But I wanted to log this feature suggestion here since it does make sense to me.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6942 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 11 January 2022 17:14:45 UTC