Leaflet: Chrome scrolls to reveal full map when user clicks a zoom button

Created on 4 Jan 2016  ·  18Comments  ·  Source: Leaflet/Leaflet

I don't know if it's a bug, but I couldn't find how to prevent browser's scroll change position when I'm using the zoom buttons on the map

Steps:

1.- Draw a map in a container with a height higher than the browsers window. Add control zoom
"new L.Control.Zoom({position: 'bottomleft'}).addTo(map); " .

2.- Click any zoom buttom.

a) Before click (the image not include the site's header) :
scrollcurrentposition

b) After click:

scrollmovedposiotion

As you can see the position of the scroll change, how could I prevent this behavior?

(I would like to prevent any movement on browser's scroll, because the top menu is lost)

jsFiddle example

Most helpful comment

Hi @justynabukiel,

As explained by @yohanboniface above, this is a specific behaviour of Chrome / Chromium browser (not specific to Leaflet) when an Element is focused, whether programmatically (as done by Leaflet) or through Tab key press: Chrome will scroll to make the Element fully visible (or to its top, in case it is bigger than the window view port), even if it is already partially visible.
Whereas other browsers will scroll only if the Element is not visible at all.

New example without Leaflet, since Leaflet Playground no longer exists:
https://plnkr.co/edit/1ur8n20eU2obylzZMetp?p=preview

As said by @yohanboniface, having Leaflet focus to the map container when a user presses a Control seems a legitimate behaviour. Therefore I do not think we can easily remove that behaviour unfortunately.

However, if you _absolutely_ want to get rid of that behaviour in your app, you can easily customize the Leaflet Controls as a workaround, as suggested by @volkanunsal:

Override the following piece:

https://github.com/Leaflet/Leaflet/blob/1ac320ba232cb85b73ac81f3d82780c9d07f0d4e/src/control/Control.js#L103-L108

…using:

L.Control.include({
  _refocusOnMap: L.Util.falseFn // Do nothing.
});

Example: https://plnkr.co/edit/B80cjCYtWUys7Lr9jnDk?p=preview

All 18 comments

Can you try the Leaflet beta or master version? Probably a duplicate of #1228.

Ok, thanks.

I'm going to check it.

Also seeing this issue. I tried it on 0.7.7 and 1.0.0-beta.2.rc.2.

Looks like this line is what is scrolling the page:

_map.getContainer().focus();

Yup, I removed this line from the zoom control and that fixed it:

.on(link, 'click', this._refocusOnMap, context);

@volkanunsal thanks for the investigation!
Can you provide a minimal test case to reproduce the issue? The jsfiddle up there seems broken, and even fixing it I don't reproduce.
Also, can you tell which browser and OS are you using (with versions)?

@yohanboniface I reproduced it here. The trick is to have the map container at 100% height and some height to the page –– enough that the scroll is showing. You also need to wait until the map to finish loading before triggering _onRefocus.

(Correction: I thought it only happened once, but it's actually happening at every zoom click.)

OK, I can reproduce now.
For reference: only reproducing with Chromium, not with FF.

Seems related to presence of not of tabindex. Pressing "TAB" key while in the map iframe will result in the exact same behaviour.
Scrolling when the focused element is out of viewport seems legit and all browsers seem to do that, but scrolling the focus element to the top of the viewport even when this element is already visible seems a bit weird to me. Can't arbitrate from the specs.
Reproduced without any Leaflet bit around: http://playground-leaflet.rhcloud.com/sud/edit?html,output

Just writing to confirm we have this same issue. The map is underneath our clients header, and taller than my browser window. In Chrome, clicking Zoom causes the Ui to scroll to the top of the map's containing div. In Safari, it works as expected, with no scrolling.

Ive noticed that if I alter the browser zoom to bring the map entirely on screen this behavior stops. If I increase zoom just enough so that the bottom edge of the map is cut off at the bottom by the browser window, clicking the zoom scrolls the UI downward just enough to bring the bottom edge on screen.

I experience the same problem in an iframed map using my iphone.
But the problem here is trigged whenyou click att the map not just the zoom buttons.
Here is a test case
iframeTest2.html.zip

Any update on this issue? I have the same problem.

Hi @justynabukiel,

As explained by @yohanboniface above, this is a specific behaviour of Chrome / Chromium browser (not specific to Leaflet) when an Element is focused, whether programmatically (as done by Leaflet) or through Tab key press: Chrome will scroll to make the Element fully visible (or to its top, in case it is bigger than the window view port), even if it is already partially visible.
Whereas other browsers will scroll only if the Element is not visible at all.

New example without Leaflet, since Leaflet Playground no longer exists:
https://plnkr.co/edit/1ur8n20eU2obylzZMetp?p=preview

As said by @yohanboniface, having Leaflet focus to the map container when a user presses a Control seems a legitimate behaviour. Therefore I do not think we can easily remove that behaviour unfortunately.

However, if you _absolutely_ want to get rid of that behaviour in your app, you can easily customize the Leaflet Controls as a workaround, as suggested by @volkanunsal:

Override the following piece:

https://github.com/Leaflet/Leaflet/blob/1ac320ba232cb85b73ac81f3d82780c9d07f0d4e/src/control/Control.js#L103-L108

…using:

L.Control.include({
  _refocusOnMap: L.Util.falseFn // Do nothing.
});

Example: https://plnkr.co/edit/B80cjCYtWUys7Lr9jnDk?p=preview

Confirmed, @ghybs workaround does fix the problem. I came to this via ember-leaflet. For those who are having this issue in Ember you can do the following:

// app/initializers/leaflet-scroll-fix.js
import Ember from 'ember';
import { L } from 'ember-leaflet';

export function initialize(container, app = container) {
  // This will prevent the awkward scroll bug produced by Chrome browsers
  // https://github.com/Leaflet/Leaflet/issues/4125#issuecomment-356289643
  L.Control.include({
    _refocusOnMap: L.Util.falseFn // Do nothing.
  });
}

export default {
  name: 'leaflet-scroll-fix',
  initialize
};

in leaflet.js check
_refocusOnMap: function () { this._map && this._map.getContainer().focus() }
and comment this._map && this._map.getContainer().focus() }
Just like below:
_refocusOnMap: function () { /*this._map && this._map.getContainer().focus()*/ }
And the problem will be solved.

I would classify any library that requires its users to fork and edit the source to make it work likely a bug in the library itself. But maybe that is just me.

But the workaround pretend is either edit the source or monkey patch it out of there.

Hi @sukima,

requires its users to fork and edit the source

As you realized yourself, the above workarounds (including yours) show that editing the source is unnecessary, unlike what @duwizerak suggests.

to make it work

To implement which behaviour?
As previously pointed out, both Chrome and other browsers behaviour are compliant with the standard.

While I can certainly understand that users may be disturbed by the browser scroll suddenly changing when they start using the map, we can also argue that, from a UI perspective, if your users start using the map while it is not entirely scrolled into the browser viewport yet, it probably means that it does not need to be that big. You can style it so that its height fits the initial view, minus some headers, typically in CSS using vh unit and calc, or JS.

Therefore it seems to me that everything works as intended here.
The "intended" is different unfortunately in the case of Chrome, but that is not specific to Leaflet. They could say "_it is a feature, not a bug_".
I can understand that you do not like this discrepancy, in which case I encourage you to raise an issue on Chrome, or push for a more explicit standard.

Now I can also imagine someone building a plugin that would smoothly scroll the map into view, so that users feel less disturbance, while retaining the Chrome rationale for implementing the standard that way.

Another possible solution would be to make it possible to turn off Leaflet refocusing on map, maybe through a control or map option, or a global flag. PR welcome!
I do not know however what could be the consequences regarding accessibility when using such option (and current workarounds).

Another possible solution would be to make it possible to turn off Leaflet refocusing on map, maybe through a control or map option, or a global flag.

I believe this is the essence of this bug. Not that Chome does something weird but that Leaflet does not allow its consumers to opt-out of this feature without monkey patching or maintaining their own patches.

I had the same problem.
It was caused by a <a href="#"></a> being executed on the click event of the zoom button.
Removing it solved the problem.

Was this page helpful?
0 / 5 - 0 ratings