Custom ordering/z-index of icons in Leaflet layer

Until somebody finds a better solution, here what I would do ...

As you noticed, leaflet is using pixel position to set zIndex (in Marker.js)

pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
this._zIndex = pos.y + this.options.zIndexOffset;

What I suggest is to undo leaflet zIndex using setZIndexOffset()

Say you want to set zIndex = 100, you would do

var pos = map.latLngToLayerPoint(marker.getLatLng()).round();
marker.setZIndexOffset(100 - pos.y);

There is a bit of a glitch: you have to do it every time the map is zoomed :(

Here is a JSFiddle example (comment the code in adjustZindex() to see the difference)


The current version of leaflet (as of early 2017) has a zIndexOffset property with default = 0 that can be set to atler the z-index of a marker. http://leafletjs.com/reference.html#marker-zindexoffset Works fine with zooming and everthing.


This plugin will do the trick: leaflet.forceZIndex.js

// Force zIndex of Leaflet
(function(global){
  var MarkerMixin = {
    _updateZIndex: function (offset) {
      this._icon.style.zIndex = this.options.forceZIndex ? (this.options.forceZIndex + (this.options.zIndexOffset || 0)) : (this._zIndex + offset);
    },
    setForceZIndex: function(forceZIndex) {
      this.options.forceZIndex = forceZIndex ? forceZIndex : null;
    }
  };
  if (global) global.include(MarkerMixin);
})(L.Marker);

To use:

var aMarker = L.marker([lat, lon], {
    icon: icon,
    title: title,
    forceZIndex: <Value> // This is forceZIndex value
})

forceZIndex declaration will assure that ZIndex will be always set from aMarker.options.forceZIndex

Update it somewhere to re-force ZIndex value

aMarker.setForceZIndex(<New Value>)

Or setForceZIndex(null) to automatical zIndex state:

aMarker.setForceZIndex(null);

By the end of the day, if no forceZIndex option declared, Marker will work with normal behaviour.