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

Disable / customize scrolling behavior of Element.focus #834

Open
RByers opened this issue Mar 8, 2016 · 26 comments
Open

Disable / customize scrolling behavior of Element.focus #834

RByers opened this issue Mar 8, 2016 · 26 comments
Labels
addition/proposal New features or enhancements

Comments

@RByers
Copy link

RByers commented Mar 8, 2016

From www-style discussion: when Element.focus() is used the UA may scroll the element into view (it's not immediately obvious to me if this is specified or not). In that case, there's currently no way to request the scrolling to be smooth. Perhaps focus should take an optional ScrollBehavior like Element.scrollIntoView now does?

@RByers RByers changed the title Should Element.focus take a ScrollBehavior Should Element.focus take a ScrollBehavior? Mar 8, 2016
@domenic
Copy link
Member

domenic commented Mar 8, 2016

Interesting. I am pretty sure this is not specced, but it probably should be! How interoperable is it? I assume this kind of scrolling only happens for .focus(), not for other methods of focusing like tabbing?

I think this is an eminently reasonable proposal, and would be happy to work on a PR or review one from you, if Blink is interested in implementing and nobody else objects.

@domenic domenic added the addition/proposal New features or enhancements label Mar 8, 2016
@zcorpan
Copy link
Member

zcorpan commented Mar 9, 2016

Tabbing also scrolls, and as was pointed out in www-style, it would be nice if it was possible to control smooth scrolling for that using the scroll-behavior CSS property. Moving sequential navigation is also part of the HTML spec.

The dictionary to use for focus() would be either ScrollOptions (to be able to control only behavior) or ScrollIntoViewOptions (if you also want to control the position etc).

@RByers
Copy link
Author

RByers commented Mar 9, 2016

This isn't urgent from the blink implementation side, our implementation of CSS OM smooth scroll is temporarily on hold, but we do hope to resume soon.

@tkent-google
Copy link
Collaborator

"No scrolling" option is also necessary. There is such use case.

@zcorpan
Copy link
Member

zcorpan commented Apr 12, 2016

What is the use case?

@tkent-google
Copy link
Collaborator

Suppose that multiple-tabs like UI, and a scrollable tab has a focusable element. Let's call it "Tab-A".

  1. Tab-A is shown initially, and the element is focused.
  2. A user scroll the tab content by scroll bar. The focused element is scrolled out.
  3. The user selects another tab. Tab-A is hidden.
  4. The user selects Tab-A again.
    Want to call focus() for the focusable element in Tab-A, but we'd like to keep the last scroll position.

We'd like to do this in DevTools console tab of Google Chrome.

@aFarkas
Copy link

aFarkas commented May 11, 2016

See also this use case for the no scroll behavior:
https://discourse.wicg.io/t/improve-element-focus-method-with-options-or-provide-a-better-new-focus-method/1485/3

It would be great, if this feature would be easily feature detectable (i.e.: without trying to focus a hidden element or similar).

@RByers RByers changed the title Should Element.focus take a ScrollBehavior? Disable / customize scrolling behavior of Element.focus Apr 20, 2017
@RByers
Copy link
Author

RByers commented Apr 20, 2017

I just saw another scenario where disabling scrolling probably makes sense - when JS is focusing an element based on pointer hover (for TV use cases).

@jihyerish
Copy link
Contributor

jihyerish commented Apr 20, 2017

I just saw another scenario where disabling scrolling probably makes sense - when JS is focusing an element based on pointer hover (for TV use cases).

Generally, the input device for the TV is the remote controller.
For LG Smart TV, an element is focused by the hover event (when people swing the remote controller).
If there is an element which is partially visible in the scroll area, like below,

image

when hovering the element, focus event triggers the scroll behavior.
On that case, the grid list scrolls too much, and it's really bad UX for TV.
So, we block that behavior with a trick.

Can focus also have the no scrolling behavior?

@jihyerish
Copy link
Contributor

jihyerish commented May 31, 2017

I suggest adding scrollOption to Element.focus() for defining the scroll behavior.

Such as:

Element.focus(scrollOptions);

scrollOptions
{
  behavior: "auto" | "none" | "smooth",
  block: "start" | "end"
 }
  • auto: Element.focus() makes the element scroll into view
  • none: Element.focus() doesn't make the scrolling behavior
  • smooth: Element.focus() makes the element come into view with smooth scrolling

scrollOptions refers to the scrollIntoViewOptions of Element.scrollIntoView().

Element.focus() currently triggers scrolling the element into view. The result is reasonable when focusing based on onkeydown. But when focusing by mouseover the element, focus event also triggers the scroll behavior.

Demo shows no scrolling behavior when focusing by mouseover. If the option isn't checked, it shows the result of the default scroll behavior triggered by Element.focus().

Similar discussion is in w3c/csswg-drafts#1388.

@domenic
Copy link
Member

domenic commented Jun 1, 2017

This seems like a good solution to me. There are several Blink developers on this thread who seem interested; can we find other vendors interested in such an addition?

@zcorpan
Copy link
Member

zcorpan commented Jun 14, 2017

@RByers can you comment on whether there is implementation interest in chromium for @jihyerish's proposal?

@smaug---- can you comment on the same for Gecko?

@RByers
Copy link
Author

RByers commented Jun 16, 2017

That sounds like a good idea to me - I'd support implementing. It's up to @dtapuska on our input team to decide what priority we'd give it.

@dtapuska
Copy link
Contributor

I've created 734166 to track the Chromium issue. We will work on figuring out what kind of priority to set to it. But it seems to make sense to me to do.

@smaug----
Copy link
Collaborator

Looks reasonable to me.

@smaug----
Copy link
Collaborator

Filed https://bugzilla.mozilla.org/show_bug.cgi?id=1374045
Need to have proper spec before implementation work.

@zcorpan
Copy link
Member

zcorpan commented Jun 19, 2017

Thank you!

@jihyerish would you be interested in working on a pull request for the standard? (Otherwise I can work on this, but not until August or so.)

FYI @cdumez @gregwhitworth

@jihyerish
Copy link
Contributor

Yes, I'd like to upload a PR. Thank you! : )

@rniwa
Copy link
Collaborator

rniwa commented Jun 26, 2017

It's not great to use "block" to refer to a viewport location and then use "start" and "end" to refer to the top / bottom of the viewport given "start" and "end" usually refers to an inline direction.

It's not entirely clear what this means in a document in vertical writing mode, or more broadly any page that scrolls horizontally. In particular, it's possible for a document to have both horizontally and vertically scrollable. What does "start" of a viewport mean in such a page?

@smfr @grorg

@jihyerish
Copy link
Contributor

jihyerish commented Jun 27, 2017

What does "start" of a viewport mean in such a page?

I considered the block flow direction here.
If the scrolling direction is top-to-bottom (vertical scrolling), let the beginning edge is the top edge and the ending edge is the bottom edge of the viewport.
If the scrolling direction is left-to-right (horizontal scrolling), let the beginning edge is the left edge and the ending edge is the right edge of the viewport.
If the scrolling direction is right-to-left (horizontal scrolling), let the beginning edge is the right edge and the ending edge is the left edge of the viewport.

Then, if the block dictionary member of options is start, the beginning edge of the viewport is aligned with the edge of the focused element which is on the same physical side of the beginning edge.

@rniwa It's a good point. : )
The inline base direction also need to be considered in this case.

@RByers
Copy link
Author

RByers commented Jul 25, 2017

@yi-gu just raised an interesting point - when you type into an already focused input box it runs the focus steps and causes it to scroll into view. Do we also need some way to customize/disable this focus-based scrolling?

@jihyerish
Copy link
Contributor

jihyerish commented Jul 26, 2017

when you type into an already focused input box it runs the focus steps and causes it to scroll into view

Does it means that an already focused input box calls scrollIntoView() even if it's already within the viewport and its position doesn't change?

I tested for the input box and found out:
If there is a focused input box which is out of view and when I try to type into it, it scrolls into the view. (In Chrome, the input box is positioned at the center of the view, but in Firefox, it is positioned to the nearest edge of the view)

@jihyerish
Copy link
Contributor

jihyerish commented Jul 27, 2017

@RByers
In the past, while adding "center" to ScrollLogicalPosition in CSSOM(see: w3c/csswg-drafts#81), there was a suggestion[1] to specify a boolean value which considers the situation whether or not the element is completely in the view like below:

partial interface Element {
      void scrollIntoView(ScrollPosition options);
    };

    dictionary ScrollPosition {
      float top = 0.5;
      float left = 0.0;
      boolean notIfViewed = true;
      long offsetX = 0;
      long offsetY = 0;
    };

The suggestion referred "scrollIntoViewIfNeeded()" which is a non-standard feature. This API doesn't work if an element is already within the view. (As far as I know, it is still supported in Webkit.)
I'm not sure the boolean value, "notIfViewed" in this suggestion was reflected when updating scrollIntoView() or ScrollLogicalPosition.
@zcorpan could you check out about this?

I think the use case that you mentioned above also could be supported by focus(), if scrollIntoView() can handle the condition when the element is already within the view, and ScrollIntoViewOptions is added to focus() as a parameter.

[1] https://lists.w3.org/Archives/Public/www-style/2012May/0808.html,
https://lists.w3.org/Archives/Public/www-style/2012Jun/0455.html

@domenic
Copy link
Member

domenic commented Oct 26, 2017

Hmm, I didn't mean to close this completely. Let me reopen. @zcorpan summarized the route we ended up taking in #2787 in w3c/csswg-drafts#1805 (comment) .

Roughly, we now have el.focus({ preventScroll: true }). This is enough of a primitive that, in combination with IntersectionObserver and scrollIntoView(), you can customize scrolling on focus. But, it's not super-convenient for developers.

Before adding more developer-facing abilities to focus() we'd like to:

So: progress! But still worth keeping this bug open.

@domenic domenic reopened this Oct 26, 2017
alice pushed a commit to alice/html that referenced this issue Jan 8, 2019
Addresses the most basic part of whatwg#834, allowing further customizations
to be done by JavaScript code.
@yattias
Copy link

yattias commented Jun 6, 2019

I just spent a bunch of time trying to figure out why my scroll function was not working. It turns out, that is due to the scroll behavior of element.focus()

@Fuzzyma
Copy link

Fuzzyma commented Jun 2, 2022

Is there a way to get the same "no scroll" behavior when using the tab key? The current browser behavior is not sufficient because it doesn't detect if the element which is focused is behind another element. Therefore I want to disable it and implement my own version. I do NOT want to reimplement tabbing through focusable elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements
Development

No branches or pull requests