Open RByers opened 8 years ago
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.
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).
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.
"No scrolling" option is also necessary. There is such use case.
What is the use case?
Suppose that multiple-tabs like UI, and a scrollable tab has a focusable element. Let's call it "Tab-A".
We'd like to do this in DevTools console tab of Google Chrome.
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).
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).
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,
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?
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"
}
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 https://github.com/w3c/csswg-drafts/issues/1388.
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?
@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?
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.
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.
Looks reasonable to me.
Filed https://bugzilla.mozilla.org/show_bug.cgi?id=1374045 Need to have proper spec before implementation work.
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
Yes, I'd like to upload a PR. Thank you! : )
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
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.
@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?
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)
@RByers In the past, while adding "center" to ScrollLogicalPosition in CSSOM(see: https://github.com/w3c/csswg-drafts/pull/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
Hmm, I didn't mean to close this completely. Let me reopen. @zcorpan summarized the route we ended up taking in #2787 in https://github.com/w3c/csswg-drafts/pull/1805#issuecomment-337801758 .
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.
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()
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
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. Perhapsfocus
should take an optional ScrollBehavior like Element.scrollIntoView now does?