Styling OpenStreetMap Data with MapCSS

By Aliaksandr Kalenik

It is easy to style the maps with MapCSS. Explore its features, syntax and most popular implementations

Let’s say you want to have a map in your application and be able to define what objects need to be displayed on your map and how exactly they should look. It is too complicated to make a map rendering engine every time the look of the map needs to be customized, so it’s common to separate the part responsible for drawing from a definition of what needs to be drawn. Among the languages designed to describe what needs to be drawn on a map, there is one that gained popularity in the OpenStreetMap community  —  MapCSS.

MapCSS is a specification of style language explicitly designed to describe the look of the OpenStreetMap data. There are already plenty of popular tools in the community that implement this specification:

  • Kothic  —  python rendering engine. It allows to compile MapCSS into a format compatible with common rendering engines e.g. Mapnik or Organic Maps;
  • Organic Maps  —  offline mobile map application that defines styles in MapCSS;
  • JOSM  —  OpenStreetMap editor that supports MapCSS natively;
  • Overpass turbo  —  data mining tool.

*Check more https://wiki.openstreetmap.org/wiki/MapCSS.

Basics of MapCSS syntax

Let’s explore MapCSS syntax. We are not going to dive into all specifics but instead get familiar with the concept by building a simple style with water, administrative boundaries, and country names.

To begin with, oceans can be filled with color, so it’s possible to distinguish them from the land.

area|z0-[natural=coastline] {
    fill-color: #F0F8FF;
}

area is a selector type that is used to choose closed ways. z0- means that the selected element will be rendered from 0 zoom to the last supported zoom. [natural=coastline] is a test needed to select only elements tagged as coastlines. fill-color is the property that specifies the color that will be used to fill selected areas.

The next obvious step is to add administrative boundaries of countries.

line|z1-[boundary=administrative][admin_level=2] {
  width: 0.5;
  opacity: 0.4;
  color: black;
}

line is a selector type that is used to choose non-closed ways. [boundary=administrative][admin_level=2]— select elements that confirm both tests: line should be administrative boundary and has an administrative level equal to 2 which is used for countries in OSM.

node is used to select elements that consist of one point. text property specifies element tag name that needs to be displayed on a map.

node|z1-[place=country] {
    text: name:en;
    font-size: 17;
    text-transform: uppercase;
}

Useful links

We went through the MapCSS styling basics in this article. If you have an interest in more examples and detailed descriptions of the syntax, you can find them here:

https://wiki.openstreetmap.org/wiki/MapCSS/0.2

https://josm.openstreetmap.de/wiki/Help/Styles/MapCSSImplementation

Also, you can learn from reading MapCSS styles of open source applications:

https://github.com/kothic/kothic/tree/master/src/styles

https://github.com/organicmaps/organicmaps/tree/master/data/styles

Pros and Cons of using MapCSS

The advantages of MapCSS:

  • Language for styling OSM data in the first place  —  rules are written using regular OSM element types and tags which means you can use OSM wiki as a reference.
  • Portability: you can learn it once and be able to write a style in any of the tools that implement the specification.
  • The syntax is expressive and looks compact.

Disadvantages:

  • Lack of tooling for modern text editors and IDEs  —  you are unlikely to find MapCSS syntax highlighter extension for your favorite editor.