Leaflet – How to Fix Popups Immediately Closing on Mobile/Touchscreen Devices

leaflet

I've been building a wiki for golf courses, and I'm now trying to add a map to the homepage. Everything seems to work just fine, unless it's on a touch screen, where, most of the time, but not always, the popups immediately close upon clicking. I have already gone through Leaflet popup immediately closing, but it offers little advice.

The code is live on the site i'm working on: http://www.golfcourse.wiki

The problem exists for me on both on ios and MacOS, firefox and chrome (even in the desktop testing frameworks if touch simulation is turned on. Note comment below: @TomazicM could not replicate on android/windows Chrome browser.

The framework is flask + jinja2, here is the relevant code:

<style>
    body {
        margin: 0;
        padding: 0;
    }
    #map img {
        {# this needs to be added beause somewhere up the chain imgs have padding #}
        padding: 0;
        background: transparent;
    }
    .course_marker {
        border: solid 1px green;
        border-radius: 50%;
    }
    .incomplete_course_marker{
        border: solid 1px green;
        border-radius: 50%;
        filter: saturate(25%);
    }
    .popup,
    .popup_anchor:link
    .popup_anchor:visited {
        color: rgb(var(--light-mode-text-main));
        background: rgb(var(--light-mode-main-main));
    }

    .leaflet-popup-pane {
        padding: 0;
        margin: 0;
    }

    @media (prefers-color-scheme: dark) {
        .leaflet-popup-tip,
        .leaflet-popup-content-wrapper,
        .popup,
        .popup_anchor:link,
        .popup_anchor:visited {
            color: rgb(var(--dark-mode-text-main));
            background: rgb(var(--dark-mode-background-main));
        }
        .popup:hover {
            background:     rgba(var(--color-lighten), 0.6);
        }

    }
</style>
<div id='map'></div>
<script>
    // replace "toner" here with "terrain" or "watercolor"
    let layer = new L.StamenTileLayer("toner-lite", {detectRetina: true});
    let map = new L.Map("map", {
        center: new L.LatLng(
            {{ user_lat_long[0] | float }},
            {{ user_lat_long[1] | float }}
            ),
        zoom: 11,
    });
    map.addLayer(layer);

    let myIcon = L.icon({
        iconUrl: '/favicon.ico',
        iconSize: [25, 25],
        //iconAnchor: [22, 94],
        //popupAnchor: [-3, -76],
        //shadowUrl: 'my-icon-shadow.png',
        //shadowSize: [68, 95],
        //shadowAnchor: [22, 94]
    });

    {% for course in courses %}
        var marker = L.marker(
            [{{ course.index.lat }}, {{ course.index.long }}],
            {icon: myIcon},
        );

        var course_content =
            `
            <section class="popup"
                style="
                    padding: 1px;
                    margin: 0 20px 3px 0;
                ">
                <a  class="popup_anchor"
                    href="${ "{{ url_for('course_page', unique_path=course.unique_path) }}" }"
                    data-button-like="true"
                    data-clickable="true"
                    data-remove-anchor-text-format="main"
                    data-required-child-div-for-text-alignment="true"
                    style="
                        ${ "{% if course.index.incomplete %}opacity: 50%;{%else %}{% endif %}" }
                        border: none;
                    ">
                    <div>${ "{{ course.name}}" }</div>
                    <section
                        style="
                            display: flex;
                            flex-direction: column;
                            font-size: 66%;
                            text-align: left;
                        ">
                        <div>${ "{{ course.facts.city }}" }, ${ "{{ course.facts.country }}" }</div>
                        <div>${ "{{ course.facts.num_holes }}" } Hole, Par ${ "{{ course.handicaps.get(course.index.hardest_handicap_id).par }}" }</div>
                        <div>${ "{{ course.index.longest_tee.total }}" } ${ "{{ course.index.longest_tee.units }}" }</div>
                    </section>
                </a>
            </section>
            `;

        var popup = L.popup({
            setLatLng: marker.getLatLng(),
            closeOnClick: false,
            closeButton: true,
        }).setContent(course_content);

        marker.bindPopup(popup).openPopup();
        marker.addTo(map);
        {% if course.index.incomplete %}
            marker._icon.classList.add("incomplete_course_marker");
        {% else %}
            marker._icon.classList.add("course_marker");
        {% endif %}
    {% endfor %}
</script>

I obviously plan on refactoring the sporadic CSS once it's up and running.

Best Answer

If you think it has something todo with this Github issue then you can try to disable tap in while map creation:

 let map = new L.Map("map", {
        center: new L.LatLng(
            {{ user_lat_long[0] | float }},
            {{ user_lat_long[1] | float }}
            ),
        zoom: 11,
tap: false
    });