Bug 83490

Summary: history pushState doesn't affect :target selector
Product: WebKit Reporter: Paul Irish <paulirish>
Component: HistoryAssignee: Nobody <webkit-unassigned>
Status: REOPENED ---    
Severity: Normal CC: 7raivis, archil, beidson, ben, christopher.bentley, contact, edwardjsabol, ericbidelman, fishd, laughinghan, lzsoft.cja, medikoo+webkit.org
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
URL: http://jsbin.com/esunoh/2/

Description Paul Irish 2012-04-09 11:36:10 PDT
0. open http://jsbin.com/esunoh/2/
1. click "select two"
2. hash on url changes
3. click button to remove hash from url
4. :target selector is still active

What is the expected result?

Should remove the :target selector as the hash is no longer on the url

What happens instead?

Doesn't update the selector.  However, if you try location.hash = ''; button, it will remove the :target selector - therefore I'd expect the pushState to work the same.


Downstream: http://code.google.com/p/chromium/issues/detail?id=89165
Comment 1 Brady Eidson 2012-04-10 13:49:23 PDT
(In reply to comment #0)
> 0. open http://jsbin.com/esunoh/2/
> 1. click "select two"
> 2. hash on url changes
> 3. click button to remove hash from url
> 4. :target selector is still active
> 
> What is the expected result?
> 
> Should remove the :target selector as the hash is no longer on the url
> 
> What happens instead?
> 
> Doesn't update the selector.  However, if you try location.hash = ''; button, it will remove the :target selector - therefore I'd expect the pushState to work the same.
> 
> 
> Downstream: http://code.google.com/p/chromium/issues/detail?id=89165


What do other browsers do?  What does the relevant spec say?
Comment 2 Edward Sabol 2012-08-06 11:14:15 PDT
It doesn't work in Firefox either, but I agree with the reporter that it should, FWIW.
Comment 3 Steven Vachon 2016-01-25 10:42:23 PST
I'm experiencing this issue as well. 4 years and it hasn't been fixed? WTF.
Comment 4 Brady Eidson 2016-01-25 11:21:29 PST
(In reply to comment #3)
> I'm experiencing this issue as well. 4 years and it hasn't been fixed? WTF.

This is not a bug.

The state object is about session history, and not the actual URL of the document.

Chromium noted this in their version of the bug (http://code.google.com/p/chromium/issues/detail?id=89165)

"This behaviour is per spec as it says "Since this is neither a navigation of the browsing context nor a history traversal, it does not cause a hashchange event to be fired." See https://html.spec.whatwg.org/multipage/browsers.html#dom-history-pushstate (Section 7.5.2)."
Comment 5 Archil Imnadze 2016-02-05 05:44:13 PST
When location.hash equals an empty string
how can document.querySelector(':target') be equal to an element?
How is it true?!

The spec says that hashchange event shouldn't be fired
But it doesn't restrict you in applying css styles.
So basically the bug is valid and you won't fix it because you are lazy.
This is true.
Comment 6 Brady Eidson 2016-02-05 10:21:05 PST
(In reply to comment #5)
> When location.hash equals an empty string
> how can document.querySelector(':target') be equal to an element?
> How is it true?!
> 
> The spec says that hashchange event shouldn't be fired
> But it doesn't restrict you in applying css styles.
> So basically the bug is valid and you won't fix it because you are lazy.
> This is true.

Since Archil contributed this respectful comment, engaging the community in a positive way, I took another look at this.

My most previous comment:

(In reply to comment #4)
> This is not a bug.
> 
> The state object is about session history, and not the actual URL of the
> document.

...was simply wrong.

It's always updated the Document URL (http://trac.webkit.org/changeset/51644) 

But does this automatically mean the CSS selector should be updated? 

I'm not sure. I know very little about the specific rules of CSS style recalc. It does appear in https://drafts.csswg.org/selectors-3/#target-pseudo that the document's URL should apply. But what I don't know is if pushState/replaceState themselves should actually trigger a style recalc...  but of course anything else that triggers a recalc would come along and refresh it...

I'll ask some CSS folks to help resolve this uncertainty.

But, in the meantime, NOBODY does this. I just tried:
-Latest Chrome (48.0.2564.103)
-Latest Firefox (44.0)
-Latest Edge (12.10514)
-IE11

And this doesn't work in any of them.

So even if we conclusively say "yes, this is the right thing", it's a compatibility concern.
Comment 7 Brady Eidson 2016-02-05 10:23:37 PST
To summarize:
-It appears *likely* that specs do call for this, though not conclusively yet.
-It's a *very* easy fix in WebCore
-But it's a compatibility nightmare.
Comment 8 Brady Eidson 2016-02-05 10:36:20 PST
I've commented in the chromium bug.

I can't find a mozilla bug for this.

AFAIK Edge doesn't have a traditional bug tracker.
Comment 9 Archil Imnadze 2016-02-05 11:46:30 PST
I've spent several days implementing pushState in a website that already used :target selectors. Only today I found that :target-s won't work anymore. That's reason of my frustration and I hope you understand.

Anyway I still think someone should be the first to propose a fix for this only css issue. Thanks Brandy and others for your attention. I've also reported to Mozilla's Bugzilla at https://bugzilla.mozilla.org/show_bug.cgi?id=1246240

Let's see what they think.
Comment 10 Chris Rebert 2016-02-07 15:45:15 PST
(In reply to comment #8)
> AFAIK Edge doesn't have a traditional bug tracker.

They have https://connect.microsoft.com/IE/Feedback
Comment 11 Brady Eidson 2016-02-07 21:04:16 PST
(In reply to comment #10)
> (In reply to comment #8)
> > AFAIK Edge doesn't have a traditional bug tracker.
> 
> They have https://connect.microsoft.com/IE/Feedback

Which is something, but not a "traditional bug tracker"

Has anybody filed this issue with that tracker and seen activity on the report?
Comment 12 Brady Eidson 2016-02-07 21:05:22 PST
FWIW, the Mozilla folks stance is the compatibility concern is first and foremost, and they've filed a bug with the spec to formalize the current agreed upon behavior.

https://github.com/whatwg/html/issues/639
Comment 13 Han 2016-04-12 18:58:06 PDT
People, we're all in agreement that the current behavior is stupid right?

I've commented on the WHATWG ticket (1) suggesting we might be able to ascertain that this would be a safe breaking change (2) suggesting backwards-compatible fixes: https://github.com/whatwg/html/issues/639#issuecomment-209189744
Comment 14 Han 2016-04-21 13:25:19 PDT
@beidson

After discussion in the WHATWG IRC I think I've found a good reason to believe that fixing this would not be a compatibility nightmare: though pushState indeed doesn't affect :target selector in all browsers, if you then hit Back then Fwd, :target will now be updated in all browsers: http://output.jsbin.com/quludi

(Tested in Chrome 48, Firefox 45, Safari 9.0.3.)

So the only way for a webapp to be broken by :target selectors being updated upon pushState, yet function correctly when you hit Back then Fwd, would be if the webapp's popstate/hashchange handlers had some kind of hysteresis that obscured the broken :target CSS. This seems highly unlikely to me. I have difficulty imagining why a popstate/hashchange handler would make a CSS change that depended on the sequence of Backs and Fwds to get to that history state, not to mention how it could obscure a :target rule that would've been broken if it had been applied upon the first .pushState().