Skip to content

Support cross-window rendering (container in different window context) #6964

@Syncret

Description

@Syncret

User Story

As a web developer, I can render a MapLibre map into a popup window while keeping the JavaScript context in the main window, so that I can build "pop-out" features with shared application state.

Rationale

Why is this feature needed?

Modern web applications implement "pop-out" features that allow users to open content in separate windows while maintaining shared state. This is achieved using window.open('about:blank') combined with ReactDOM.createPortal() or direct DOM manipulation, where JS runs in the main window but UI renders into the popup's DOM.

Currently, MapLibre fails in this scenario because it uses window-scoped globals (window, document, instanceof HTMLElement, instanceof MouseEvent) that don't work across window contexts.

Example use cases

  • Multi-window web applications: Trading platforms, analytics dashboards, or collaboration tools where users can pop out widgets to secondary monitors
  • Electron/Tauri/WebView-based desktop apps: Desktop applications built with web technologies often need to support multiple windows sharing the same JS context
  • Picture-in-picture style features: Detachable map panels that float independently while staying connected to the main application
  • Kiosk and digital signage: Multi-display setups where a single application drives content across multiple screens/windows

Can it be done today? Is there a workaround?

No viable workaround exists.

The only alternative is to load MapLibre separately in the popup window, but this:

  • Breaks shared state with the main application
  • Requires duplicating the library and styles
  • Prevents React portal patterns that many apps rely on
  • Adds complexity for cross-window communication (postMessage, etc.)

Impact

What if we do nothing?

Developers building multi-window web applications cannot use MapLibre for pop-out features. They must either:

  1. Abandon the pop-out pattern for map-containing components
  2. Use a different map library that supports cross-window rendering
  3. Maintain a custom fork of MapLibre with cross-window fixes

This limits MapLibre's adoption in enterprise web applications and Electron/WebView-based desktop apps where multi-window support is a common requirement.


Minimal Reproduction

Save as HTML and open in browser. Click the button to open a map in a popup window.

<!DOCTYPE html>
<html>
<head>
    <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>
</head>
<body>
    <button onclick="openMapInPopup()">Open Map in Popup Window</button>
    <script>
        function openMapInPopup() {
            const popup = window.open('about:blank', '_blank', 'width=800,height=600');
            popup.document.write(`
                <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/maplibre-gl.css">
                <div id="map" style="width:100%;height:100%"></div>
            `);
            popup.document.close();

            // Container is in popup, but MapLibre JS runs in main window
            new maplibregl.Map({
                container: popup.document.getElementById('map'),
                style: 'https://demotiles.maplibre.org/style.json',
            });
        }
    </script>
</body>
</html>

Symptoms:

  1. Map fails to render. Console shows: Uncaught Error: Invalid type: 'container' must be a String or HTMLElement.
  2. Even after bypassing the container validation, the map renders but does not respond to any mouse or keyboard events.

Proposed Implementation

Derive ownerDocument and ownerWindow from the container element instead of using globals:

  1. Use container.ownerDocument and ownerDocument.defaultView instead of global document/window
  2. Bind document/window-level events to the container's ownerDocument/ownerWindow
  3. Use duck typing for event detection instead of instanceof
  4. Pass ownerWindow to requestAnimationFrame() and ResizeObserver

I have a working implementation and would be happy to submit a PR.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions