Csswg-drafts: CSS :active and JS mousedown preventDefault complication

Created on 2 Feb 2018  路  16Comments  路  Source: w3c/csswg-drafts

Please read this topic. I also observe the problem. FF behaves differently than other browsers but the behaviour looks to be... undefined.

https://stackoverflow.com/questions/11464520/aactive-vs-mousedown-event-preventdefault-ed

Is here any dpec that define it to file a bug to Moz?

There is no way to fire :active from JS, thus I guess the behaviour of IE11 and Cr is correct in that case.

selectors-4

Most helpful comment

The requested spec was not found. That's all we know...

I propose the :active should be invoked before (on)mousedown. There also should be specified that before or after touch event.

Why before? There is no JS function to fire :active and then preventDefault the rest.
In contrast to :focus, there are functions to fire focus and blur.

Also the :hover should be invoked before mousemove/mouseenter. The reason the same: no JS function to invoke :hover and preventDefault.

All 16 comments

The quoted section of Selectors is intended to connect with this definition in HTML: https://html.spec.whatwg.org/multipage/semantics-other.html#selector-active

Unfortunately, I can't make enough sense of the HTML definition to answer your question about what behavior should happen in the above situation (or if it's even fully defined). Maybe @annevk can help?

I'm not entirely sure I understand that definition either, but the main problem here is with hit testing not being defined, and UI events and selectors not being defined in terms of that. That should all be part of a set of algorithms dealing with user input.

I don't think either browser fail to comply with the definition, I think the actual issue is a difference in handling the 'mousedown' event. In firefox, preventDefault'ing the mousedown event prevents the click event to fire. As such, it cancels the navigation action of the link in Firefox while it does not in Edge and Chrome. From this difference, all else follows.

Just to be clear, here is the definition we are looking at:

If the element is an a element that has an href attribute, [...]
Then the element is being activated if it is in a formal activation state.

An element is said to be in a formal activation state between

  1. the time the user begins to indicate an intent to trigger the element's activation behavior and
  2. either

    1. the time the user stops indicating an intent to trigger the element's activation behavior, or

    2. the time the element's activation behavior has finished running, which ever comes first.

Since calling preventDefault on mousedown does prevent the click event in Firefox, and that the click event is where the activation behavior runs, preventDefault'ing in Firefox does finish the activation behavior (condition 2.2) and then :active stops to apply.

Since calling preventDefault on mousedown does not prevent the click event in Chrome and Edge, it does not cause condition 2.2 to become true, and therefore :active continue to apply.

I spent some time in the Pointer Events and UI Events specs, and I don't see any ground to justify the Firefox's behavior to cancel the 'click' event in case 'preventDefault' has been called on mousedown. I think we should file an issue on them regarding that behavior.

Test case: http://jsfiddle.net/n45k9/112/

6 years and UNCONFIRMED? They should hire illuminati to confirm it.

From my bug report:

nsFileControlFrame::SetFocus hasn't got an implementation
https://bugzilla.mozilla.org/show_bug.cgi?id=1430196

Looks like the events are not implemented globally and are implemented for each control and element separately.

@FremyCompany you generally want to talk to @smaug---- about event issues. But as I said in the bug you link, the default action of mousedown is to make things active. If you prevent its default action... they don't become active.

The definition of :active is not specific to links (or shouldn't be; lots of other things can become :active), so I'm not sure how a link-specific bit of text is relevant.

In firefox, preventDefault'ing the mousedown event prevents the click event to fire.

What makes you say that, exactly? My testcase at http://jsbin.com/qugizofuhe/edit?html,output shows an alert in Firefox.

Test case http://jsfiddle.net/n45k9/112/ (seems to be specific for links indeed)


The definition of :active is not specific to links (or shouldn't be)

Well, it is. I guess the reason is the past only links used to be :active things, so I'm fairly sure there is a bunch of content that depends on a specific behavior for active on links that might actually be different from other elements.

Test case http://jsfiddle.net/n45k9/112/ (seems to be specific for links indeed)

That testcase removes the actual target of the event (the textnode) from the DOM onmousedown, so the mousedown and mouseup are happening on different nodes. You're right that Firefox doesn't fire click in that case (for the same reasons that click doesn't get fired if you mouse down on an element then move your mouse outside it before releasing), but that has nothing to do with preventDefault() in any way. That testcase shows the same behavior if the preventDefault() is taken out.

Well, it is.

Ugh. Gecko basically just implements the "If the element is being actively pointed at" bit, and has all along, instead of doing this bizarre per-tag list of different behaviors. Do other UAs actually do the per-tag behaviors, or is this something aspirational Hixie just wrote?

I guess the reason is the past only links used to be :active things

Fwiw, Gecko's current behavior has been in place ever since I recall. I'd bet it's the only :active behavior Gecko ever had. And it's allowed non-links to be :active all along.

In any case, a simple testcase for non-links at http://jsbin.com/sawafonogu/edit?html,output shows that browsers don't even agree on that. And this one should only involve the "actively pointed at" concept. Of course this concept is not defined in terms of events at all, which makes it vague enough that who knows what it means.

That testcase removes the actual target of the event (the textnode) from the DOM onmousedown, so the mousedown and mouseup are happening on different nodes.

Hashtag "When one line of debug code derails you testcase " :)

I wasn't able to find much of a specific behavior for links in Edge (except AREA) but I do see the special behavior for the space key and buttons.

The interop difference between Edge/Chrome and Firefox is shown here:
http://jsbin.com/bavexoneno/edit?html,console,output

Firefox adds "active" as a "default action" of mousedown (hence cancellable), while active is already set before firing mousedown in the other browsers.

FWIW, the processing for ":active" in Edge happens in the input/output message pipeline directly, (way) before event deciding to create a "mousedown" event.

What makes you say that, exactly? My testcase at http://jsbin.com/qugizofuhe/edit?html,output shows an alert in Firefox.

Test 52 ESR version. I see only random numbers. In Chromium 63 two alerts.

I make preventDefaulting (in my commercial sites) on <datalist/>s and <option/>s. The effect: no :active pseudoclass, the :focus on input still present (and preventing blur is OK), I had to use .activeclass and additionally use mouseupon document to cancel the .activeclass. In FF the :activeis not invoked, In Cr, IE11 and EDGE does.

I think we should clarify the spec that Firefox makes it badly if ALL OTHER browsers makes it identically. I am fan of Moz but if only Moz behaves differently...

while active is already set before firing mousedown in the other browsers.

Lovely. This is why we need actual specs instead of handwaving. With a processing model, instead of handwaving. ;)

the processing for ":active" in Edge happens in the input/output message pipeline directly

Does it get affected by things like user-select, SVG bits that affect event targeting, etc? I mean, it must at least be happening after the event target is determined, right?

I am not wedded to the current Firefox behavior, and am willing to change it, but not willing to change it twice. Hence it would be good to have a clear spec for what the behavior should be.

Test 52 ESR version. I see only random numbers.

It would help if you were running the actual testcase I linked, which has no random numbers and the behavior I described. Including in ESR52.

the processing for ":active" in Edge happens in the input/output message pipeline directly

Does it get affected by things like user-select, SVG bits that affect event targeting, etc? I mean, it must at least be happening after the event target is determined, right?

Yes, after that indeed.

The requested spec was not found. That's all we know...

I propose the :active should be invoked before (on)mousedown. There also should be specified that before or after touch event.

Why before? There is no JS function to fire :active and then preventDefault the rest.
In contrast to :focus, there are functions to fire focus and blur.

Also the :hover should be invoked before mousemove/mouseenter. The reason the same: no JS function to invoke :hover and preventDefault.

Just adding two cents and maybe reinvoke this thread for consideration in spec; but I'd also like to see the presentation layer elements (aka pretty much everything handled first by compositor thread) handling their own events before main thread events.

Primarily because I just spent far more time than I would have liked hunting down this innocuous nuance that none of the other browsers are effected by just to have some nifty UX interactions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

svgeesus picture svgeesus  路  3Comments

rachelandrew picture rachelandrew  路  3Comments

schenney-chromium picture schenney-chromium  路  3Comments

fantasai picture fantasai  路  3Comments

litherum picture litherum  路  3Comments