Skip to content

Your first map, explained

This page goes through the map.yaml from the quick start one part at a time and grows it: a view of the whole Pacific, earthquakes sized by magnitude, a better popup and map controls. The whole file, and the map it draws, are at the end. After each change, save map.yaml and reload the page.

Every map document has the same few keys at the top level:

  • type: map says what the file is. (A story map is type: scrollytelling.)
  • id: is a short name for the map, in your own words. It is required.
  • config: is the view the map opens on and its basemap.
  • layers: is what is drawn on top of the basemap, in order: the first layer is drawn first, at the bottom.
  • controls:, optional, adds zoom buttons, a scale bar and the like.

A document can hold more, such as a legend: or shared sources:; the YAML reference lists every key.

The YAML on its own draws nothing: a web page shows it with <ml-map src="./map.yaml">. This page uses the quick start’s index.html unchanged. It gives <ml-map> a height, which any page of your own must do too: the element has no size of its own (The map has no height).

config: sets where the map opens. The quick start looks at California. To see the earthquakes all around the Pacific, change center and zoom:

config:
center: [-160, 20]
zoom: 1
mapStyle: "https://tiles.openfreemap.org/styles/liberty"
  • center is the point in the middle of the map, as [longitude, latitude].
  • zoom is how close the map is: 0 shows the whole world, about 10 a city, about 15 a few streets.

config: takes more, all optional: pitch and bearing tilt and turn the map, minZoom and maxZoom limit how far the reader can zoom, and bounds or fitTo frame an area or your data instead of a center and zoom. See config in the YAML reference.

Coordinates are always [longitude, latitude], the GeoJSON order, not the latitude-first order most map websites show:

# Right: [longitude, latitude]
center: [-74.006, 40.7128]
# Wrong: [latitude, longitude], an empty spot in Antarctica
center: [40.7128, -74.006]

Longitude is the x axis, latitude the y axis. While you develop, a center that looks written latitude first gets a note on the map.

mapStyle is the basemap, the background map of streets, water and labels under your layers. It is the address of any MapLibre style. These docs use OpenFreeMap’s liberty style, which is free and needs no API key. Two others:

# A quieter, light-grey basemap, for maps where your data should stand out
mapStyle: "https://tiles.openfreemap.org/styles/positron"
# A keyed provider: add your own key
mapStyle: "https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY"

It can also be a basemap you host yourself, from one Protomaps .pmtiles file next to your page: Host your own basemap.

A map with no mapStyle doesn’t draw: it shows an error card asking for one.

The quick start’s one layer draws every earthquake as a red circle:

layers:
- id: earthquakes
type: circle
source:
type: geojson
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson"
paint:
circle-radius: 6
circle-color: "#e74c3c"
circle-stroke-width: 1
circle-stroke-color: "#ffffff"
  • id names the layer. Each layer’s id must be different from the others’; other parts of the document, such as a story chapter that shows or hides it, refer to the layer by it.
  • type is how the data is drawn: circle for points, line for lines, fill for polygons, symbol for text labels and icons, and a few more (Layers & styling).
  • source is where the data comes from: here a GeoJSON file, fetched from its url when the page opens. Data can also be written in the document itself, or defined once under a top-level sources: and shared by several layers (Loading data).
  • paint is how it looks. The keys are MapLibre’s paint properties, such as circle-radius in pixels and circle-color.

Colours go in quotes. In YAML # starts a comment, so an unquoted circle-color: #e74c3c leaves the colour empty and the layer fails validation.

A paint value can come from each feature’s data. Every earthquake in the feed has a mag property, its magnitude. To draw stronger ones bigger, replace the paint: block with:

paint:
circle-radius: ["interpolate", ["linear"], ["get", "mag"], 1, 2, 7, 20]
circle-color: "#e74c3c"
circle-opacity: 0.7
circle-stroke-width: 1
circle-stroke-color: "#ffffff"

The radius is a MapLibre expression: read mag, and scale it from 2 pixels at magnitude 1 to 20 pixels at magnitude 7. circle-opacity: 0.7 lets overlapping circles show through. To sort features into classes with a legend instead, see Thematic maps & legends.

To map a file of your own, put it in your folder and point url: at it. To try it with the earthquakes, open the feed’s address in your browser, save what it shows as earthquakes.geojson in a data folder next to index.html, and change the source:

source:
type: geojson
url: "data/earthquakes.geojson"

Two rules for paths to your own files:

  • data/earthquakes.geojson and ./data/earthquakes.geojson mean the same thing: a path relative to the page. A path that starts with / starts at the site root.
  • They are resolved against the page (index.html), not against the YAML file. With index.html and map.yaml side by side and the data in a data/ folder next to them, data/earthquakes.geojson is right.

Files on other websites work too, as the USGS feed does, when that server allows other sites to read them (CORS). If it doesn’t, the map’s notice says the file didn’t load and the browser console shows a CORS error.

The quick start’s popup shows each earthquake’s title. This one shows the place as the heading and the magnitude below it, rounded to one decimal place. Replace the layer’s interactive: block with:

interactive:
hover:
cursor: pointer
click:
popup:
- h3:
- property: place
- p:
- str: "Magnitude "
- property: mag
format: { max-fraction-digits: 1 }

A popup is a list of HTML elements (h3, p and others), each holding text (str) and values from the clicked feature (property). format writes a number the way the page’s language does. The popups guide covers what a popup can show, hover popups and number formats.

controls: adds MapLibre’s controls to the map. Add this at the top level of the document, below layers::

controls:
navigation: true
scale: true

navigation is the zoom and compass buttons, top right; scale is a scale bar, bottom left. fullscreen: true and geolocate: true add a full-screen button and a “show my location” button. Each control can also take a position: controls in the YAML reference.

The whole map.yaml, with every change from this page:

type: map
id: earthquake-map
config:
center: [-160, 20]
zoom: 1
mapStyle: "https://tiles.openfreemap.org/styles/liberty"
layers:
- id: earthquakes
type: circle
source:
type: geojson
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson"
paint:
circle-radius: ["interpolate", ["linear"], ["get", "mag"], 1, 2, 7, 20]
circle-color: "#e74c3c"
circle-opacity: 0.7
circle-stroke-width: 1
circle-stroke-color: "#ffffff"
interactive:
hover:
cursor: pointer
click:
popup:
- h3:
- property: place
- p:
- str: "Magnitude "
- property: mag
format: { max-fraction-digits: 1 }
controls:
navigation: true
scale: true
Earthquakes of the past seven days, sized by magnitude. Click one for its place and magnitude

Edit this map in the playground

This page, and every page outside Advanced, uses format v1, the default. Format v2 is an opt-in layout of the same document that splits it into the part that exports to a MapLibre style.json and the part that only runs on the page. You don’t need it to make any map on these pages.