Guide

A nautical map with depths and sea marks

A web map of the sea: the water coloured by depth, depth contours, and buoys, beacons and lights in their colours. With the marine style, or added to a style of your own with MapLibre layers. For websites of marinas, sailing schools, ferries and coastal tourism; not for navigation. Tested with MapLibre GL JS 6.13.0.

The marine style has it all, in MapLibre GL JS 5.6 or later:
const map = new maplibregl.Map({
  container: "map",
  style: "https://api.overpass.ch/v1/YOUR_KEY/maps/styles/marine.json",
  center: [-1.31, 50.8], // the Solent
  zoom: 12
});
Go to:
Loading the map…
Depth: 0 m 6,000 m · sea marks from zoom 9, buoys and beacons from zoom 11 · not for navigation

What the marine style shows

  • The sea coloured by depth, with the sea floor shaded, and depth contours with labels.
  • Lighthouses, lights, lateral and cardinal buoys and beacons in their colours, danger and safe water marks, special marks, wrecks and rocks. Closer in, lights show their character, such as Fl(2) R 6s: two red flashes every six seconds.
  • Harbours, marinas, anchorages and ferry routes, the coastline, and protected areas as outlines, since many reach out to sea.

Lighthouses, harbours, marinas and anchorages show from zoom 9, the other marks from zoom 11. The marine style uses the color-relief layer type, which came with MapLibre GL JS 5.6, so it needs that version or a later one.

Depths and sea marks on a style of your own

The depths, contours and marks come as three tile sets of their own. This adds them to the light style; the sea marks are coloured circles, which need no icons:

const API = "https://api.overpass.ch/v1/YOUR_KEY/maps";
const map = new maplibregl.Map({
  container: "map",
  style: `${API}/styles/light.json`,
  center: [-1.31, 50.8],
  zoom: 12
});
map.on("load", () => {
  map.addSource("bathymetry", { type: "raster-dem", url: `${API}/bathymetry.json` });
  map.addSource("isobaths", { type: "vector", url: `${API}/isobaths.json` });
  map.addSource("seamarks", { type: "vector", url: `${API}/seamarks.json` });

  // the depths go under the land ("earth"); the sea polygons of the
  // water layer would cover them, so that layer keeps lakes and rivers only
  map.setFilter("water", ["all", ["==", ["geometry-type"], "Polygon"], ["!=", ["get", "kind"], "ocean"]]);
  map.setPaintProperty("water", "fill-color", "#b9dbf0"); // bays and lakes: a shallow-sea blue
  map.addLayer({
    id: "sea-depth",
    type: "color-relief", // MapLibre GL JS 5.6 or later
    source: "bathymetry",
    paint: {
      "color-relief-color": ["interpolate", ["linear"], ["elevation"],
        -6000, "#4c8bc0", -1000, "#84b8dd", -200, "#9dc8e6", -50, "#badaef",
        -10, "#d3e9f6", 0, "#e6f3fb"]
    }
  }, "earth");
  map.addLayer({
    id: "isobaths",
    type: "line",
    source: "isobaths",
    "source-layer": "contours",
    paint: { "line-color": "#4f86b8", "line-width": 0.6, "line-opacity": 0.6 }
  }, "earth");
  map.addLayer({
    id: "seamarks",
    type: "circle",
    source: "seamarks",
    "source-layer": "seamarks",
    paint: {
      "circle-radius": ["match", ["get", "kind"], ["lighthouse", "harbour", "marina"], 6, 4],
      "circle-color": ["match", ["get", "colour"],
        "red", "#d0312d", "green", "#2e8b3d", "yellow", "#e2b100", "black", "#222222", "#ffffff"],
      "circle-stroke-color": "#2b3f57",
      "circle-stroke-width": 1
    }
  });
});
  • color-relief colours each pixel of the raster-dem source by its height; ["elevation"] is negative at sea. The colours above are those of the marine style, with fewer steps.
  • Bays and estuaries that OpenStreetMap maps as water areas, such as Southampton Water, keep one colour; only the open sea gets the depth colours.
  • In a style JSON, add the three sources to sources, the two depth layers before earth and the sea marks near the end of layers.

The tiles

TilesContentZoom
bathymetry.jsonHeights in the Terrain-RGB format: depths from GEBCO at sea, Copernicus on land. For color-relief and a shaded sea floor with a hillshade layer.0 to 9
isobaths.jsonLayer contours: ele in metres below 0, level 1 at 100 m and every 1,000 m. 200 m and every 1,000 m down to zoom 7, then also 20, 50, 100 and 500 m, and from zoom 10 also 5 and 10 m.5 to 12
seamarks.jsonLayer seamarks: kind (lighthouse, light, lateral, cardinal, danger, safe_water, special, marina, harbour, anchorage, wreck, rock, mooring), colour, category, name and light.9 to 13

The sea marks come from the seamark:* tags of OpenStreetMap, the tags that OpenSeaMap also uses, through our Overpass server; a tile is at most 7 days old. colour holds the main colour of a mark, and some marks have none. category tells port from starboard for lateral marks and the direction for cardinal marks.

Limits

  • The depths come from GEBCO, a worldwide grid of about 460 m. They show where the sea is deep or shallow, and miss channels, sandbanks and rocks that are smaller than the grid.
  • Sea marks in OpenStreetMap can be missing, out of date or misplaced, and buoys are moved. Use official charts and notices on board. Keep the words “not for navigation” in your map, as the credit of the marine style does.
  • Credit GEBCO when you show the depths: the attribution of the depth tiles adds it to the map.
  • Every depth, contour and sea mark tile counts as one map tile. The first view of the marine style above, at zoom 13 and 1280 × 720 pixels, loaded 20 tiles. Every account includes 100'000 a month.