FEATURE · MAP

Ship a styled map with no API key and no tile account.

Streets, terrain, light, dark and OpenStreetMap come with the editor. Switch between them at runtime, and the shapes your users drew stay on the map.

Built into the default <ElementEditor> from @element-editor/react.

The same corner of Barcelona rendered in each built-in map style, from light street maps to a dark one, laid out as overlapping cards.
One place, every built-in style. Pick one and ship.

Try it

Click Basemap, bottom left, and pick a style. Choose Auto, then flip the editor theme and watch the map follow.

  1. 1Click Basemap, bottom left, and pick a style
  2. 2Choose Auto, then switch the editor theme
  3. 3Drag a shape, then switch again: it stays

Open in full playground →

A map editor needs a map

Before anyone can draw a shape, there has to be a map under it. Usually that means picking a tile provider, creating an account, putting an API key in your frontend, and writing a style switcher. Or you settle for the default raster tiles and a map that looks nothing like the rest of your app.

The MapLibre editor comes with styles you can use from the first render, and a picker to switch between them. The vector styles load from OpenFreeMap, which needs no registration and no key. Element's own layers move over to the new style with it.

What you get

Styles that need no account. Streets, Terrain, Light and Dark are vector styles on OpenFreeMap tiles. The OpenStreetMap style uses the standard OSM raster tiles. Nothing to sign up for, no key in your bundle.

A map that follows your theme. 'auto' is the default: the editor picks Streets for a light theme and Dark for a dark one, so the editor and the map always match.

Shapes stay put when the style changes. Element carries Element's sources, layers and icons over to the new style. A user mid-edit loses nothing.

Your own style or tiles. Pass { style } with any MapLibre style URL or object, or { url, attribution } for raster tiles from any provider, as basemap or inside the picker's basemaps list.

Credits handled. Each style sets its own attribution (OpenFreeMap, OpenMapTiles, OpenStreetMap, plus Mapterhorn for the hill shading). The editor shows it expanded when the map loads, then folds it into an (i) button after 5 seconds or the first interaction.

In the drop-in editor

import { ElementEditor } from '@element-editor/react'
import '@element-editor/react/style.css'

// Auto (follows the theme), with a picker for the user
<ElementEditor />

// Start on terrain, offer a shorter list
<ElementEditor defaultBasemap="terrain" basemaps={['auto', 'streets', 'terrain', 'dark']} />

// One fixed style, no picker
<ElementEditor basemap="light" basemaps={false} />

// Serve the icon sprite yourself (an absolute URL)
<ElementEditor config={{ network: { sprite: `${location.origin}/basemaps/sprite` } }} />

The picker sits where 'basemap' is in config.ui.layout, bottom left by default. defaultBasemap sets the starting style; the user's own pick is remembered and wins on the next load. basemap puts your app in charge instead: pair it with onBasemapChange, and nothing is remembered. Tiles, fonts and the icon sprite can all come from your own servers through config.network. See the basemaps guide.

On your own MapLibre map

import maplibregl from 'maplibre-gl'
import { loadBasemapStyle, setBasemap } from '@element-editor/adapter-maplibre/basemaps'

// Icons for the vector styles. Copy the package's basemaps/ folder into public/
// (see "Things to know" below).
const network = { sprite: `${location.origin}/basemaps/sprite` }

const map = new maplibregl.Map({
  container: 'map',
  style: await loadBasemapStyle('auto', { theme: 'dark', network }),
  center: [2.17, 41.39],
  zoom: 13,
})

// Later, from your own switcher. Element's shapes stay on the map.
await setBasemap(map, 'terrain', { network })

// When your app's theme changes, 'auto' resolves again.
await setBasemap(map, 'auto', { theme: 'light', network })

// Your own style, or raster tiles from any provider.
await setBasemap(map, { style: 'https://example.com/style.json' })
await setBasemap(map, { url: 'https://tiles.example.com/{z}/{x}/{y}.png', attribution: '© Example' })

Then attach Element to map as usual: see the MapLibre quickstart. BASEMAPS lists every built-in style with its id and label, so a switcher can render from it, or render BasemapControl from @element-editor/adapter-maplibre for the same picker the drop-in uses.

The styles

StyleidTilesGood for
Auto'auto'Streets or DarkApps with a light/dark toggle: the map matches the editor theme.
Streets'streets'OpenFreeMap vector, Mapterhorn hill shadingA general-purpose map with roads, parks, places and gentle relief. The light-theme default.
Terrain'terrain'OpenFreeMap vector, Mapterhorn hill shadingLand, outdoor and site work, where slopes and land cover matter.
Light'light'OpenFreeMap vectorData-first screens. Muted greys keep your shapes the brightest thing on the map.
Dark'dark'OpenFreeMap vectorDark UIs. Low-contrast streets that sit behind your data. The dark-theme default.
OpenStreetMap'osm'tile.openstreetmap.org rasterThe familiar OSM look, with the most detail on the map itself.

Switching between them is a style change on the same map: the camera, the selection and the undo history stay where they were.

Things to know before you ship

  • The default editor runs on MapLibre. The Leaflet drop-in (@element-editor/react/leaflet) shows raster tiles only, through tileLayer or a raster basemaps list; see the basemaps guide.
  • Self-host the sprite for offline or strict-CSP apps. Without config.network.sprite, the vector styles load their icons from jsDelivr at the installed package's version, which only resolves once that version is published. Copy node_modules/@element-editor/adapter-maplibre/basemaps/ into your public folder and pass its absolute URL (MapLibre rejects relative sprite URLs), as in the snippet. Tiles, fonts and hill shading can move too (vectorTiles, glyphs, dem): see third-party services.
  • Shared, free tile servers. OpenFreeMap's public instance has no view limits, allows commercial use, and runs on donations. The OpenStreetMap style uses tile.openstreetmap.org, which is best-effort with no SLA and blocks heavy use and offline downloads. For high traffic, point { url } or { style } at a provider or your own tile server.
  • Keep the attribution available. Both OpenFreeMap and OpenStreetMap require it. The editor shows it automatically (expanded at load, then behind the (i) button); don't hide it.
  • setBasemap keeps your layers too. It carries over Element's layers and your own sources and layers, and when calls overlap, the last one wins. A plain map.setStyle also works: Element puts its own layers back by itself, but re-adding yours is up to you.

Works with

  • Theming: light, dark and auto for the editor. With 'auto', the map follows the same switch.
  • Drawing tools: draw on any style. Switching never touches the shapes.
  • Import and export: the style is a view setting. Your GeoJSON stays the same whichever map is under it.

Ready to try it?

Open in playground →

Read the quickstart · See pricing