Fork Me on GitHub
{ "layout":"odd-r", "hexes": { "0-0":{"q":0,"r":0}, "0-1":{"q":1,"r":0}, "0-2":{"q":2,"r":0}, "0-3":{"q":3,"r":0}, "0-4":{"q":4,"r":0}, "0-5":{"q":5,"r":0}, "0-6":{"q":6,"r":0}, "0-7":{"q":7,"r":0}, "0-8":{"q":8,"r":0}, "0-9":{"q":9,"r":0}, "0-10":{"q":10,"r":0}, "0-11":{"q":11,"r":0}, "0-12":{"q":12,"r":0}, "0-13":{"q":13,"r":0}, "0-14":{"q":14,"r":0}, "0-15":{"q":15,"r":0}, "0-16":{"q":16,"r":0}, "0-17":{"q":17,"r":0}, "0-18":{"q":18,"r":0}, "0-19":{"q":19,"r":0}, "0-20":{"q":20,"r":0}, "0-21":{"q":21,"r":0}, "0-22":{"q":22,"r":0}, "0-23":{"q":23,"r":0}, "0-24":{"q":24,"r":0}, "0-25":{"q":25,"r":0}, "0-26":{"q":26,"r":0}, "0-27":{"q":27,"r":0}, "0-28":{"q":28,"r":0}, "0-29":{"q":29,"r":0}, "0-30":{"q":30,"r":0}, "0-31":{"q":31,"r":0}, "0-32":{"q":32,"r":0}, "0-33":{"q":33,"r":0}, "0-34":{"q":34,"r":0}, "1-0":{"q":0,"r":1}, "1-1":{"q":1,"r":1}, "1-2":{"q":2,"r":1}, "1-3":{"q":3,"r":1}, "1-4":{"q":4,"r":1}, "1-5":{"q":5,"r":1}, "1-6":{"q":6,"r":1}, "1-7":{"q":7,"r":1}, "1-8":{"q":8,"r":1}, "1-9":{"q":9,"r":1}, "1-10":{"q":10,"r":1}, "1-11":{"q":11,"r":1}, "1-12":{"q":12,"r":1}, "1-13":{"q":13,"r":1}, "1-14":{"q":14,"r":1}, "1-15":{"q":15,"r":1}, "1-16":{"q":16,"r":1}, "1-17":{"q":17,"r":1}, "1-18":{"q":18,"r":1}, "1-19":{"q":19,"r":1}, "1-20":{"q":20,"r":1}, "1-21":{"q":21,"r":1}, "1-22":{"q":22,"r":1}, "1-23":{"q":23,"r":1}, "1-24":{"q":24,"r":1}, "1-25":{"q":25,"r":1}, "1-26":{"q":26,"r":1}, "1-27":{"q":27,"r":1}, "1-28":{"q":28,"r":1}, "1-29":{"q":29,"r":1}, "1-30":{"q":30,"r":1}, "1-31":{"q":31,"r":1}, "1-32":{"q":32,"r":1}, "1-33":{"q":33,"r":1}, "1-34":{"q":34,"r":1}, "2-0":{"q":0,"r":2}, "2-1":{"q":1,"r":2}, "2-2":{"q":2,"r":2}, "2-3":{"q":3,"r":2}, "2-4":{"q":4,"r":2}, "2-5":{"q":5,"r":2}, "2-6":{"q":6,"r":2}, "2-7":{"q":7,"r":2}, "2-8":{"q":8,"r":2}, "2-9":{"q":9,"r":2}, "2-10":{"q":10,"r":2}, "2-11":{"q":11,"r":2}, "2-12":{"q":12,"r":2}, "2-13":{"q":13,"r":2}, "2-14":{"q":14,"r":2}, "2-15":{"q":15,"r":2}, "2-16":{"q":16,"r":2}, "2-17":{"q":17,"r":2}, "2-18":{"q":18,"r":2}, "2-19":{"q":19,"r":2}, "2-20":{"q":20,"r":2}, "2-21":{"q":21,"r":2}, "2-22":{"q":22,"r":2}, "2-23":{"q":23,"r":2}, "2-24":{"q":24,"r":2}, "2-25":{"q":25,"r":2}, "2-26":{"q":26,"r":2}, "2-27":{"q":27,"r":2}, "2-28":{"q":28,"r":2}, "2-29":{"q":29,"r":2}, "2-30":{"q":30,"r":2}, "2-31":{"q":31,"r":2}, "2-32":{"q":32,"r":2}, "2-33":{"q":33,"r":2}, "2-34":{"q":34,"r":2} } }
stuquery.hexmap.js (13kB) stuquery.hexmap.css (1kB)

stuQuery hexmap

This is a simple HTML-based hexmapping library that makes use of stuQuery. Being created from simple HTML elements, it is easy to style the hexes with CSS. Each hex is accessible via the keyboard too.

As HTML is based on rectangles, we've had to create hexagons using CSS's clip-path. We've simulated a border on each hexagon by nesting two elements and setting the border-color by using background-color on the outer element and border-width by using margin on the inner element.

Make sure to include the relevant CSS and Javascript files in your HTML page:

Basic hex map

Let's create a simple hex map. We define the hex map by embedding some HexJSON (that way the raw data is visible if Javascript fails).

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Custom label on each hex

Let's create a simple hex map but add a visible label to each hex.

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Extra labels on select

Now we'll add labels to each hex which have elements that are always visible and elements that only appear when the hex is selected or hovered.

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Hex-specific colours

Sometimes you might want to make your hex map into a heat map. To do that we send a callback function that returns an object of the form { 'background-color': '#ff0000', 'color': 'black' }

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Hover styling

As the hexes are created as DOM elements, we can style them with CSS

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Adding callbacks

You may want to make your hexes interactive. You can attach callback functions to events such as click, mouseover, mouseout, and focus.

Click or hover on a hex
{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Update the content

You may want to update the content of your hexes.

{ "layout":"odd-r", "hexes": { "A":{"n":"Hex a","q":0,"r":0}, "B":{"n":"Hex b","q":0,"r":1}, "C":{"n":"Hex c","q":1,"r":0}, "D":{"n":"Hex d","q":1,"r":1}, "E":{"n":"Hex e","q":2,"r":0}, "F":{"n":"Hex f","q":2,"r":1}, "G":{"n":"Hex g","q":0,"r":2}, "H":{"n":"Hex h","q":1,"r":2}, "I":{"n":"Hex i","q":2,"r":2} } }

Settling hex island

Some hexes styled like the starting map of a famous board game.

{ "layout":"odd-r", "hexes": { "A":{"n":"A","q":0,"r":0,"dice":5,"type":"mountains"}, "B":{"n":"B","q":1,"r":0,"dice":2,"type":"fields"}, "C":{"n":"C","q":2,"r":0,"dice":6,"type":"forest"}, "D":{"n":"D","q":2,"r":1,"dice":3,"type":"mountains"}, "E":{"n":"E","q":3,"r":2,"dice":8,"type":"fields"}, "F":{"n":"F","q":2,"r":3,"dice":10,"type":"pasture"}, "G":{"n":"G","q":2,"r":4,"dice":9,"type":"fields"}, "H":{"n":"H","q":1,"r":4,"dice":12,"type":"pasture"}, "I":{"n":"I","q":0,"r":4,"dice":11,"type":"forest"}, "J":{"n":"J","q":-1,"r":3,"dice":4,"type":"hills"}, "Robber":{"n":"Robber","q":-1,"r":2,"dice":7,"type":"desert"}, "K":{"n":"K","q":-1,"r":1,"dice":8,"type":"hills"}, "L":{"n":"L","q":0,"r":1,"dice":10,"type":"pasture"}, "M":{"n":"M","q":1,"r":1,"dice":9,"type":"pasture"}, "N":{"n":"N","q":2,"r":2,"dice":4,"type":"forest"}, "O":{"n":"O","q":1,"r":3,"dice":5,"type":"hills"}, "P":{"n":"P","q":0,"r":3,"dice":6,"type":"mountains"}, "Q":{"n":"Q","q":0,"r":2,"dice":3,"type":"forest"}, "R":{"n":"R","q":1,"r":2,"dice":11,"type":"fields"} } }

London 1895

Re-creating "The Unification of London: The Need and the Remedy", John Leighton, page 14, 1895 released by the British Library to the Public Domain.

N
E
W
S
{ "layout":"odd-q", "hexes": { "A":{"n":"1a","q":0,"r":2,"label":"Horn
sey","type":"horizontal"}, "B":{"n":"2a","q":1,"r":2,"label":"Hack
ney","type":"horizontal"}, "C":{"n":"3a","q":2,"r":1,"label":"Old
Ford","type":"horizontal"}, "D":{"n":"4a","q":2,"r":0,"label":"Poplar","type":"horizontal"}, "E":{"n":"5a","q":2,"r":-1,"label":"Dept
ford","type":"horizontal"}, "F":{"n":"6a","q":1,"r":-1,"label":"Peck
ham","type":"horizontal"}, "G":{"n":"7a","q":0,"r":-2,"label":"Brix
ton","type":"horizontal"}, "H":{"n":"8a","q":-1,"r":-1,"label":"Batter
sea","type":"horizontal"}, "I":{"n":"9a","q":-2,"r":-1,"label":"Chel
sea","type":"horizontal"}, "J":{"n":"10a","q":-2,"r":0,"label":"Mary Le Bone","type":"horizontal"}, "K":{"n":"11a","q":-2,"r":1,"label":"St John's Wood","type":"horizontal"}, "L":{"n":"12a","q":-1,"r":2,"label":"Kentish Town","type":"horizontal"}, "M":{"n":"1","q":0,"r":1,"label":"Isling·
ton","type":"vertical"}, "N":{"n":"2","q":1,"r":1,"label":"Bethnal Green","type":"vertical"}, "O":{"n":"3","q":1,"r":0,"label":"South·
wark","type":"vertical"}, "P":{"n":"4","q":0,"r":-1,"label":"Kenning·
ton","type":"vertical"}, "Q":{"n":"5","q":-1,"r":0,"label":"Westmin-
ster","type":"vertical"}, "R":{"n":"6","q":-1,"r":1,"label":"St Pan·
cras","type":"vertical"}, "S":{"n":"","q":0,"r":0,"label":"The
City
"} } }
London indexed by 2-mile hexagons

Hex map from HTML elements

Sometimes you'd rather have a pre-generated hex map in the page as raw HTML rather than a JSON blob that gets converted. You can do that and attach a hexmap object to the element.