Styling And Building Custom Maps

Notes on building a data-styled map with TileMill

First, you’ll need to install TileMill (the now deprecated software in favour of Mapbox Studio). Even if it has been deprecated, it is a unique and powerful software that allows us to build maps from scratch.

The goal of TileMill is to take a shapefile, style it with CartoCSS and export it as a .mbtiles file. mbtiles is a spec created by Mapbox to store raster images of a map.

A map showing degree of urbanisation in Europe.

Data attribution: © EuroGeographics for the administrative boundaries. Please read before re-use.

Fundamentals of web maps

A web map is usually a mercator projection (A projection is a transformation of our 3D world to a 2D map). There are different types of projection, and discussing all of those would be a digression.

A web map should provide users a seamless experience of zooming, and panning across regions at various zoom levels. Thus, we can easily say that map interactions can be bound to 3 variables: z, x and y.

At street level zoom, a single 2D image would be too big for the computer, therefore we serve the map as tiles, or smaller images, think of it as {z}/{x}/{y}.png, where we’ll have that many images for different values of z, x, and y.

Whenever the user pans left or right, we request for the appropriate image from the server in an AJAX call. This is handled by the wonderful library leaflet.js

Creating a map in TileMill

Download and install TileMill for your OS, and create a new project.

Next, download shapefile data from your source. For this example, I am using DGRUBA data from Eurostat that shows degree of urbanisation with 3 ranks: 1, 2 and 3 with highest urbanised areas having rank as 1.

In the bottom left, you can add a layer in TileMill. If you look at the layer file in TileMill, it should look like the below image

Styling with CartoCSS

CartoCSS is similar to CSS, with a few extra features. Below is the set of specifiers I’ve used to style my example map. The specifiers are for the dataset dgurbarg01m2014.

#dgurbarg01m2014[DGURBA_CLA=1] {

#dgurbarg01m2014[DGURBA_CLA=2] {

#dgurbarg01m2014[DGURBA_CLA=3] {

Notice that you can provide individual polygon fills based on column values in your shapefile data. The complete reference for CartoCSS can be found at

Hosting your own map server

Once it is styled, you can export it as a .mbtiles file, and then use mbutil to convert it to pngs with the z/x/y directory structure.

Finally, if your custom pngs are at /path/to/tiles, start $ python -m http.server from that folder. Once your tile server is up, below is a sample leaflet code to serve it on the browser.

L.tileLayer(`http://localhost:8000/{z}/{x}/{y}.png`, {
  subdomains: 'abcd',
  minZoom: 4,
  maxZoom: 12

Refer to if you haven’t used leaflet already.

Note that this example tile server is for illustration purpose only. Do not use such a setup in production.


Creating maps are awesome fun!

There are plenty of shapefiles and GIS resources available online. Leaflet is also a wonderful library for map-based interactivity in the front end, in which you can show summarized data on hover, on click, etc. I hope you find this tutorial useful to start exploring on your own.


Here are a few screenshots from a custom map dashboard that my friend Nikhil and I built for a client recently.

If you’re looking for advise, or need consultation with building map based data analysis and visualisation, you can contact me.

Share article

Also recommended

Parsing Python Abstract Syntax Trees
Featuring my talk at Pycon India 2016

Update: This blog post inspired my talk at Pycon India 2016, Hacking the Python AST. Watch it on YouTube: …

Read now ▶
Understanding Callbacks
The concept that is used in many frameworks, including jQuery

Prior to understanding what callbacks are, we need to explore functional programming with JavaScript. Every function in …

Read now ▶