How to overlay content on react leaflet (z-index problem)
Asked Answered
M

6

6

Really tried to not post this as I've seen similar questions but I'm not able to display anything over the react leaflet library after reading things online.

The following code snippets show the markup for the map and the overlay I'm trying to produce.

Many thanks, any help appreciated.

Looking at other questions online people refer to making the Map container position: absolute and setting the z-index to 400+ which doesn't seem to make a difference for me with the markup below.

Map markup

              <Map
                zoomControl={false}
                doubleClickZoom= {false}
                closePopupOnClick= {false} 
                dragging= {false}
                zoomSnap= {false} 
                zoomDelta= {false} 
                trackResize= {false}
                scrollWheelZoom= {false}
                touchZoom={false}
                className="map"
                worldCopyJump={true}
                center={position}
                zoom={this.state.zoom}>

                <TileLayer
                  attribution="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors and Chat location by Iconika from the Noun Project"
                  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />

                {this.state.pins.map(pin => (
                  <Marker
                    onClick={() => this.showPanel(pin)}
                    key={pin._id}
                    position={[pin.latitude, pin.longitude]}
                    icon={pinIcon}>
                  </Marker>
                ))}

              </Map>

Overlay markup

  <div ref={ref => this.el = ref}>
            <button onClick={() => this.setState({ isPaneOpen: true })}>Click me to open right pane!</button>


            <SlidingPane
                className='some-custom-class'
                overlayClassName='some-custom-overlay-class'
                isOpen={ this.state.isPaneOpen }
                title='Hey, it is optional pane title.  I can be React component too.'
                subtitle='Optional subtitle.'
                onRequestClose={ () => {
                    // triggered on "<" on left top click or on outside click
                    this.setState({ isPaneOpen: false });
                } }>
                <div className="container-fluid padding">
                </div>
             </SlidingPane>

Update

I have now moved the overlay into a function, shown below

function MyOverLay(props) {
  return <SlidingPane
      className='some-custom-class'
      overlayClassName='some-custom-overlay-class'
      isOpen={ props.isPaneOpen }
      title='Book here
  </SlidingPane>
}

The change in the markup is shown below

New markup

<div>

        <MyOverLay isPaneOpen={this.state.isPaneOpen} />

          <div className="container-fluid padding">

            <div className="row padding">

              <div className="col-lg-8">

                <Map zoomControl={false}
                doubleClickZoom= {false}
                closePopupOnClick= {false} 
                dragging= {false}
                zoomSnap= {false} 
                zoomDelta= {false} 
                trackResize= {false}
                scrollWheelZoom= {false}
                touchZoom={false}
                className="map"
                worldCopyJump={true}
                center={position}
                zoom="13">
                <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
                <Marker
                    position={[10, -10]}
                    icon={messageIcon}>
                </Marker>
            </Map>

          </div>
Marozik answered 22/3, 2019 at 0:30 Comment(0)
P
12

this is the perfect answer

.leaflet-control { z-index: 0 !important}
.leaflet-pane { z-index: 0 !important}
.leaflet-top, .leaflet-bottom {z-index: 0 !important}
Pseudohemophilia answered 22/7, 2022 at 16:50 Comment(2)
Where should we place this snippet in the code?Kahle
Perfect indeed!! Thanks, Hassan!Buckle
S
1

The solution I can only think is the use of React Portal. It's a feature of React that can append a component outside the "root" component inside the body element. Considering that element children in the lower part of the parent has higher stacking index than those in the higher part, it can "overlay" any component inside the root component. Try wrapping your component like this:

import React from 'react';
import ReactDOM from 'react-dom';

const OverlayComponent = () => {
   return ReactDOM.createPortal(
      <MyComponent />,
      document.body
   );
};
Seato answered 22/3, 2019 at 0:57 Comment(4)
Makes sense but I'll have to do some reading as I'm learning react so I'm not sure where to put thisMarozik
I've updated my question with my attempt although the MyOverLay still displays behind the map.Marozik
It's definitely the tiles causing the problem, if I just have the <map> element but remove the <TileLayer> tag my overlay works.Marozik
Think I got it with CSS, let me checkMarozik
D
1

just had the same Problem. For anyone still looking for an answer - The highest z-index on leaftlet-react is for the zoom buttons and is

.leaflet-top, .leaflet-bottom 
{
    position: absolute;
    z-index: 1000;
    pointer-events: none;
}

so if you go above you can show the element in front of the map. Cheers

Demilitarize answered 28/4, 2022 at 13:23 Comment(0)
M
0

Managed to get it working by controlling the z-index values within the CSS for all the panels the map renders on the page. The zIndex option available on the TileLayer doesn't seem to work for me but the following resolved the issue. Noticed - have tested this in Chrome only.

div.map.leaflet-container.leaflet-touch.leaflet-retina.leaflet-fade-anim {
    /*border: 5px solid red;*/
    z-index: 1;
}

div.slide-pane__content {
    /*border: 5px solid black;*/
    z-index: 100;
}

div.ReactModal__Content.ReactModal__Content--after-open.slide-pane.slide-pane_from_right.some-custom-class {
    /*border: 5px solid orange;*/
    z-index: 100;
}

div.slide-pane__header {
    /*border: 5px solid orange;*/
    z-index: 100;
}

div.ReactModal__Overlay.ReactModal__Overlay--after-open.slide-pane__overlay.some-custom-overlay-class {
    /*border: 5px solid blue;*/
    z-index: 100;

}
Marozik answered 22/3, 2019 at 14:25 Comment(0)
B
0

Simple answer, test with MapContainer but not with Map

<MapContainer
    ...other props
    style={{ zIndex: 0 }}
>

To ensure other components overlay the MapContainer, you should set their z-index values to 1 or higher. This technique leverages the CSS stacking context, where a parent container's z-index influences its children, making it a reliable method to manage the visual stacking order of your components.

Keep in mind, for z-index to work as expected, the elements involved must be positioned (i.e., their position property set to anything other than static, such as relative, absolute, or fixed).

Blister answered 21/2 at 16:6 Comment(0)
C
0

I found it easiest and most explicit to use Panes: https://react-leaflet.js.org/docs/example-panes/

Just put your layer in a different <Pane>, then add zIndex style:

<Pane style={{zIndex: 1}}>
  // layer(s) here
</Pane>
Colvert answered 18/8 at 10:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.