Metro Maps

Visualize your career as metro map

About

Showcasing Metro Maps

At some point in time, when putting my resume together for a job application, I was looking for examples of great resumes. I stumbled upon resumes in the form of a metro or subway map - like the iconic London tube map or NY City's MTA map. I kind of always found the subway style maps pretty cool, when they were used to visualize technology trends, the web, music, vendors or even cancer pathways. I liked how they provided a different view and structure to a topic.

When digging around, I found a ton of info on transit maps and especially their automatig generation, e.g. Automatic Metro Map Layout Using Multicriteria Optimization or Automtatic Generation of Transit Maps. However I did not go so far to have the metro map representing my career automatically generated. Understanding and implementing the algorithms was more work than I was willing to invest. Maybe later in case I use metro maps more often.

Nevertheless I also did not want to compeltely draw the lines and stations manually. Some kind of script would be nice. I found the Subway Map Visualization jQuery Plugin by Nik Kalyani and created my own little fork from it. Sticking with the original idea of defining the structure of the metro map as HTML elements and having a script generating the metro map from it. However I forked it, because i wanted to generate a Scalable Vector Graphics (SVG) intead of painting on HTML canvas. I deemed SVGs easier to reuse in other contexts. Design wise there is also tons of work out there, but the most inspiration I found from Robert Aehnelt's work.

My Metro Map

Visualizating my career as metro map

Step by Step

Creating your first metro map

Metro Map uses unordered HTML lists to define the metro lines. The basic HTML markup consists of the following:
  • An outer div element to control general placement, background etc.
  • One ul element for each metro line desired in the map
  • For each ul element, multiple li elements defining the coordinates for the line and its stations.
Each of the div, ul and li elements make use of custom attributes to define how the map should be rendered. These are explained step by step in the sections below.

Map container

An empty canvas for your metro map

246810121416182022242628302468101214161820

To create a map, you first need to prepare the map container. A div element with class metroMap-map will do.

In the data attributes of the div element, you can specify the number of columns (data-columns) and rows (data-rows) for the map. Together with the cell size (default:10px), this will determine the map size.

The grid has its origins at the top left. X coordinates extend from left to right. Y coordinates extend from top to bottom.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
</div>
                        
                    

Horizontal lines

Your first metro line

246810121416182022242628302468101214161820

To add a line to the map, add an unordered list (ul) to the div container element. In the data attribute data-color, you specify the color for the line. Any RGB color code as well as HTML color names will do, e.g. "#ee352e" or "red".

Each line is drawn along specified nodes. You can specify a node in a list item (li) element. In the data attribute data-coords you specify the x and y coordinate for the node. data-coords="5,6" adds a node in the fifth column and sixth row.

Two subsequent nodes with the same y coordinate and a different x coordinate create a horizontal line.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
  <ul data-color="#ee352e">
    <li data-coords="5,6"></li>
    <li data-coords="17,6"></li>
  </ul>
</div>
                        
                    

Stations

Adding stops to your metro line

246810121416182022242628302468101214161820First StationSecond Station

Your metro can stop at any of the nodes defined for your line. To make the metro stop at a node, just add a station name to the text content of the li element.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6">Second Station</li>
  </ul>
</div>    
                        
                    

Line Building

Entending your metro line

246810121416182022242628302468101214161820First StationSecond Station

Your metro can stop at a node, but does not have too. Nodes without text are structural to define the path of the line.

You can add one more node by adding an additional li element.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6">Second Station</li>
    <li data-coords="26,6"></li>
  </ul>
</div>        
                        
                    

Vertical Lines

Building into another direction

246810121416182022242628302468101214161820First StationSecond StationThird Station

Being able to take the metro in just one direction is not enough. Similar to horizontal lines, you can add vertical lines.

You can add one more node for an additional station south of the current metro line. When the new li element has the same x coordinates, but a different y coordinate a vertical line is added.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6">Second Station</li>
    <li data-coords="26,6"></li>
    <li data-coords="26,10">Third Station</li>
  </ul>
</div>            
                        
                    

Curves

Shaping turns properly

246810121416182022242628302468101214161820First StationSecond StationThird Station

Metro trains in the real world usually do not make sharp 90° turns. You can shape the turns more realistic and have nice curves (90° arcs).

To create a curve two conditions need to be met by subsequent nodes:

  • The absolute difference in x and y coordinate need to be the same.
  • The previous line segment has to be a vertical or horizontal line.

In this map the nodes with the coordinates 23,6 and 26,9 fulfill the conditions. The absolute difference in x and in y coordinates both have a value of 3. The line segment before is a horizontal line from 17,6 to 23,6.

                        
<div class="metroMap-map" data-columns="30" data-rows="20">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10">Third Station</li>
  </ul>
</div>            
                        
                    

Further Construction

More line building

2468101214161820222426283024681012141618202224262830First StationSecond StationThird StationFourth StationFifth Station

Adding more li elements, grows your metro line. Curves are not limited in size. You can create turns with a larger or smaller radius.

The first additional curve have a change of -2 in x direction and 2 in y direction - absolute difference of 2. The abolute difference for the second curve is 9, which creates a pretty large curve.

The extension of the line also leads to an effect that two of the station names are overlapping with the line. We'll fix that in the next step.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16">Fourth Station</li>
    <li data-coords="13,25">Fifth Station</li>
    <li data-coords="13,30"></li>
  </ul>
</div>            
                        
                    

Station Names

Adjusting the display of your station names

2468101214161820222426283024681012141618202224262830First StationSecond StationThird StationFourthStationFifth Station

Station names are by default displayed below (south) of the metro line. You can position station names by adding the data attribute data-labelPos to the li item. Potential values are the eight compass directions N, NE, E, SE, S, SW, W and NW.

In this map the label for Fifth station is moved to the East by adding data-labelPos="E" to the li element. In the same way the label for Second station is moved to the North, while the label for Third stations is moved to the West.

Due to the curve of the line, the label for Fourth Station would still overlap with the line. Instead of moving it to another position, you can also adjust its width.

You can define the width in the data attribute data-labelSize of the li element. Potential values are t-shirt sizes XL, L, M, S, XS. A t-shirt size of M results in the default width. In this map the label for Fourth Station is reduced in width by two levels by defining data-labelSize="XS".

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="13,25">Fifth Station</li>
    <li data-coords="13,30" data-labelPos="E"></li>
  </ul>
</div>            
                        
                    

Diagonal Lines

More flexibility for your metro lines

2468101214161820222426283024681012141618202224262830First StationSecond StationThird StationFourthStationFifth Station

In case a larger curve is not the desired look of your map, you can also use a diagonal line instead. Each of the diagonal line consists of three elements:

  • 45° curve starting from a vertical or horizontal line segment and turning into a diagonal line
  • Diagonal straight line segment
  • 45° curve turing the diagonal into a vertical or horizontal line segment again

The direction of the line segment before can be different from the direction of the line segment afterwards. In the map, the line is going in a Western direction and turns to the South-West. From there the line turns to a Southern direction to reach Fifth Station, but it could also turn to the West again after the diagonal.

In the map the absolute overall difference in x and y direction is 9 units.

  • The first 45° curve changes x by -2 and y by 1.
  • The diagonal line changes x by -6 and y by 6 units
  • The second 45° curve finally changes x by -1 and y by 2.

See reference for more examples of commonly used elements.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25">Fifth Station</li>
    <li data-coords="13,30" data-labelPos="E"></li>
  </ul>
</div>            

                        
                    

Adding metro lines

More lines for your metro

2468101214161820222426283024681012141618202224262830First StationSecondStationThird StationFourthStationFifth StationAlpha Station

For an additional line, you can add another ul element, specify data-color and add li elements to specify nodes. In the map there is now an additional line that comes in from the North and goes in a straight line to the South, with only one station.

Note: To avoid an overlap of the station name for Second Station, its label was resized by specifying data-labelSize="XS".

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25" data-labelPos="E">Fifth Station</li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,30"></li>
  </ul>    
</div>            
                        
                    

Crossing Interchange

Creating an interchange for crossing metro lines

2468101214161820222426283024681012141618202224262830First StationSecondStationThird StationFourthStationFifth StationInterchangeCrossingAlpha Station

When adding a new line in the step before, the new line was crossing the existing line, but passengers had no way of changing between stations. To define an interchange just add a node to one of the crossing lines at the coordinates of the intersection of the two lines. All intersections have to have a name, so you need to specify a name in the text of the li element.

The data-marker attribute is set to the value interchange to specify that you want to build an interchange. The first line defines, the outer ring color, while the second color defines the inner circle color. In case you want to use the opposite colors, you can set the data-inverseColors attribute to true.

Naturally at a crossing interchange the station name would overlap with the vertical line segment. Therefore the attribute data-labelPos="NW" is defined to positon the label.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6" >First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25" data-labelPos="E">Fifth Station</li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-inverseColors="true" data-labelPos="NW">Interchange Crossing</li>
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,30"></li>
  </ul>    
</div>            
                        
                    

Parallel Interchange

Creating an interchange for your parallel lines

2468101214161820222426283024681012141618202224262830First StationSecondStationThird StationFourthStationInterchangeCrossing Alpha StationFifth Station

Changing between lines is not only possible when lines are crossing. You can also add interchanges between parallel metro lines. In this map you might want to convert Fifth Station to an interchange that connects the two metro lines.

To start the conversion, first the node with the interchange needs to be moved to the left line. You always have to have the interchange on the left or top most of the lines included. To do that you need to remove the station name from node at the right line and add a node on the left line instead.

Creating an interchange works like before by setting the attributes for an interchange (data-marker="interchange"). In addition to create an interchange between parallel lines you have to set the attribute to indicate the horizontal interchange type data-interchangeDirection="horizontal" and the attribute to indicate the size data-size="2"

Note: The station name was also moved to the West by setting data-labelPos="W".

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="2" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>    
</div>
                        
                    

Under construction

Adding a future extension to your lines

2468101214161820222426283024681012141618202224262830First StationSecondStationThird StationFourthStationInterchangeCrossing Alpha StationFifth StationNewStation

When your metro keeps growing you might add another line coming from the South, making a turn and leaving to the West. This new line might partially still be under construction. For now the last finished station is New Station, but construction already started for the extension.

You can indicate a line segment being under construction by setting the data attribute data-underConstruction="true". This will draw the line segment from the previous node to this node as dotted line.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="2" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>            
                        
                    

Extending an interchange

Creating more options to change between your lines

2468101214161820222426283024681012141618202224262830First StationSecondStationThird StationFourthStationInterchangeCrossing Alpha StationFifth StationNewStation

The newly added line might also have a connection to the other lines at Fifth Station. The new line is not exactly a neighbor of the other two lines, but the interchange can still be extended to include it.

Just increase the data-size attribute to span the interchange all the way to the additional line. The gap will be bridged automatically.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="5,6">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="5" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>                        
                        
                    

Line Indicator

Adding an indicator for the name or number to you lines

2468101214161820222426 2830246810121416182022242628301FirstStationSecondStationThird StationFourthStationInterchangeCrossingAlpha StationFifth StationNewStation

To give the user an indication about the line name or line number, you might want to add an indicator to the end of the line. An indicator includes one letter or one number.

You can add an indicator by adding a new node (li) at the beginning of the line - usually a short distance before the first station of the line. Set the data attribute for data-marker to the value of terminal and specify the character in the text of the li element.

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="2,6" data-marker="terminal">1</li>
    <li data-coords="5,6" data-labelSize="XS">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W">Alpha Station</li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="5" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>                        
                        
                    

Hyperlinks

Adding links to your station names

2468101214161820222426 2830246810121416182022242628301FirstStationSecondStationThird StationFourthStationInterchangeCrossingAlpha StationFifth StationNew Station

To add a hyperlink to one of your station names, just wrap it in a link tag a. As usual in HTML set the href attribute to the url you want to link to. Optionally you can also set the title attribute to add a description of the link target.

You can also use Bootstrap Modals instead of standard hyperlinks. Add the data-toggleTarget attribute to the node li element and set the value to the id of the modal you want to trigger, e.g. data-target="#exampleModal".

                        
<div class="metroMap-map" data-columns="30" data-rows="30">
  <ul data-color="#ee352e">
    <li data-coords="2,6" data-marker="terminal">1</li>
    <li data-coords="5,6" data-labelSize="XS">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W"><a href="https://en.wikipedia.org/wiki/Alpha">Alpha Station</a></li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="5" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS" data-toggleTarget="#newStationModal">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>                        
                        
                    

Legend

Adding a legend to your map

246810121416182022242628 30246810121416182022242628301FirstStationSecondStationThird StationFourthStationInterchangeCrossingAlpha StationFifth StationNew Station

Legend

1Line 1
2Line 2
3Line 3

You might want to add a legend to your metro map to give further information on your lines and metro map. For an automatic list of your metro lines you can add a new container, e.g. a div element to your page, to hold the generated list. This container needs to have an id set, e.g. id="legend".

To connect the metro map to the legend container, you have to specify the id in the data attribute data-legendId of the map container, e.g. data-legendId="legend". The legend does not have to be next to the map container, it can be positioned anywhere on the page.

The generated list includes a terminal marker with a short line segment as well as the line name. By default the lines are numbered automatically. In the next step, you'll learn how to change the line names manually.

                        
<div class="metroMap-map" data-columns="30" data-rows="30" data-legendId="legend">
  <ul data-color="#ee352e">
    <li data-coords="2,6" data-marker="terminal">1</li>
    <li data-coords="5,6" data-labelSize="XS">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W"><a href="https://en.wikipedia.org/wiki/Alpha">Alpha Station</a></li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="5" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS" data-toggleTarget="#newStationModal">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>
<div class="">
  <h3>Legend</h3>
  <div id="legend"> </div>
</div>
                        
                    

Line Labels

Naming your metro lines

24681012141618202224262830246810 12141618202224262830FFirstStationSecondStationThird StationFourthStationInterchangeCrossingAlpha StationFifth StationNew Station

Legend

FFirst Line
EExtension Line
DEastern District Line

As seen in the previous step, the lines are numbered automatically by default. You can manually set a different name for a line by setting the data-label attribute on the ul element defining a line. After this change the legend shows the line name and the terminal marker in the legend shows the first character of the specified line name.

If you followed the step by step tutorial so far, you might notice that the terminal marker in the map shows 1 while the marker in the legend shows F. This is an artifact of the earlier mechanism to allow you to have a terminal without a line label. Remove the text content of the li element defining the terminal and the line labels will match.

When adding multiple lines you might end up in a situation where the first character of your line names is the same. You can manually specify the character used in the terminal markers. To do so, set the attribute data-labelShort of the ul element defining the line.

                        
<div class="metroMap-map" data-columns="30" data-rows="30" data-legendId="legend">
  <ul data-color="#ee352e" data-label="First Line">
    <li data-coords="2,6" data-marker="terminal"></li>
    <li data-coords="5,6" data-labelSize="XS">First Station</li>
    <li data-coords="17,6" data-labelPos="N" data-labelSize="XS">Second Station</li>
    <li data-coords="23,6"></li>
    <li data-coords="26,9"></li>
    <li data-coords="26,10" data-labelPos="W">Third Station</li>
    <li data-coords="26,14"></li>
    <li data-coords="24,16"></li>
    <li data-coords="22,16" data-labelSize="XS">Fourth Station</li>
    <li data-coords="20,17"></li>
    <li data-coords="14,23"></li>
    <li data-coords="13,25"></li>
    <li data-coords="13,30"></li>
  </ul>
  <ul data-color="#996633" data-label="Extension Line">
    <li data-coords="12,0"></li>
    <li data-coords="12,6" data-marker="interchange" data-labelPos="NW">Interchange Crossing</li>                                
    <li data-coords="12,13" data-labelPos="W"><a href="https://en.wikipedia.org/wiki/Alpha">Alpha Station</a></li>
    <li data-coords="12,25" data-labelPos="W" data-marker="interchange" data-size="5" data-interchangeDirection="horizontal">Fifth Station</li>
    <li data-coords="12,30"></li>
  </ul>  
  <ul data-color="#00933c" data-label="Eastern District Line" data-labelShort="D">
    <li data-coords="16,30"></li>
    <li data-coords="16,20"></li>
    <li data-coords="12,16"></li>
    <li data-coords="8,16" data-labelSize="XS" data-toggleTarget="#newStationModal">New Station</li>                            
    <li data-coords="1,16" data-underConstruction="true"></li>
  </ul>
</div>
<div class="">
  <h3>Legend</h3>
  <div id="legend"> </div>
</div>
                        
                    

Integration

Getting Metro Maps to work

Metro Maps consists of a single Javascript file and an accompanying stylesheet. In the current version there is a dependency on jQuery - I'm using 3.2.1 currently. It's planned to remove the jQuery dependency in the next major version.

To include the necessary scripts, include the following code at the bottom of your HTML body:

                        
        <script src="vendor/jquery/jquery.min.js"></script>
        <script src="metroMap.js"></script>        
                        
                    

To trigger the generation of the metro maps in the page, include the following code at the bottom of your HTML body below the script inclusion:

                        
        <script>
            $(".metroMap-map").metroMap({ debug: true });
        </script>
                        
                    

To apply the styles for the metro maps, also include the stylesheet as part of the the HTMl head element:

                        
        <link href="metroMap.css" rel="stylesheet" />
                        
                    

Reference

All the details you might be interested in

The map - div.metroMap-map

The container element is usually of the type div and is identified by class="metroMap-map". It can hold additional data attributes to configure the overall metro map.

Attribute Default Description
data-rows 40 The number of rows (y dimension) of the metro map.
data-columns 40 The number of columns (x dimension) of the metro map.
data-cellSize 10 The size of each cell in pixels. The resulting size of the grid depends on this value and the values for rows and columns. For example, a cellSize of 10 and specify a grid of 20 columns by 10 rows, then you will have a map that is 200 pixels wide and 100 pixels high.
data-lineWidth 8 The width of the metro lines in pixels.
data-legendId The id of the HTML element that acts as placeholder for the legend generation. If none is specified, then no legend is generated.
data-grid false Toggle to show/hide the data grid - useful during design/debugging of a metro map.
data-gridNumbers false Toggle to show/hide the numbers for the data grid - useful during design/debugging of a metro map.
data-reverseMarkers false Deprecated option to inverse colors of a station. Do not use, will be removed in the next version.
data-textClass Value to be added to the class attribute of the text contents (e.g. station names).

The line - ul

A line is defined as unordered list ul element inside the map container. It can hold additional data attributes to configure the metro line.

Attribute Default Description
data-color #000000 The color to be used for the metro line. Either hexadecimal color values or HTML color names will work.
data-textClass Text class set for map Value to be added to the class attribute of the text contents (e.g. station names) - overrides the value set for the map for this specific line.
data-label Automatic Line numbering (e.g. 'Line 1') Label for the metro line to be used in legend. If nothing is set, the lines are automatically numbered.
data-labelShort Number of line or first character of line label Character to be shown in the terminal for the metro line. If nothing is set, the number of the line or the first character of the line label is used.

The line node - li

A node in a metro line is defined as list item li. Nodes can be structural to define the pathway of the metro line. Nodes can also represent stations, interchanges and terminals by adding additional data attributes.

For nodes representing stations or interchanges, the text content of the list item element defines the name of the station/interchange.

Attribute Default Description
data-coords Mandatory attribute for all nodes, defining the position of the node in the grid in the format x,y (e.g. data-coords="5,2" for a node in the fifth column and the second row in the grid).
data-curveDirection Deprecated option to specify the direction of a curve. Do not use, will be removed in the next version.
data-labelPos S Position of the label for a station or interchange. Possible values are the eight compass directions N, NE, E, SE, S, SW, W and NW.
data-labelSize S Size of the label for a station or interchange. Possible values are t-shirt sizes XL, L, M, S, XS.
data-marker

For an interchange between parallel lines the left or top most line can define a station by adding the station name as text content. To convert this station to a parallel interchange, the data-marker can be set to interchange. This needs to go hand in hand with setting the data-interchangeDirection and data-size.

To show a terminal (usually at the start or end of the line), the data-marker can be set to terminal. A terminal station shall not have any textual content. The character to be shown in the terminal, is determined by the data-labelShort or data-label attribute of the corresponding metro line.

data-interchangeDirection For parallel interchanges this attribute shall be set to horizontal or vertical to define the direction of the interchange. Parallel interchanges always start from the left or top most node - if necessary the interchange node need to be moved to the line including the left/top most node.
data-size For parallel interchanges this attribute is used to define the size of the interchange. The number of grid ticks start counting from the left/top most node.
data-toggleTarget Hyperlinks can be set using the standard HTML mechanism. In cases when Bootstrap modals shall be used, this attribute can be set to the id of the modal that shall be opened (e.g. data-target="#exampleModal").
data-underConstruction Setting this attribute to true, will draw the line segment from the previous node to this node as dotted line.
data-inverseColors Deprecated option to inverse colors of a station. Do not use, will be removed in the next version.

Reference Elements

Showcasing commonly used elements

24681012141618202224262830323436384042444648 50525456586062646668707274 767880246810121416182022242628303234363840 42 44464850525456586062646668707274767880 AB CDEFGHIJKLMNOPQRS
                        
    <div class="metroMap-map" data-columns="80" data-rows="80" data-cellSize="10" data-legendId=""
    data-textClass="text" data-gridNumbers="true" data-grid="true" data-lineWidth="8">
    <ul data-color="#ee352e">
        <li data-coords="10,10" data-marker="terminal">A</li>
        <li data-coords="20,10"></li>
        <li data-coords="22,9"></li>
        <li data-coords="25,6"></li>
        <li data-coords="26,4"></li>
        <li data-coords="26,2"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="10,14" data-marker="terminal">B</li>
        <li data-coords="20,14"></li>
        <li data-coords="22,13"></li>
        <li data-coords="25,10"></li>
        <li data-coords="27,9"></li>
        <li data-coords="29,9"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="10,18" data-marker="terminal">C</li>
        <li data-coords="20,18"></li>
        <li data-coords="22,19"></li>
        <li data-coords="25,22"></li>
        <li data-coords="27,23"></li>
        <li data-coords="29,23"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="10,22" data-marker="terminal">D</li>
        <li data-coords="20,22"></li>
        <li data-coords="22,23"></li>
        <li data-coords="25,26"></li>
        <li data-coords="26,28"></li>
        <li data-coords="26,30"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="60,10" data-marker="terminal">E</li>
        <li data-coords="50,10"></li>
        <li data-coords="48,9"></li>
        <li data-coords="45,6"></li>
        <li data-coords="44,4"></li>
        <li data-coords="44,2"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="60,14" data-marker="terminal">F</li>
        <li data-coords="50,14"></li>
        <li data-coords="48,13"></li>
        <li data-coords="45,10"></li>
        <li data-coords="43,9"></li>
        <li data-coords="40,9"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="60,18" data-marker="terminal">G</li>
        <li data-coords="50,18"></li>
        <li data-coords="48,19"></li>
        <li data-coords="45,22"></li>
        <li data-coords="43,23"></li>
        <li data-coords="40,23"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="60,22" data-marker="terminal">H</li>
        <li data-coords="50,22"></li>
        <li data-coords="48,23"></li>
        <li data-coords="45,26"></li>
        <li data-coords="44,28"></li>
        <li data-coords="44,30"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="10,60" data-marker="terminal">I</li>
        <li data-coords="10,54"></li>
        <li data-coords="9,52"></li>
        <li data-coords="6,49"></li>
        <li data-coords="4,48"></li>
        <li data-coords="2,48"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="14,60" data-marker="terminal">J</li>
        <li data-coords="14,54"></li>
        <li data-coords="13,52"></li>
        <li data-coords="10,49"></li>
        <li data-coords="9,47"></li>
        <li data-coords="9,45"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="18,60" data-marker="terminal">K</li>
        <li data-coords="18,54"></li>
        <li data-coords="19,52"></li>
        <li data-coords="22,49"></li>
        <li data-coords="23,47"></li>
        <li data-coords="23,45"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="22,60" data-marker="terminal">L</li>
        <li data-coords="22,54"></li>
        <li data-coords="23,52"></li>
        <li data-coords="26,49"></li>
        <li data-coords="28,48"></li>
        <li data-coords="30,48"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="50,40" data-marker="terminal">M</li>
        <li data-coords="50,44"></li>
        <li data-coords="49,46"></li>
        <li data-coords="46,49"></li>
        <li data-coords="44,50"></li>
        <li data-coords="40,50"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="54,40" data-marker="terminal">N</li>
        <li data-coords="54,44"></li>
        <li data-coords="53,46"></li>
        <li data-coords="50,49"></li>
        <li data-coords="49,51"></li>
        <li data-coords="49,53"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="58,40" data-marker="terminal">O</li>
        <li data-coords="58,44"></li>
        <li data-coords="59,46"></li>
        <li data-coords="62,49"></li>
        <li data-coords="63,51"></li>
        <li data-coords="63,53"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="62,40" data-marker="terminal">P</li>
        <li data-coords="62,44"></li>
        <li data-coords="63,46"></li>
        <li data-coords="66,49"></li>
        <li data-coords="68,50"></li>
        <li data-coords="70,50"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="10,70" data-marker="terminal">Q</li>
        <li data-coords="14,70"></li>
        <li data-coords="20,70"></li>
        <li data-coords="22,71"></li>
        <li data-coords="25,74"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="30,70" data-marker="terminal">R</li>
        <li data-coords="40,70"></li>
        <li data-coords="44,72"></li>
        <li data-coords="46,74"></li>
    </ul>
    <ul data-color="#ee352e">
        <li data-coords="50,70" data-marker="terminal">S</li>
        <li data-coords="60,70"></li>
        <li data-coords="66,73"></li>
        <li data-coords="67,74"></li>
    </ul>
</div>