Menu

Map

Added in 1.7.0

A map shows places and markers on an interactive world map. Tabler turns a single element into a themed map, and the map itself is rendered by MapLibre GL JS.

Overview

The map component turns an element into an interactive map. Add data-bs-toggle="map" to it, set the center and the zoom with data attributes, and write the markers as child elements. No script is needed.

The map is drawn by MapLibre GL JS, an open-source map library, which you load next to Tabler. The map tiles come from OpenFreeMap. It needs no account and no access token, and it can be used in commercial projects.

If you only need a simple map of countries or regions, use the vector map instead. It makes no network calls at all.

Installation

The map component is not part of tabler.js. It ships as a small add-on, tabler-map.js, so pages without a map do not carry it. Load the MapLibre stylesheet, and the add-on after tabler.js; it adds MapView to the tabler object:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/libs/maplibre-gl/dist/maplibre-gl.css" />
<script src="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/js/tabler.min.js" integrity="sha384-cW1KeY1Abv4YMD1D4qcBZVHMSeGL8iBtpGn9n8WNcxx6ANLZnMr4wO/2jLQFJuwk" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/js/tabler-map.min.js" integrity="sha384-mT4/40rBohAQekq2rkQcp6Gdp+3cEyU4jkHJW0Lh2dmnEYjy7WUbfyNRZPIIm0dZ" crossorigin="anonymous" defer></script>

The add-on loads MapLibre GL JS by itself, from dist/libs/maplibre-gl next to the Tabler scripts. Tabler uses version 6, which is published as an ES module. When your files are somewhere else, point the library option at the module: data-bs-library="/vendor/maplibre-gl.mjs". The library loads two more files from its own folder, maplibre-gl-shared.mjs and maplibre-gl-worker.mjs, so keep the three together.

If the page sets window.maplibregl before the add-on runs, the component uses that and loads nothing. This is the way to go with a bundler:

npm install maplibre-gl
import * as maplibregl from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'

window.maplibregl = maplibregl

const { MapView } = await import('@tabler/core/dist/js/tabler-map.esm.js')

Browsers do not load ES modules from a page opened straight from the disk. Use a local server to see the maps while you work.

Tabler styles the map controls, popups and attribution to match the interface, in light and dark mode. These styles are in tabler-vendors.css, so load it after the MapLibre stylesheet:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/css/tabler-vendors.min.css" integrity="sha384-b+YzQ3wbqkqeKY30ZsKxofcS71EsJ2Du59hAnd11P9/02pu1DSxkR2ynmwDHJA7U" crossorigin="anonymous" />

Usage

Basic map

Put the map element inside a ratio element, so the map keeps its shape on every screen size. data-bs-center takes the longitude first and the latitude second. This is the opposite of what most map services show.

<div class="ratio ratio-16x9">
  <div>
    <div id="map-simple" class="w-100 h-100" role="region" aria-label="Simple map" data-bs-toggle="map" data-bs-center="13.4049,52.518827" data-bs-zoom="13" data-bs-controls="true"></div>
  </div>
</div>

Change the shape with the ratio classes, for example ratio-21x9 for a wide map or ratio-1x1 for a square one.

Map styles

The map uses a light gray style in light mode and a dark one in dark mode. Tabler softens their colors, so markers and data stand out. Set another style with data-bs-map-style: the name of an OpenFreeMap style, or the URL of any MapLibre style.

Style Result
positron Light gray map. The default in light mode.
dark Dark gray map. The default in dark mode.
liberty Street map in color.
bright Street map with stronger colors.
fiord Dark blue map.
<div class="ratio ratio-16x9">
  <div>
    <div id="map-light" class="w-100 h-100" role="region" aria-label="Street map style" data-bs-toggle="map" data-bs-center="-0.2416782,51.5285582" data-bs-zoom="11" data-bs-map-style="liberty"></div>
  </div>
</div>

data-bs-map-style-dark sets the style for dark mode. Styles from other providers work the same way, as long as they follow the MapLibre style format. Check the terms of each provider, as many of them need an API key or a paid plan.

Dark mode

The map follows the nearest data-bs-theme and changes its style when the theme changes. Markers and popups stay on the map. To keep one look in both modes, set data-bs-map-theme to light or dark.

Markers

Each child element with data-bs-lng and data-bs-lat becomes a marker. Use the .map-marker class to draw it: a circle in the primary color that can hold an icon, a short count or an avatar. Put a .map-marker-label element inside the marker for a short text under it.

Add .map-marker-dot for a small dot, or .map-marker-pin for a pin that points down. A pin needs data-bs-anchor="bottom", so its tip sits on the place. Change the color with .map-marker-{color}.

Store12
<div class="ratio ratio-16x9">
  <div>
    <div id="map-marker-styles" class="w-100 h-100" role="region" aria-label="Marker styles" data-bs-toggle="map" data-bs-center="13.405,52.522" data-bs-zoom="11">
      <span class="map-marker map-marker-dot" data-bs-lng="13.345" data-bs-lat="52.54"></span>
      <span class="map-marker map-marker-dot map-marker-red" data-bs-lng="13.39" data-bs-lat="52.545"></span>
      <span class="map-marker" data-bs-lng="13.445" data-bs-lat="52.538">
        <!-- Download SVG icon from http://tabler.io/icons/icon/building-store -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M3 21l18 0" />
          <path d="M3 7v1a3 3 0 0 0 6 0v-1m0 1a3 3 0 0 0 6 0v-1m0 1a3 3 0 0 0 6 0v-1h-18l2 -4h14l2 4" />
          <path d="M5 21l0 -10.15" />
          <path d="M19 21l0 -10.15" />
          <path d="M9 21v-4a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v4" />
        </svg>
        <span class="map-marker-label">Store</span>
      </span>
      <span class="map-marker map-marker-green" data-bs-lng="13.35" data-bs-lat="52.512">12</span>
      <span class="map-marker map-marker-pin" data-bs-lng="13.405" data-bs-lat="52.522" data-bs-anchor="bottom">
        <!-- Download SVG icon from http://tabler.io/icons/icon/home -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M5 12l-2 0l9 -9l9 9l-2 0" />
          <path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
          <path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" />
        </svg>
      </span>
      <span class="map-marker map-marker-pin map-marker-red" data-bs-lng="13.47" data-bs-lat="52.518" data-bs-anchor="bottom">
        <!-- Download SVG icon from http://tabler.io/icons/icon/star -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" />
        </svg>
      </span>
      <span class="map-marker" data-bs-lng="13.43" data-bs-lat="52.508">
        <span class="avatar avatar-sm" style="background-image: url(/static/avatars/000m.jpg)"></span>
      </span>
    </div>
  </div>
</div>

Add data-bs-draggable="true" to let people move a marker, for example to pick an address. Add .map-marker-pulse for a ring that grows out of the marker, for a live position or a place that needs attention.

HTML markers work well for up to a few hundred places. For more, use clusters.

Popups

Add data-bs-popup to a marker for a short text that opens when the marker is clicked. Tabler draws the popup as a small bordered panel with no arrow, and fades it in.

<div class="ratio ratio-16x9">
  <div>
    <div id="map-markers" class="w-100 h-100" role="region" aria-label="Map with markers" data-bs-toggle="map" data-bs-center="0,0" data-bs-zoom="1" data-bs-map-style="positron">
      <span class="map-marker map-marker-dot" data-bs-lng="-58.666667" data-bs-lat="-34.58333333" data-bs-popup="Buenos Aires"></span>
      <span class="map-marker map-marker-dot" data-bs-lng="16.366667" data-bs-lat="48.2" data-bs-popup="Vienna"></span>
      <span class="map-marker map-marker-dot" data-bs-lng="116.383333" data-bs-lat="39.91666667" data-bs-popup="Beijing"></span>
      <span class="map-marker map-marker-dot" data-bs-lng="149.133333" data-bs-lat="-35.26666667" data-bs-popup="Canberra"></span>
      <span class="map-marker map-marker-dot" data-bs-lng="58.583333" data-bs-lat="23.61666667" data-bs-popup="Muscat"></span>
      <span class="map-marker map-marker-dot" data-bs-lng="-77" data-bs-lat="38.883333" data-bs-popup="Washington"></span>
    </div>
  </div>
</div>

For richer content, put a <template> inside the marker. Its content becomes the popup. Add the map-popup-card class to the template for a popup with an image: it removes the padding and sets a fixed width, so the image reaches the edges. data-bs-close-button="true" on the template adds a close button, and data-bs-popup-open="true" on the marker opens the popup from the start.

<div class="ratio ratio-4x3">
  <div>
    <div id="map-popup-card" class="w-100 h-100" role="region" aria-label="Popup card" data-bs-toggle="map" data-bs-center="13.4,52.546" data-bs-zoom="11">
      <span class="map-marker map-marker-pin" data-bs-lng="13.4019" data-bs-lat="52.5169" data-bs-anchor="bottom" data-bs-popup-open="true">
        <!-- Download SVG icon from http://tabler.io/icons/icon/map-pin -->
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="icon">
          <path d="M9 11a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
          <path d="M17.657 16.657l-4.243 4.243a2 2 0 0 1 -2.827 0l-4.244 -4.243a8 8 0 1 1 11.314 0" />
        </svg>
        <template class="map-popup-card" data-bs-close-button="true">
          <div class="img-responsive img-responsive-21x9" style="background-image: url(/static/photos/a-visit-to-the-bookstore.jpg)"></div>
          <div class="p-3">
            <div class="fw-medium">Museum Island</div>
            <div class="text-secondary mb-3">Five museums on the Spree, open daily.</div>
            <a href="#" class="btn btn-primary btn-sm">View details</a>
          </div>
        </template>
      </span>
    </div>
  </div>
</div>

Controls

Add data-bs-controls="true" for zoom buttons in the top corner of the map. They are regular Tabler buttons, so they follow the theme. For more buttons, pass a list of names:

Name Buttons
zoom Zoom in and zoom out.
north Turns the map back to north up.
locate Moves the map to the position of the device. The browser asks for permission first.
fullscreen Shows the map on the whole screen, and back.
<div class="w-100 h-100" data-bs-toggle="map" data-bs-center="13.405,52.52" data-bs-zoom="12" data-bs-controls="zoom,north,locate,fullscreen"></div>

The buttons have English names for screen readers. Change them with the labels option, by action:

<div class="w-100 h-100" data-bs-toggle="map" data-bs-controls="true" data-bs-labels='{"zoom-in": "Przybliż", "zoom-out": "Oddal"}'></div>

You can also write the buttons yourself. Any button with data-bs-map-action works on the map it is inside, or on the map its data-bs-target points at. The actions are zoom-in, zoom-out, north, locate and fullscreen. A button with no content gets a matching icon; put the buttons in a .map-controls element to place them in the top corner.

<div class="w-100 h-100" id="map-office" data-bs-toggle="map" data-bs-center="13.405,52.52" data-bs-zoom="12">
  <div class="map-controls">
    <button type="button" class="btn btn-sm btn-icon" data-bs-map-action="zoom-in" aria-label="Zoom in"></button>
    <button type="button" class="btn btn-sm btn-icon" data-bs-map-action="zoom-out" aria-label="Zoom out"></button>
  </div>
</div>

<button type="button" class="btn" data-bs-map-action="locate" data-bs-target="#map-office">Find me</button>

Route

Draw a path with data-bs-route: a list of [longitude, latitude] points. The line takes the primary color and is drawn again after a theme change. Mark its ends with markers.

<div class="w-100 h-100" data-bs-toggle="map" data-bs-center="13.4046,52.513" data-bs-zoom="11.6" data-bs-route="[[13.3695,52.5251],[13.4132,52.5219],[13.4397,52.505]]">
  <span class="map-marker map-marker-dot" data-bs-lng="13.3695" data-bs-lat="52.5251"></span>
  <span class="map-marker map-marker-pin" data-bs-lng="13.4397" data-bs-lat="52.505" data-bs-anchor="bottom"></span>
</div>

To show how far along a path something is, add data-bs-route-progress with the index of the point reached so far, counted from 0. The path up to that point stays solid and the rest is dashed.

<div class="w-100 h-100" data-bs-toggle="map" data-bs-route="[[13.3695,52.5251],[13.4132,52.5219],[13.4397,52.505]]" data-bs-route-progress="1"></div>

Areas and other shapes

data-bs-geojson draws GeoJSON over the map: areas with a light fill and an outline, lines, and points as small circles. Pass the GeoJSON itself, or the URL of a file.

<div class="w-100 h-100" data-bs-toggle="map" data-bs-center="13.405,52.519" data-bs-zoom="11" data-bs-geojson="/data/delivery-zone.geojson"></div>

Both use the primary color. Set data-bs-layer-color to another color, for example --tblr-red or #d63939.

Globe

Add data-bs-globe="true" to draw the map as a 3D globe. Use a low zoom, between 1 and 2, to see the whole globe. People can turn it by dragging.

<div class="w-100 h-100" data-bs-toggle="map" data-bs-center="62,32" data-bs-zoom="1.3" data-bs-globe="true"></div>

Content over the map

To put buttons or a small card over the map, place them next to the map element and position them with the utility classes:

<div class="ratio ratio-16x9">
  <div>
    <div class="w-100 h-100 rounded" data-bs-toggle="map" data-bs-center="13.405,52.52" data-bs-zoom="10"></div>
    <div class="btn-list position-absolute top-0 start-0 m-2">
      <button type="button" class="btn btn-sm btn-pill btn-primary">Berlin</button>
      <button type="button" class="btn btn-sm btn-pill">Tokyo</button>
    </div>
  </div>
</div>

Attribution

MapLibre adds the credit for the map data in the corner of the map. OpenFreeMap requires it, so do not hide it.

Layers

The route and GeoJSON options cover simple shapes. For anything more, such as clusters, dashed lines or circles sized by a value, take the MapLibre map from the component and use its own API. The map property is the MapLibre map.

A layer reads its data from a GeoJSON source. Layers are part of the map style, so add them in onStyle(). It runs when the style has loaded, and again each time the style changes, for example on a theme change.

document.addEventListener('DOMContentLoaded', function () {
  const view = tabler.MapView.getInstance('#map-stores')

  view.onStyle(function (map) {
    map.addSource('stores', { type: 'geojson', data: stores })
    map.addLayer({
      id: 'stores',
      type: 'circle',
      source: 'stores',
      paint: { 'circle-color': tabler.MapView.color('--tblr-primary'), 'circle-radius': 6 },
    })
  })

  // Runs once the map exists: the library may load a moment after the page
  view.ready(function (map) {
    map.on('click', 'stores', function (event) {
      console.log(event.features[0].properties)
    })
  })
})

For an area, use a Polygon geometry with a fill layer, and a line layer for its outline.

Theme colors in layers

MapLibre draws layers on a canvas, so a CSS variable does not work in paint, and neither do the oklch() values Tabler colors are written in. MapView.color() turns a variable, or any CSS color, into a plain rgb() color. Call it inside onStyle(), so the colors are read again after a theme change.

tabler.MapView.color('--tblr-primary') // 'rgb(6, 111, 209)'

Clusters

Put many points in a GeoJSON source with cluster: true. MapLibre then groups nearby points and splits the groups as you zoom in.

map.addSource('stores', { type: 'geojson', data: stores, cluster: true, clusterRadius: 40 })

// Circle for each cluster, larger for more points
map.addLayer({
  id: 'clusters',
  type: 'circle',
  source: 'stores',
  filter: ['has', 'point_count'],
  paint: { 'circle-color': tabler.MapView.color('--tblr-primary'), 'circle-radius': ['step', ['get', 'point_count'], 14, 10, 18, 25, 24] },
})

// Number of points in the cluster
map.addLayer({
  id: 'cluster-count',
  type: 'symbol',
  source: 'stores',
  filter: ['has', 'point_count'],
  layout: { 'text-field': ['get', 'point_count_abbreviated'], 'text-font': ['Noto Sans Regular'], 'text-size': 12 },
  paint: { 'text-color': '#ffffff' },
})

text-font has to be a font the map style provides. All OpenFreeMap styles have Noto Sans Regular.

Tooltips

For a short label on hover, add the map-tooltip class to a MapLibre popup. It turns the popup into a small dark label.

const tooltip = new maplibregl.Popup({ closeButton: false, offset: 12, className: 'map-tooltip' })

map.on('mousemove', 'cities', function (event) {
  tooltip.setLngLat(event.lngLat).setText(event.features[0].properties.name).addTo(map)
})
map.on('mouseleave', 'cities', function () {
  tooltip.remove()
})

Live versions of a route, an area, clusters, a bubble map, a globe with arcs and a city switcher are on the maps preview page. The map blocks page has larger examples: a store locator, a list of homes with prices on the map, a delivery tracker, an address form with a draggable pin, a server status map, a map of live users and a vector map of users by country.

JavaScript

Via data attributes

An element with data-bs-toggle="map" becomes a map when the tabler-map.js script loads:

initAll(SELECTOR_DATA_TOGGLE, MapView)

// A button with `data-bs-map-action` acts on the map it is in, or on the map
// its `data-bs-target` points at.
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_ACTION, function (this: HTMLElement) {
  const element = SelectorEngine.getElementFromSelector(this) ?? this.closest<HTMLElement>(SELECTOR_DATA_TOGGLE)
  const view = element && (MapView.getInstance(element) as MapView | null)
  const actions: Record<string, () => void> = {
    'zoom-in': () => view?.zoomIn(),
    'zoom-out': () => view?.zoomOut(),
    'north': () => view?.resetNorth(),
    'locate': () => view?.locate(),
    'fullscreen': () => view?.toggleFullscreen(),
  }

  actions[this.getAttribute('data-bs-map-action') ?? this.getAttribute('data-tblr-map-action') ?? '']?.()
})

Via JavaScript

Create a map from your own code with the same options:

const view = new tabler.MapView('#map', {
  center: [13.405, 52.52],
  zoom: 12,
  controls: true,
})

Options

Pass options as data attributes, with the name written in kebab case after data-bs-, or in the config object.

Name Type Default Description
library string MapLibre in dist/libs URL of the MapLibre GL JS module, loaded when window.maplibregl is not set. A relative URL starts at the Tabler script. null turns the loading off.
center array, string [0, 0] Center of the map: [longitude, latitude], or the two numbers in a string such as "13.405,52.52".
zoom number 1 Zoom level, from 0 for the whole world to about 20 for a building.
mapStyle string 'positron' Name of an OpenFreeMap style, or the URL of a MapLibre style.
mapStyleDark string 'dark' Style used in dark mode. Set null to keep mapStyle in both modes.
mapTheme string 'auto' 'auto' follows the nearest [data-bs-theme]; 'light' or 'dark' keeps one look.
palette boolean true Softer colors for the positron and dark styles. Other styles are left as they are.
controls boolean, string false Buttons over the map: true for zoom, or a list of zoom, north, locate and fullscreen.
labels object {} Names of the buttons for screen readers, by action: zoom-in, zoom-out, north, locate, fullscreen.
route array null A path drawn as a line: a list of [longitude, latitude] points.
routeProgress number null Index of the route point reached so far. The path up to it is solid, the rest is dashed.
geojson object, string null GeoJSON drawn over the map: an object, or the URL of a file.
layerColor string '--tblr-primary' Color of the route and the GeoJSON shapes: a CSS color or a custom property.
globe boolean false Draw the map as a 3D globe.
mapOptions object {} Any MapLibre map option, passed straight through.

A marker element takes these attributes:

Attribute Description
data-bs-lng, data-bs-lat Position of the marker. Both are needed.
data-bs-anchor Part of the marker that sits on the position: center by default, bottom for a pin.
data-bs-draggable Set true to let people move the marker.
data-bs-popup Text of a popup that opens when the marker is clicked.
data-bs-popup-open Set true to open the popup from the start.

Methods

Name Description
map The MapLibre map, for layers, events and everything else the options do not cover. null until the library has loaded.
ready(callback) Runs the callback with the MapLibre map once it exists.
onStyle(callback) Runs the callback with the map each time a style loads. The place to add layers.
markers The MapLibre markers made from the child elements, in document order.
zoomIn(), zoomOut() Zooms the map by one level.
resetNorth() Turns the map back to north up, with no tilt.
locate() Moves the map to the position of the device.
toggleFullscreen() Shows the map on the whole screen, and back.
dispose() Removes the map, its markers and the instance.
MapView.color(value) Turns a CSS variable or color into a plain rgb() color for a map layer.
MapView.getInstance(element) Returns the instance for an element, or null.
MapView.getOrCreateInstance(element) Returns the instance, or creates one.

Events

Event Description
load.bs.map Fires on the map element once the map has loaded its style and first tiles.

Using Mapbox GL JS

MapLibre GL JS started as a fork of Mapbox GL JS, so the two share most of their API. The map component works with MapLibre only. To use Mapbox, write the map script yourself: load its script and stylesheet, set mapboxgl.accessToken to your public token, and use a mapbox:// style URL.

Accessibility

  • The map is a picture for most users. Give the same information as text near it, for example the address or a list of places.
  • Add role="region" and an aria-label to the map element, so screen reader users know what the map shows.
  • Do not put an action only on a marker. Repeat it in a normal link or button below the map.
  • Keep a visible fallback when the script fails to load, for example the address in text.

Class reference

Every class this component ships, grouped by what it changes. A name in braces stands for a family — {color} is any base color, {breakpoint} any responsive step.

ratio componentWrapper that keeps the map at a fixed aspect ratio
map-marker componentMarker drawn in HTML, a circle that can hold an icon, a count or an avatar
map-marker-label partShort text under a marker
map-controls partColumn of buttons in the top end corner of the map
map-marker-dot modifierSmall dot with no content
map-marker-pulse modifierRing that grows out of the marker and fades, for a live position
map-marker-pin modifierTeardrop pin that points down, used with the bottom anchor
map-popup-card modifierPopup with no padding and a fixed width, for an image above the text
map-tooltip modifierPopup shown as a small dark label, for text on hover
map-marker-{color} colorAny theme color, for example map-marker-red or map-marker-green
ratio-{ratio} sizeThe aspect to hold, for example ratio-16x9 or ratio-21x9

CSS

Variables

The component uses local CSS variables on .map-marker for real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too. Source: core/scss/vendor/_maplibre.scss.

--map-marker-size: #{$map-marker-size};
--map-marker-bg: #{$map-marker-bg};
--map-marker-color: #{$map-marker-color};
--map-marker-border-width: #{$map-marker-border-width};
--map-marker-border-color: #{$map-marker-border-color};
--map-marker-font-size: #{$map-marker-font-size};
--map-marker-icon-size: #{$map-marker-icon-size};

Sass variables

Override these variables before importing Tabler to change the defaults. Source: core/scss/_variables.scss.

$map-marker-size: 1.75rem;
$map-marker-dot-size: 1rem;
$map-marker-bg: var(--primary);
$map-marker-color: var(--primary-fg);
$map-marker-border-width: 2px;
$map-marker-border-color: var(--bg-surface);
$map-marker-font-size: $h5-font-size;
$map-marker-icon-size: 1rem;
$map-marker-shadow: drop-shadow(0 1px 2px rgba($black, 0.3));
$map-popup-card-width: 16rem;
$map-controls-offset: 0.625rem;
$map-controls-gap: 0.375rem;
$map-control-icon-size: 1rem;
$map-control-icons: (
  'zoom-in': "<path d='M12 5v14M5 12h14'/>",
  'zoom-out': "<path d='M5 12h14'/>",
  'north': "<path d='M12 18.5l7.265 2.463c.196 .077 .42 .032 .57 -.116a.548 .548 0 0 0 .134 -.572l-7.969 -17.275l-7.97 17.275c-.07 .2 -.017 .424 .135 .572c.15 .148 .374 .193 .57 .116l7.265 -2.463'/>",
  'locate': "<path d='M9 12a3 3 0 1 0 6 0a3 3 0 1 0 -6 0M4 12a8 8 0 1 0 16 0a8 8 0 1 0 -16 0M12 2v2M12 20v2M20 12h2M2 12h2'/>",
  'fullscreen': "<path d='M4 8v-2a2 2 0 0 1 2 -2h2M4 16v2a2 2 0 0 0 2 2h2M16 4h2a2 2 0 0 1 2 2v2M16 20h2a2 2 0 0 0 2 -2v-2'/>",
);