z-index not functioning properly

Currently, I'm diving into the world of custom map creation using Leaflet and Mapbox. Everything was going smoothly until I encountered a challenge with the popups.

Here's the issue: I have a unique navigation/control panel that I want to display behind any open popups, but it's not working as intended.

To visualize the problem, I've set up a JSFiddle and included a screenshot:

https://i.sstatic.net/qsxYn.jpg

Here is a snippet of my CSS:

#map-nav {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 2;
}
.leaflet-popup-pane, .leaflet-popup {
  z-index: 1000 !important;
}

While inspecting the code in Firefox/Chrome, I noticed that the z-index is correctly set, and there are no conflicting z-index values in the .leaflet-popup element.

I've heard that using a negative z-index might fix this issue, but I'm looking for a more elegant solution that doesn't feel like a hack. JavaScript solutions are welcome as well.

Upon inspection, Leaflet applies attributes like transform: translate3d(..), bottom, and left to .leaflet-popup in terms of positioning.

Any assistance on this matter would be greatly appreciated.

Edit:

Even when I nest the #map-nav inside #map-content, the issue persists. Here's a fiddle illustrating this. However, when I attempt a similar setup without the map elements, it works.

Answer №1

The issue arises from the fact that #map-nav is situated in a completely separate stacking context compared to the marker and its popup.

As it stands, the entirety of the map is positioned behind #map-nav. Therefore, adjusting the z-index on either #map-nav or the .leaflet-popup-pane will not provide a solution.

Disclaimer: Resorting to this method is not ideal. It is recommended to explore Leaflet's documentation and implement custom widgets instead of resorting to this workaround.

Nevertheless, I have devised a somewhat functional approach (results may vary):

  1. Relocate #map-nav within .leaflet-map-pane
  2. Set up a MutationObserver to monitor changes to the attributes of .leaflet-map-pane.
  3. Whenever the style attribute of .leaflet-map-pane changes, extract the x and y values from its style.transform property, 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 &copy; <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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a3cfc6c2c5cfc6d7e3928d908d92">[email protected]</a>/dist/leaflet.css" />
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="412d2420272d243501706f726f70">[email protected]</a>/dist/leaflet.js"></script>
<div id="map">
  <div id="map-content">
    <div id="map-nav"></div>
  </div>
</div>

There might be performance issues on certain devices during dragging. Utilizing a timeout to delay the update could mitigate this, but it may cause the navigation menu to shift until dragging ceases.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Implementing a delay between two div elements using jQuery

I have two Divs with the class "sliced", each containing three images with the class "tile". When I animate using jQuery, I am unable to add a delay between the "sliced" classes. However, I have successfully added a delay between the "tile" classes. index ...

Eliminate missing values from geospatial dataset

Struggling to remove NAs from a "SpatialPolygonsDataFrame". Traditional data frame approaches and subsetting methods have proven ineffective in this case. Even attempts to eliminate NAs as one would for a regular data frame have failed. The solutions that ...

Button click not triggering Ajax functionality

I've been working on implementing a simple Ajax function in a JSP using JQueryUI. The goal is to pass two text fields from a form and use them to populate two separate divs. However, when I click the button, nothing seems to be happening. I even tried ...

Changing the size of an image in an HTML5 canvas

I have been attempting to generate a thumbnail image on the client side using Javascript and a canvas element. However, when I reduce the size of the image, it appears distorted. It seems as though the resizing is being done with 'Nearest Neighbor&apo ...

Interface key error caused by the TypeScript template literal

Version 4.4.3 of Typescript Demo Playground Example -- interface IDocument { [added_: `added_${string}`]: number[] | undefined; } const id = 'id'; const document: IDocument = { [`added_${id}`]: [1970] } My Attempts: I made sure that id in ...

Utilizing React, manipulating the DOM by utilizing getElementById, and then attempting to swap out a node with a React Component

Is there a method to replace a DOM node with a ReactJS node? If so, how can it be achieved? const myComp = <span>hey</span> const elem = document.getElementById('video1') elem.parentNode.replaceChild(myComp, elem) What is the correc ...

Comparing the syntax of JSON to the switch statement in JavaScript

I recently came across a fascinating post on discussing an innovative approach to utilizing switch statements in JavaScript. Below, I've included a code snippet that demonstrates this alternative method. However, I'm puzzled as to why the alter ...

Deliver varied asset routes depending on express js

I have a situation where I am working with express routes for different brands. My goal is to serve two separate asset directories for each brand route. One directory will be common for all brand routes, located at public/static, and the other will be spec ...

JavaScript influences CSS in EasySlider 1.7, creating a harmonious relationship between the

Struggling to achieve a captivating overlay effect with a slider using EasySlider 1.7, incorporating both images and corresponding text. However, encountering difficulties in aligning the text correctly on the page. The black overlay visible on the main s ...

What is the best way to modify the selection text background with CSS?

Does anyone know the method for modifying the selection text background in CSS? Many modern websites opt for a personalized background color instead of the traditional blue? ...

Inserting duplicate rows from CSV using JavaScript

Currently, I am utilizing Papaparse to sum up rows with duplicate SKUs in my CSV file. I'm striving to achieve this task without the use of additional JS libraries such as D3. Here is a snippet of how my CSV data is structured: SKU,Daily total,Weekly ...

Tips for hiding the bottom bar within a stackNavigator in react-navigation

I am facing a challenge with my navigation setup. I have a simple createBottomTabNavigator where one of the tabs is a createStackNavigator. Within this stack, I have a screen that I want to overlap the tab bar. I attempted to use tabBarVisible: false on th ...

Could one potentially generate new static files in Nextjs without needing to rebuild the entire app?

After recently beginning to utilize NextJs' getStaticProps feature, I have found that the static files generated at build time are quite impressive. However, my content is not static and requires updates without having to rebuild the entire app each t ...

What drawbacks come with developing an Express.js application using TypeScript?

Curious about the potential drawbacks of using TypeScript to write Express.js applications or APIs instead of JavaScript. ...

Having difficulty aligning the container div in the center

I'm trying to create a centered grid of full-width buttons, but for some reason, I just can't seem to get the container centered. Any suggestions? Check out the code here - https://jsfiddle.net/a6qo6tzL/ Thank you! <div class="Wrapper"> ...

search for the compose function in the material table within a react component

When I receive a string array as a response from the API for lookup, it looks like this: ['India', 'Sri Lanka'] I am looking to pass this as a parameter to a Material React table column as a List of Values (LOV) in the following format ...

Having trouble constructing the Grand-Stack-Starter api because babel-node is not being recognized

As I endeavor to create the initial api for the Grand Stack Starter, I encounter difficulties every time I try to execute npm start: >nodemon --exec babel-node src/index.js [nodemon] 1.18.7 [nodemon] to restart at any time, enter `rs` [nodemon] watchi ...

Text positioned beneath a toggle switch in html that overlaps

Is there a way to fix the issue of the label on the left side overlapping below the selector switch on my website? I want to ensure that both labels are perfectly distributed on each side of the switch. Here is the code snippet: <div class="ro ...

Database-driven cron scheduling

How can I set up a cron job to send an email notification using node-mailer about 1 or 2 weeks before the expiration date of a product in my database that includes an expired_date field? ...

Creating Static Content using Spring Framework

I need some help with handling static content in my SpringMVC app. Currently, I am using the following configuration: <mvc:resources mapping="/resources/**" location="/resources/" /> This setup works well for uploading and retrieving images within ...