Map
Overview
The <x-map> component is the foundational building block for all maps. It initializes MapLibre GL JS, sets up the viewport, and provides the container for all child components like markers, popups, routes, clusters, arcs and GeoJSON layers. Children react to Livewire state: when your component re-renders, they update in place while the map itself is preserved (the map uses wire:ignore.self, so you never need to wrap it in wire:ignore). Until the style has loaded, a loading overlay is shown; you can customise or disable it.
Basic Usage
Tile Providers
Switch between built-in tile providers using the provider prop. You can also supply a custom MapLibre style (a URL or a style array) via the style prop.
| Provider | Description |
|---|---|
| carto-positron | Clean light basemap (default) |
| carto-voyager | Colorful light basemap |
| carto-dark-matter | Dark basemap (the default dark_provider) |
| openfreemap-liberty | OpenFreeMap vector style with 3D building extrusions; pair it with a pitched view |
| openfreemap-bright | OpenFreeMap bright vector style |
| openfreemap-positron | OpenFreeMap minimal light style |
| osm-raster | Standard OpenStreetMap raster tiles |
| blank | Transparent style with no basemap (same as the blank prop) |
Carto Positron (Light)
Carto Dark Matter
OpenFreeMap Liberty
Theme Support
The theme prop controls how the map responds to dark mode. With "auto" (default) the map follows a dark / light class or a data-theme attribute on <html>, swapping styles live and dispatching map:theme-changed. Set follow_system_theme to true in the config to also follow the OS preference when neither is present. Force a theme with "light" / "dark", or switch at runtime with the map:set-theme command.
- Light mode uses provider (or light-style); dark mode uses dark-style, falling back to the configured dark_provider.
- A style (or light-style) applies to both themes unless you also set dark-style.
- Anywhere a style is accepted you can pass a provider key, e.g. dark-style="openfreemap-positron".
Globe Projection
Set projection="globe" to render the world as a sphere at low zoom. MapLibre transitions to a flat map as you zoom in. It pairs well with arcs.
Bounds & Camera
Use :bounds to fit an area when the map loads (instead of :center/:zoom), and :max-bounds to stop users panning away. Bounds are [[west, south], [east, north]]. :zoom accepts floats and 0.
Gesture props such as :drag-rotate, :touch-zoom-rotate, :pitch-with-rotate and :cooperative-gestures (Ctrl/⌘ + scroll to zoom, two fingers to pan on touch) are useful for maps embedded in long pages.
Blank Map
Add :blank="true" for a transparent style with no basemap. Combine it with <x-map-geojson> to build choropleths and diagrams where your data is the whole map.
<x-map :blank="true" :center="[15, 25]" :zoom="0.6"> <x-map-geojson data="https://example.com/countries.geojson" :interactive="true" /> </x-map>
Loading State
Until the map has loaded, a subtle pulsing-dots overlay is shown. It fades out when MapLibre fires load (the map element gets the lm-loaded class). You can replace it, restyle it, or turn it off.
Custom loader
Pass a <x-slot:loading> with any markup. Attributes on the slot (like class) are added to the overlay, which stays centered over the map:
Restyle the default
The default overlay reads these CSS custom properties, so you can theme it without new markup:
.lm-map {
--lm-loader-bg: rgba(255, 255, 255, 0.85); /* overlay background */
--lm-loader-backdrop: none; /* default: blur(2px) */
--lm-loader-color: #0a0a0a; /* dots / text colour */
--lm-loader-dot-size: 0.5rem;
--lm-loader-fade: 0.5s; /* fade-out duration */
}
Disable it
Use :loader="false" on a single map, or set 'loader' => false in config/livewire-mapcn.php to turn it off everywhere (a map can opt back in with :loader="true"). A <x-slot:loading> is always shown, even when the default loader is disabled. Lazy maps that haven't started yet show their loader as a placeholder until they come into view.
MapLibre Options
Anything without a dedicated prop can be passed straight to the MapLibre Map constructor with :options. These are merged last, so they win over the props.
<x-map :options="['hash' => true, 'fadeDuration' => 0, 'maxTileCacheSize' => 200]" :attribution-compact="false" :loader="false" />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| :center | ?array | config | Initial map center [lng, lat] (config default_center) |
| :zoom | int|float|null | config | Initial zoom level, floats and 0 allowed (config default_zoom) |
| :min-zoom | int|float | 0 | Minimum zoom level |
| :max-zoom | int|float | 22 | Maximum zoom level |
| provider | ?string | config | Built-in provider (config default_provider, 'carto-positron') |
| style | array|string|null | null | Custom MapLibre style URL, style array or provider key. Applies to both themes unless dark-style is set |
| light-style | array|string|null | null | Style for light mode |
| dark-style | array|string|null | null | Style for dark mode (falls back to dark_provider) |
| theme | string | 'auto' | 'light', 'dark', or 'auto' |
| projection | ?string | null | 'globe' for a 3D globe, otherwise Mercator |
| :blank | bool | false | Transparent style with no basemap |
| height | int|string|null | config | full (100%), an int (px) or any CSS value, e.g. 320px, 60vh |
| width | int|string | '100%' | CSS width (ints are px) |
| :bearing | int|float | 0 | Initial bearing in degrees |
| :pitch | int|float | 0 | Initial pitch in degrees |
| :max-pitch | int|float|null | null | Maximum pitch |
| :bounds | ?array | null | Fit [[w, s], [e, n]] on load |
| :bounds-padding | int | 40 | Padding (px) for :bounds |
| :max-bounds | ?array | null | Restrict panning to [[w, s], [e, n]] |
| :interactive | bool | true | Enable mouse/touch interactions |
| :scroll-zoom | bool | true | Allow mouse wheel zoom |
| :double-click-zoom | bool | true | Allow double-click zoom |
| :drag-pan | bool | true | Allow panning by drag |
| :drag-rotate | bool | true | Allow rotating with right-click / Ctrl + drag |
| :touch-zoom-rotate | bool | true | Allow pinch zoom and rotate |
| :pitch-with-rotate | bool | true | Allow pitch while rotating |
| :cooperative-gestures | bool | false | Require Ctrl/⌘ + scroll to zoom and two fingers to pan |
| :render-world-copies | bool | true | Repeat the world horizontally when zoomed out |
| :attribution | bool | true | Show the attribution control |
| :attribution-compact | bool | true | Collapse attribution into an info button |
| :loader | ?bool | config loader | Show the default loading overlay until the map has loaded. Use <x-slot:loading> for custom content (Loading State) |
| :events | array | [] | Extra MapLibre event names to forward as map:{event} |
| :options | array | [] | Raw options merged into the MapLibre Map constructor |
| class | string | '' | Additional CSS classes |