I am currently working with Leaflet and Mapbox to create a custom map. All has been working fine until I started to work on the popups.
My situation: I have a custom navigation/control panel that will be used but it needs to be behind any open popups (which it currently is not).
I have prepared a JSFiddle and this screenshot
Part of my CSS is
#map-nav {
position: absolute;
left: 10px;
top: 10px;
z-index: 2;
}
.leaflet-popup-pane, .leaflet-popup {
z-index: 1000 !important;
}
The default leaflet classes have z-index
of 7 (I think), I just overwrote it to be 100% sure. When inspecting the code in browser (FF/Chrome), I see that the z-index is set properly and no other element in the .leaflet-popup
has any z-index
set.
I have read that negative z-index
may solve this, but as I am working with multiple elements I'd really much like a less "hacky" solution - if there is one. (JavaScript solutions are welcome as well, hence the tag)
As I can see from the code inspection, Leaflet sets some attributes to .leaflet-popup
which in terms of position are: transform: translate3d(..)
, bottom
and left
.
Any help is appreciated.
Edit:
I can put the #map-nav
inside #map-content
and it still won't work fiddle. However, when I try to imitate this without alle the map stuff, it does work.
You set z-index on a static element By default, every element has a position of static. z-index only works on positioned elements (relative, absolute, fixed, sticky) so if you set a z-index on an element with a static position, it won't work.
To sum up, most issues with z-index can be solved by following these two guidelines: Check that the elements have their position set and z-index numbers in the correct order. Make sure that you don't have parent elements limiting the z-index level of their children.
Definition and Usage An element with greater stack order is always in front of an element with a lower stack order. Note: z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky) and flex items (elements that are direct children of display:flex elements).
The problem is that #map-nav
exists in an entirely different stacking context than the marker and its popup.
The way you have it set up right now, the entire map is behind #map-nav
. So, changing the z-index on either #map-nav
or the .leaflet-popup-pane
won't really help.
Disclaimer: This is a terrible, terrible hack. If you look into Leaflet's documentation and find a way to add your own widgets, I'd highly recommend doing that instead of this.
That said, I have something which sort of works (your mileage may vary):
#map-nav
into .leaflet-map-pane
MutationObserver
and observe changes to the attributes of .leaflet-map-pane
.style
attribute of .leaflet-map-pane
changes, grab its style.transform
property and extract the x and y values. Invert those values and apply them to #map-nav
.var map = L.map('map-content', {
zoomControl: false
}).setView([51.505, -0.09], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
maxZoom: 18,
id: 'rauschundrausch.cih3gisks00r8rlly0ob5s2me',
accessToken: 'pk.eyJ1IjoicmF1c2NodW5kcmF1c2NoIiwiYSI6ImNpaTYyeW14MTAwNml2eW0zcmR6aHIzdDcifQ.6T8nzYq49rFnvcqk6lgYPg'
}).addTo(map);
var marker = L.marker([51.5, -0.09]).addTo(map);
marker.bindPopup("this is a<br>large<br>popup<br>in<br>terms of height");
var mapNav = document.getElementById("map-nav");
var mapPane = document.querySelector(".leaflet-map-pane");
var rxTranslate = /translate(?:3d)?\(([^\)]+)\)/i;
mapPane.appendChild(mapNav);
var observer = new MutationObserver(function(mutations) {
if (mutations.some(m => m.attributeName === "style")) {
// apply an inverse transform
mapNav.style.transform = "translate(" + mapPane
.style
.transform
.match(rxTranslate)[1]
.split(",")
.slice(0, 2) /* extract only x and y; discard z */
.map(n => parseFloat(n) * -1 + "px") /* invert values */ + ")";
}
});
observer.observe(mapPane, {
attributes: true
});
#map {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#map-nav {
position: absolute;
left: 10px;
top: 10px;
width: 100px;
height: 100px;
background-color: #ccc;
z-index: 200;
box-shadow: inset 0 0 0 1px #f00;
}
#map-content {
width: 100%;
height: 100%;
}
.leaflet-popup-pane {
z-index: 3;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<div id="map">
<div id="map-content">
<div id="map-nav"></div>
</div>
</div>
This may lag on some clients while dragging. You could use a timeout to defer the update but that would mean the nav menu would move around until you stop dragging.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With