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 · 24 comments

Comments

9 participants
@RByers

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 from Should Element.focus take a ScrollBehavior to Should Element.focus take a ScrollBehavior? Mar 8, 2016

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Mar 8, 2016

Member

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.

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.

@zcorpan

This comment has been minimized.

Show comment
Hide comment
@zcorpan

zcorpan Mar 9, 2016

Member

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).

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

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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.

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

This comment has been minimized.

Show comment
Hide comment
@tkent-google

tkent-google Apr 12, 2016

Contributor

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

Contributor

tkent-google commented Apr 12, 2016

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

@zcorpan

This comment has been minimized.

Show comment
Hide comment
@zcorpan

zcorpan Apr 12, 2016

Member

What is the use case?

Member

zcorpan commented Apr 12, 2016

What is the use case?

@tkent-google

This comment has been minimized.

Show comment
Hide comment
@tkent-google

tkent-google Apr 13, 2016

Contributor

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.

Contributor

tkent-google commented Apr 13, 2016

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

This comment has been minimized.

Show comment
Hide comment
@aFarkas

aFarkas 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).

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 from Should Element.focus take a ScrollBehavior? to Disable / customize scrolling behavior of Element.focus Apr 20, 2017

@RByers

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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).

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish Apr 20, 2017

Contributor

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?

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish May 31, 2017

Contributor

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.

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

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Jun 1, 2017

Member

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?

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

This comment has been minimized.

Show comment
Hide comment
@zcorpan

zcorpan Jun 14, 2017

Member

@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?

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

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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.

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

This comment has been minimized.

Show comment
Hide comment
@dtapuska

dtapuska Jun 16, 2017

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.

Contributor

dtapuska commented Jun 16, 2017

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----

This comment has been minimized.

Show comment
Hide comment
@smaug----

smaug---- Jun 18, 2017

Collaborator

Looks reasonable to me.

Collaborator

smaug---- commented Jun 18, 2017

Looks reasonable to me.

@smaug----

This comment has been minimized.

Show comment
Hide comment
@smaug----

smaug---- Jun 18, 2017

Collaborator

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

Collaborator

smaug---- commented Jun 18, 2017

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

@zcorpan

This comment has been minimized.

Show comment
Hide comment
@zcorpan

zcorpan Jun 19, 2017

Member

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

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish Jun 19, 2017

Contributor

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

Contributor

jihyerish commented Jun 19, 2017

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

@rniwa

This comment has been minimized.

Show comment
Hide comment
@rniwa

rniwa Jun 26, 2017

Collaborator

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

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish Jun 27, 2017

Contributor

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.

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

This comment has been minimized.

Show comment
Hide comment
@RByers

RByers 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?

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish Jul 26, 2017

Contributor

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)

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

This comment has been minimized.

Show comment
Hide comment
@jihyerish

jihyerish Jul 27, 2017

Contributor

@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

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

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Oct 26, 2017

Member

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:

  • Wait to see how libraries develop on top of our new primitive, and what features they really want.
  • Fix the interop situation on current scroll-on-focus behavior, so we can figure out what the API shape looks like (e.g. what the default values are for each dictionary member). @zcorpan filed a bunch of browser bugs to discuss this at w3c/csswg-drafts#1805 (comment) .

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

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:

  • Wait to see how libraries develop on top of our new primitive, and what features they really want.
  • Fix the interop situation on current scroll-on-focus behavior, so we can figure out what the API shape looks like (e.g. what the default values are for each dictionary member). @zcorpan filed a bunch of browser bugs to discuss this at w3c/csswg-drafts#1805 (comment) .

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment