55

I want to place the zoom control in middle right of the the map i.e. in the middle of the right most side of the map. I have found solution to put the zoom control in different corners using the following code

var map = new L.map("map-container",{ zoomControl: false });

   new L.Control.Zoom({ position: 'topleft' }).addTo(map);

So the positions can be

topleft
topright
bottomleft
bottomright

But my goal is to put the control window in the middle right. Or even I put the control in the corner I want to add some margin to the top. How can I do that? Is there any idea?

Md Johirul Islam
  • 5,042
  • 4
  • 23
  • 56

8 Answers8

58

Simplest and Accurate

var map = L.map('map', {
    maxZoom: 20,
    minZoom: 6,
    zoomControl: false
});

L.control.zoom({
    position: 'bottomright'
}).addTo(map);

enter image description here

Bruno Peres
  • 2,980
  • 1
  • 21
  • 19
saadat ali
  • 925
  • 9
  • 17
  • 1
    this adds second zoom controls. – Damjan Pavlica Jun 24 '19 at 10:55
  • 2
    No, You have to turn off the default zoom control. var map = L.map('map', { maxZoom: 20, minZoom: 6, zoomControl: false }); this zoomControl: false will disable the default zoom and then L.control.zoom({ position: 'bottomright' }).addTo(map); This adds the new control at your specified position. – saadat ali Jun 25 '19 at 11:38
  • 2
    For some reason the `zoomControl: false` didn't work. Not sure why - possibly a bug? Anyway I added the code `map.zoomControl.remove();` before adding the new zoom control. – Steve Mc Mar 22 '20 at 11:22
45

We can create additional Control placeholder(s), besides the 4 provided corners by default.

A nice advantage is that it allows putting several Controls in one of those placeholders. They will stack without overlapping, as in the standard corners.

JavaScript:

// Create additional Control placeholders
function addControlPlaceholders(map) {
    var corners = map._controlCorners,
        l = 'leaflet-',
        container = map._controlContainer;

    function createCorner(vSide, hSide) {
        var className = l + vSide + ' ' + l + hSide;

        corners[vSide + hSide] = L.DomUtil.create('div', className, container);
    }

    createCorner('verticalcenter', 'left');
    createCorner('verticalcenter', 'right');
}
addControlPlaceholders(map);

// Change the position of the Zoom Control to a newly created placeholder.
map.zoomControl.setPosition('verticalcenterright');

// You can also put other controls in the same placeholder.
L.control.scale({position: 'verticalcenterright'}).addTo(map);

Then it becomes easy styling those placeholders with CSS, because their DOM parent is the map container itself. Hence top, bottom, left and right can be specified with percentages (which use the parent's dimensions).

CSS:

.leaflet-verticalcenter {
    position: absolute;
    z-index: 1000;
    pointer-events: none;
    top: 50%; /* possible because the placeholder's parent is the map */
    transform: translateY(-50%); /* using the CSS3 Transform technique */
    padding-top: 10px;
}

.leaflet-verticalcenter .leaflet-control {
    margin-bottom: 10px;
}

As for vertical centering the placeholder itself, you can use your favourite technique. Here I used the CSS3 Transform to offset the placeholder by half of its own height.

If necessary (e.g. for old browsers compatibility), you can rather use a "calculate-on-load" method to perform this offset, similar to iH8's answer. But you no longer need to run it on map resize, only when adding new Control(s) to the placeholder.

Live demo: https://plnkr.co/edit/bHJwfm598d1Ps7MpLG0k?p=preview

Note: there is currently an open PR (Leaflet/Leaflet #5554) for this, but since it is not compatible with old versions of Internet Explorer, it will not likely be merged in Leaflet core.

ghybs
  • 47,565
  • 6
  • 74
  • 99
  • 2
    For Leaflet 1.0.3, I needed to include the line `z-index: 1000;` in the CSS for leaflet-vertical center. Otherwise, I could click the control but it wasn't visible. Demo: http://jsfiddle.net/ve2huzxw/437/ – user2441511 Jan 30 '17 at 15:09
  • thank you for this solution! it works like a charm on leaflet 1.5.1 too! – Elisabetta Oct 30 '20 at 09:42
14

This can be done a tad easier, with one line of CSS. Works with responsive design (Bootstrap) and moves additional buttons added with Leaflet.EasyButton too.

.leaflet-control-container { position: absolute; right: 56px } 
ow3n
  • 5,974
  • 4
  • 53
  • 51
  • 1
    This is the best and most concise answer imho. Thank you. :) – Felix Gertz Mar 29 '20 at 23:19
  • 1
    Ah! I need to recall. This technique turned out to be very bad without further adjustments. Because it moves the complete container and the including attribution line from the bottom right out of the viewport. So it's hidden then! Be careful. – Felix Gertz Mar 30 '20 at 13:04
  • This is doing the job: .leaflet-control-container .leaflet-top.leaflet-left { position: absolute; left: auto; right: 10px; } – Felix Gertz Mar 30 '20 at 13:10
  • This moves the whole control container, which include all topleft, topright, bottomleft, bottomright classes. I think it's pretty good design to solve this using css rather than using noisy js but in that case it prevent further customization of the controler pane. As an example, if the developer wants to put the layer control on the left and zoom control on the right – Simon Mulquin Oct 21 '22 at 14:47
8

this worked for me

var map = new L.map("map-container",{ zoomControl: false });

L.control.zoom({ position: 'topright' }).addTo(map);
  • 5
    Welcome to StackOverflow! Please [edit your question](https://stackoverflow.com/posts/58808432/edit) to include an explanation of your code, and justify why it's as good as or better than the other five answers. This question is *four years old* and already has an accepted answer. Answers without explanations on questions like these will tend to get downvoted or deleted. – Das_Geek Nov 11 '19 at 21:17
7

Grab the map's container height, divide by two. Subtract the zoom's container height, divided by two. Use absolute positioning and assign the top position:

var mapHalfHeight = map.getSize().y / 2,
    container = map.zoomControl.getContainer(),
    containerHalfHeight = parseInt(container.offsetHeight / 2),
    containerTop = mapHalfHeight - containerHalfHeight + 'px';

container.style.position = 'absolute';
container.style.top = containerTop;

Example on Plunker: http://plnkr.co/edit/Yg8phGDcCBS1IlGgpKa2?p=preview

Note that when you're not using a fixed size map container that you'll need to do this every time the map's container get resized. Throw it in a method and hook it up to the map's resize event as in the supplied example.

iH8
  • 27,722
  • 4
  • 67
  • 76
7

After you initialized map:

map.zoomControl.setPosition('bottomright');

Here is the documentation

The position of the control (one of the map corners). Possible values are 'topleft', 'topright', 'bottomleft' or 'bottomright'

As you see "Options inherited from Control"

And here is all methods from Control class:

getPosition()
setPosition(<string> position)
getContainer()
addTo(<Map> map)
remove()
lendoo
  • 332
  • 4
  • 5
  • this seems the only correct solution to me according to the documentation. Overriding CSS is very un-intuitive. The other solutions are creating unnecessary boilerplate, e.g. having to unset the default zoom to recreate it on the desired position is not smart imho. Thanks for sharing – GBra 4.669 Aug 26 '22 at 10:26
3

If your map is not complicated, the easiest way is to use CSS.

In your case, you can just add following CSS:

.leaflet-top {
bottom: 0;
}

.leaflet-top .leaflet-control-zoom {
top:50%;
transform: translateY(-50%);
}
Jack J
  • 181
  • 1
  • 7
  • To center it perfectly add `margin-top: 0` : `.leaflet-top .leaflet-control-zoom { top: 50%; transform: translateY(-50%); margin-top: 0 }` – DevDavid Mar 23 '20 at 17:23
0

I needed a new Position for the zoom control like middleleft, So

1- Clone the Leaflet repository

2- In dist/leaflet.css add

.leaflet-middle,
.leaflet-top,
.leaflet-bottom {
  position: absolute;
  z-index: 1000;
  pointer-events: none;
}
.leaflet-middle{
  top: 50%;
}
.leaflet-middle .leaflet-control {
  margin-top: 5px;
}

3- In src/control/Control.js Add

createCorner('bottom', 'right');
createCorner('middle', 'left');
createCorner('middle', 'right');

then

npm install && npm run build

In your script to initiate the map use,

L.control.zoom({  position: 'middleleft' }).addTo(map);
rahram
  • 560
  • 1
  • 7
  • 21