Gabriel H. Nunes
Gabriel H. Nunes

Reputation: 755

Mapbox GL JS canvas not displaying properly in Bootstrap modal

According to the Mapbox GL JS Quickstart guide, it should be straightforward to implement a map on a website using the Mapbox CDN. Unfortunately, that is not the case if the map is located inside a Bootstrap modal, which does not have a predefined width, a property that is set only after the modal is opened.

The result is a Mapbox canvas loaded with a default width of 400px, which may differ from the modal width and create a terrible user experience.

Also, if one opens the modal and then resizes the browser window, the map automatically fits the whole horizontal space as expected, which seems to be a JavaScript response to a resize event.

Here follows the related code.

HTML file

<div id='map'></div>

CSS file

#map {
  height: 300px;
}

JS file

mapboxgl.accessToken = '...';
var map = new mapboxgl.Map({
    container: 'map',
    center: [..., ...],
    zoom: 10,
    style: 'mapbox://styles/mapbox/streets-v11'
});

I've tried to load Mapbox inside a Bootstrap 3.4.0 modal, as I was previously able to do when using Google Maps or Bing Maps, but in both cases embedded inside an iframe. Therefore, I was expecting to see Mapbox filling the whole modal as Google Maps and Bing Maps did.

Instead, the Mapbox interface (bottom left logo and bottom right info button) was correctly positioned inside the modal, at its borders, but the canvas containing the map was incorrectly positioned.

Finally, setting a predefined width to the #map CSS property is not a solution. If the width is set to a fixed width in pixels, it may not display properly on all window sizes, while adding a fixed percentage width, say 100%, did not do the trick.

Upvotes: 5

Views: 5069

Answers (1)

Gabriel H. Nunes
Gabriel H. Nunes

Reputation: 755

A similar issue has already been solved for the Leaflet JavaScript library here and here.

As it turns out, the lack of a predefined width for the modal leaves Mapbox with no option but to initially load a default width (400px in this case). Because opening the modal does not trigger any event that Mapbox may be listening to, such as the window resizing, Mapbox keeps its default width no matter the size set for the modal once it is displayed.

Therefore, to make the Mapbox canvas to fill the entire width of the modal, one must link the opening of the modal, which will finally set a width to it, to the Mapbox resize method.

The Bootstrap event of interest here is the "shown.bs.modal", which is triggered once the modal has been displayed to the user and the CSS transitions have completed. This guarantees that a width has already been set to the modal.

The solution is to add the following code after the 'map' variable definition in the JS file:

$('#modalID').on('shown.bs.modal', function() {
    map.resize();
  });

Make sure to change 'modalID' to the same 'id' used to identify the respective modal.

Upvotes: 6

Related Questions