Making a Starter Map using Leaflet

The following covers setting up your map, adding data, and popups.

Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need.

Leaflet is designed with simplicity, performance, and usability in mind. It works efficiently across all major desktop and mobile platforms, can be extended with lots of plugins, has a beautiful, easy to use and well-documented API, and a simple, readable source code that is a joy to contribute to.

Leaflet offers much more flexibility for story-mapping than many other tools used for such projects; on the other hand, it does demand a basic knowledge of coding in JavaScript.

Here, we walk through the basic steps of setting up a Leaflet map, adding spatial data, and creating popup boxes that go along with that data. Though there are many ways to organize your map files, here we will first create a basic HTML file that will hold your map and then a second JavaScript file that will contain the code for the map and spatial data. To download all the tutorial files discussed in this lesson, click below or visit our GitHub page!

Also, see Leaflet's own Quick Start Guide for an introductory tutorial

How to Set Up the Leaflet JS Library and your HTML page

Your map needs to be situated on an HTML page in order for it to function. Luckily, it only takes a few steps to get this up and running.

Create an empty folder to hold your map files, and then in the folder new text file in a text editor and save it as index.html. I recommend using Notepad++ (Windows only) or Atom, as your text editor, as these are designed for coding, rather than regular Notepad or Word. At the top of your file, put the following introductory code to set up your HTML and name your map. Each line is commented to let you know how it is functioning.

<!doctype html> <!-- This says your file is in .html -->
<html lang="en"> <!-- This says your file is in English -->

<head>	<!-- This opens your header. Your header is where different libraries and plugins are loaded -->
  <meta charset="utf-8">
  <title>Put the Title of Your Map Here</title> <!-- Put the title of your map here -->
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />

Next, you need to tell your HTML to access the Leaflet JavaScript library and its associated CSS stylesheet. You have two options for this, as you can either host the files locally on your computer or call them from their already-hosted location on the web.

  • To call them from the web, simply copy these lines into the <head> section of your HTML

 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
 integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
 crossorigin=""/>
   
 <!-- Make sure you put this AFTER Leaflet's CSS -->
 <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
   integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
   crossorigin=""></script>
 
 </head>
  • To host the files locally, download and unzip Leaflet, placing the entire Leaflet folder into the folder with your HTML file. Now, you simply need to change the "href=" and the "src=" links from the above code to the current location of your file. It should end up looking something like this. You can also close your header at this point.

 <!-- Load Leaflet files locally -->
 <link rel="stylesheet" href="./leaflet/leaflet.css"/> <!--Put the path to the leaflet.css  you downloaded here -->
 <script src="./leaflet/leaflet.js"></script>  <!-- Put the path to the leaflet.js you downloaded here -->
 </head>

Any Leaflet plugins that you want to use can be accessed the same way! Many are hosted online, or you can download them and host them locally. In either case, you will call links to their .css and .js files in the HTML header!

Finally, you need to create the container that will hold your map and set its size on the html page, as well as call the JavaScript file that will be your map itself. This will take place in the <body> of your code. And that's it, your html file is done for now!

<!-- In the body of the code, you need to create the division on the page for your map and call the map.js file you will make next -->
<body>
	<div id = "map" style = "width:900px; height:580px;"></div> <!--set the size of your map -->
  <script type="text/javascript" src="nameOfYourMap.js"></script> <!--call the javascript file for your map -->
</body>
</html>

The Javascript file name associated with your map can be anything you'd like, but we recommend tying it to the name of your map for easy association. Remember, capitalization is VERY important to take note of in coding, and no spaces, please!

Starting your Map Javascript File and Loading a World Map Tilelayer

So you've got an HTML file with a map container, but that container is currently totally empty. In this step, we will walk through how to load up an externally hosted world map and show you how to open the HTML file on your own computer. It only takes a few lines of code!

First, create a new empty text file and save it as a javascript file, making sure to use the same file name that you referred to in the HTML file. The first step is to define your map options and create the map object itself. There are a variety of default mapOptions you can set; here we simply choose the center of the map, its initial zoom, and its max zoom level.

var mapOptions = {
 center: [42.336004, -71.169212], //set center Lat/Long of your area of interest
 zoom: 16, //set initial zoom level
 maxZoom : 24,  //set max zoom level
 tap : false //fix popup bug on Safari
 }

//Creates map object according to map options
var map = new L.map('map', mapOptions);

Trying to find the coordinates for a specific location? Google Maps makes it easy; just right click and select "What's here?", and the coordinates of that location will appear.

Now you need to load a background map. While it is possible to load a locally hosted tiled map as a background map (which will be discussed in a different tutorial), here we will simply use one of the maps hosted online already by ArcGIS online. Notice that the basemap variable is made up of a few parts: a variable name, a URL for where the layer is located, and attribution information. Other layer options are also possible here, similar to the map options above.

//Example of an externally called basemap
var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
			attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'});

Esri_WorldImagery.addTo(map);

The last line of this code is key; for each variable, you must add it to your named map variable (in this case the "map" defined above) in order for it to appear on your map.

Note that there are several providers of free and open source tiled background maps online, some of which do require you to register. See this excellent previewer for more information and for URLs for various maps.

Now it's time to open your map! This is simple enough: just drag your index.html file into a browser window, and your map should appear, centered on your favorite university library!

Adding Spatial Data to Your Map

Now, we have some background imagery, but what about adding other spatial data? There are lots of ways to add spatial data to your map, depending on what form you want it to take. Here we will talk about two methods: adding points individually and importing points from an excel file or a CSV (comma-separated list) exported from excel.

Adding point data directly to your map via code

Adding point data individually is as easy as one line of code! Just give your point variable a name (here bcLibrary), add the coordinates, and add it to your map!

var bcLibrary= L.marker( [42.336004, -71.169212] ).addTo(map);
//adds marker at designated lat/long

Adding a polygon is just as easy! You just need the coordinates for its corners, like this one which is roughly situated around the library.

var libraryPolygon = L.polygon([
    [42.336477, -71.169550],
    [42.336569, -71.169126],
    [42.335788, -71.168826],
    [42.335728, -71.169314]
]).addTo(map);

Now open your map again, and it should look similar to that below!

Want to stylize your point marker in a unique way? Check out the linked tutorial for more info!

Adding point data from an external source

Sometimes you already have your spatial data in an external location (either in an excel file or on another platform) and you want to import it fully formed into your map. In order to do this, you need to convert your data into a geoJSON format, a standard spatial format for data that is able to be easily imported into Leaflet.

  • For spatial software like ArcGIS or QGIS, such a transformation is easy. You can export files like shapefiles or geodatabase files directly into GeoJSON files to import into Leaflet. Check out the linked pages for more information.

  • From software like GoogleEarth, you first want to export your data as a .kml file. From here, there are many free online platforms like MyGeodataConverter that can convert the files to GeoJSONs for you!

  • Finally, you can convert your data even if it is in a simple excel file. The key here is to export your file as a .csv. Then, similar to .kml files, there are opensource tools online that will convert it for you.

Remember! To convert your excel files make sure you have individual columns with the Latitude and Longitude data for each point of interest! This is vital for converting your point data to the needed form with its spatial data.

Great! Now you've got your .geojson file; it's time to get it into your map.

  • First, make sure a copy of your .geojson file is in the folder with your HTML and map javascript files.

Now, there are 2 different ways forward here:

  • You can simply copy and paste the entire .geojson into your code, if desired (see an example here). Simply set it equal to a variable and you are good to go. On the downside, this approach both clutters up your code, potentially making it very long, and makes it more difficult to find and change any desired attributes

//example code from leafletjs.com, in this case inserted directly into your map code
var states = [{
    "type": "Feature",
    "properties": {"party": "Republican"},
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-104.05, 48.99],
            [-97.22,  48.98],
            [-96.58,  45.94],
            [-104.03, 45.94],
            [-104.05, 48.99]
        ]]
    }
}, {
    "type": "Feature",
    "properties": {"party": "Democrat"},
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-109.05, 41.00],
            [-102.06, 40.99],
            [-102.03, 36.99],
            [-109.04, 36.99],
            [-109.05, 41.00]
        ]]
    }
}];
  • A second approach is to enter the GeoJSON file itself, set the data equal to a variable (same as was done above), and then resave the file as a .js Javascript file. If this approach is taken, you must also call the javascript file in the header of your .html page, just as you called the Leaflet javascript file. In doing this, you make your variable accessible within your map. The below spatial data was created in google earth, exported as a .kml file, converted to a .geojson using the method described above for KML files, and then saved as a .js Javascript file after adding the variable name. Each file in this process can be seen in the files associated with this tutorial

//this looks the same as above, but now is done directly in the
//geojson file, which should be resaved as a .js file
var bcKMLTest = {

    "type": "FeatureCollection",
    "name": "Temporary Places",
    "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },

    "features": [
        {   "type": "Feature", 
            "properties": { 
                "Name": "Chestnut Hill Reservoir", 
                "description": "Water! " }, 
                "geometry": { "type": "Point", "coordinates": [ -71.160451098751224, 42.335235738372397 ] } },
        
        {   "type": "Feature", 
            "properties": { 
                "Name": "Football!", 
                "description": "Go Eagles!" }, 
                "geometry": { "type": "Point", "coordinates": [ -71.166387763840049, 42.335024576048127 ] } },
        
        {   "type": "Feature", 
            "properties": { 
                "Name": "Basketball and Hockey", 
                "description": "Go Sports!" }, 
                "geometry": { "type": "Point", "coordinates": [ -71.16777265141657, 42.335122222222218 ] } }
    ]
}
//example of html header to call your spatial data
<script src="./bcKMLTest.js"></script>

Now, your external data is linked within your map's code, but it still needs to be added to the map! Whichever of the above two methods you used, the following line of code will add the data to your map

//with the external js holding your data, only this line of code needs to be added to add your data to the map
L.geoJSON(bcKMLTest).addTo(map);

A third bonus method for importing your .geojson! You can simply leave the geoJSON file as it is and use a plugin to bring your data in. See the AJAX geoJSON plugin for more information. Using this method means that some standard methods for manipulating the data within your map will not be available, however.

Some browsers will not let you view GeoJSON files locally in a browser window, due to CORS security issues. See here for instructions on how to enable CORS in Firefox and IE.

Adding Popups

So now you have some points, lines, or polygons on your map, but what do they mean? For example, in Google Earth, we added names and descriptions to our points, but that information is not yet visible in our Leaflet map. Popup boxes attached to your data can offer more information to those using your maps. And making them is quite simple!

Let's look back at the first marker we used to indicate the O'Neill Library (named bcLibrary). To create a popup box for this, we simply use one line of code. Then clicking on the point creates our popup!

bcLibrary.bindPopup("<b>I'm the Boston College Library</b>");

Note how you can use HTML styling methods like <b> to style your text (in this case, to make it bold).

If you are importing large amounts of spatial data, sometimes it already has attribute data attached to it. For example, in our GeoJSON data imported from Google Earth above, each point already had a "Name" and "description" attribute. Instead of retyping that into our code, we can call the attribute directly in our popups!

When importing your spatial data, you can automatically create a popup for every piece of spatial data in your dataset. We do this by adding the "onEachFeature" option when adding the GeoJSON to the map; here, this calls a function called "popUp" which will use to define our popup.

var ourImportedData = L.geoJSON(bcKMLTest, {
    onEachFeature: popUp
}).addTo(map);

Now you can write and customize a function called popUp to create whatever type of popup information you want!

//if your features come with various attributes already attached to them,
//this function will create your popup box based on those features!

function popUp(feature, layer) {
    var out = [];
		if (f.properties){
		     out.push("The name of location is is: " + feature.properties.Name);
		     out.push("The description of the location is:" + feature.properties.description);
		     out.push("Have a nice day!");
		}
		layer.bindPopup(out.join("<br />"));
}

Now every piece of spatial information in your Google Earth geojson will have a popup box saying the name of the space it is associated with (assuming it has an attribute titled "name" that it was imported with, such as a header from an excel spreadsheet) and its description, and it will wish you a nice day!

There are many other things you can do with popups, including addeding images, videos, and hyperlinks. Check out the Leaflet documentation for much more info about popup boxes.

Sharing your map online

The easiest way to immediately share your map online is to upload it to GitHub.

1) Create a GitHub account

2) Click Start a Project, which will then ask you to name your project and provide a brief description.

3) Upload your entire mapping folder into the project depository by clicking Upload an existing file on the main repository page

Now that your map files are in, anyone with access to your repository can download your mapping files. You can also set up a unique url to display your map in just a few easy steps

1) Go to Settings on the central toolbar

2) Scroll down to the Github Pages portion of the settings

3) Under "Source" select Branch: main to set your main branch as the viewable page. Then hit Save.

4) The page will refresh. If you scroll back down, you should now see a statement in the Github Pages portion saying: Your site is ready to be published at YYY. Now you have a URL for your map! You can share this URL with others or put it on the main page of your repository in the About or Readme sections.

That's all for now! In the future, there will be tutorials on how to add new raster layers to your map, turn on and off layers, and other functions!

Last updated