Map Style
The MapCSS style file consists of rules that apply to each object from top to bottom.
For example, a style:
node[natural=tree] {
icon-image: "tree.svg";
}
will display a picture of tree.svg
for points where the tag natural
has the value tree
.
Each rule in the style has two parts: the filter node[natural=tree]
and the drawing parameters icon-image: tree.svg;
. The filter determines which objects the parameters apply to.
Rules can be nested and set parameters at each level.
|z16- {
icon-scale: 0.50;
icon-tint: @color_icon_tint;
[amenity=bicycle_parking] {
icon-image: "bike_parking.svg";
}
[amenity=bicycle_rental] {
icon-image: "bike_rental.svg";
}
[amenity=bicycle_repair_station] {
icon-image: "bike_service.svg";
}
}
These nested style rules keep the style concise and structured. You can define shared parameters once and avoid repeating them across multiple blocks.
This documentation describes the MapCSS dialect used in the Guru Maps application. Some original drawing parameters are not implemented, but preprocessing macros, nested rules, and new functions for evaluated operations are available. The style used in Guru Maps can be found in the repository.
Filters
Let's consider a complex filter:
node,area|z14-[boundary=forest_compartment][ref]
It consists of:
- Type filter
node,area
. Usenode
for points,line
for lines,area
for polygons, or separate multiple types with commas. Use*
if the type does not matter. - Zoom filter
z14-
. This specifies the zoom levels where the rule should trigger. You can define only the minimum zoom levelz8-
, or use a range such asz3-9
. In this case the rule applies on zoom levels 3 through 8 inclusive. - Tag filters
[boundary=forest_compartment][ref]
. This keeps only objects with theboundary
tag set toforest_compartment
and any value for theref
tag. To keep objects that do not have theref
tag, use the filter[!ref]
.
Several filters can be separated by a comma:
node,area|z14-[boundary=forest_compartment][ref],
node,area|z14-[boundary=forestry_compartment][ref]
In this example, shared parameters can be moved to a higher level:
node,area|z14-[ref] {
[boundary=forest_compartment],
[boundary=forestry_compartment] {
}
}
Sometimes you need to combine several rules into a group. Wrap the filters in parentheses (
and )
to group them without immediately starting a rule block.
node,area|z14-[ref](
[boundary=forest_compartment],
[boundary=forestry_compartment]) {
}
}
Preprocessing macros
The preprocessor prepares the style for parsing by substituting values and enabling or disabling blocks based on the settings.
Substitution Macros
@import
Inserts the content of the specified file:
@import "polygons.mapcss";
@{name}
Inserts the value of a macro wherever it is used:
// Define color using
@color_ground: #EAE3D3;
// then use it as
canvas
{
fill-color: @color_ground;
}
Conditions
@if
Checks the parameter and includes or excludes a block from the style:
@if Theme == Dark
@import "colors_dark.mapcss";
@else // Default colors
@import "colors.mapcss";
@endif
Guru Maps uses the following preprocessor parameters:
- Theme {Light, Dark} - current app theme,
- Style {Default, Outdoor} - current map style,
- SubStyle {Car, Hike, Bike}
- Car is used for driving
- Hike and Bike are used for hiking and biking activities respectively
@else
Specifies a block of code to run when the first condition is false.
@elif
Contains a condition to run if the previous conditions did not match.
@endif
Closes the block of the current condition.
Draw parameters
These parameters control how objects are drawn on the map.
Parameter values
Width
Line thickness or width
can be specified in pixels 1px
, points 2pt
, meters 3m
, or calculated using an expression such as eval( zlinear( 13, 1px,1pt,max(2pt, 4m)) );
. Read more about expressions in the expressions section.
Color
Specify color using #RGB
, #RRGGBB
, #RRGGBBAA
, or a named color from the CSS color list.
Text
Any sequence of characters between single or double quotes is considered text.
'string'
"another string"
Draw order parameters
layer
The layer number is needed to separate the different levels on the map.
// for any object with tag 'layer', set its 'layer' property to the value of the tag
*|z9-[layer] {
layer: eval(tag(layer));
}
z-index
z-index
sets the drawing order of objects of the same type within a layer.
area|z10-[natural=wood] {
z-index: -3;
fill-color: @color_wood;
}
area[natural=oceanwater] {
z-index: -2;
fill-color: @color_water;
}
Polygon parameters
fill-color
Fill color for the polygon.
area|z5-[natural=water] {
fill-color: @color_water;
}
fill-image
Fill image for the polygon.
// fill image of a military area displayed on top of other objects
area|z11- {
[landuse=military],
[military=danger_area] {
z-index: 2;
fill-image:"forbiddenArea.png";
}
}
fill-image
supports inline style with base64 data.
// same as arrow.svg
fill-image: eval(data("PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTI2IDNoMTBWMWw1IDMtNSAzVjVIMjZ6IiBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIG9wYWNpdHk9Ii40Ii8+PC9zdmc+Cg=="))
color
and width
for polygon
Polygon border color and border width.
area|z15-[building] {
z-index: 3;
width: 1px;
color: @color_landuse_residential_stroke;
}
Line parameters
color
and width
for line
Line color and width.
line|z13-[natural=tree_row] {
width: 3pt;
color: @color_wood;
z-index: -10;
}
casing-color
and casing-width
Line casing color and casing width, used mostly for roads.
line|z8-[highway=motorway],
line|z11-[highway=motorway_link] {
color: @color_motorway;
casing-color: @color_motorway_casing;
casing-width: 0.5pt;
}
dashes
Indicates the lengths of painted and blank segments. The sum of the numbers must be a power of 2 (4, 8, 16, 32, 64, etc.). Each number is the length of a line segment in points.
line|z15-[highway=cycleway] {
dashes: 2,2,2,2;
dashes-color: @color_cycleway_dashes;
}
dashes-color
and dashes-width
Dash color and width used for trails, paths, stairs, and borders.
line|z15-[highway=steps] {
dashes-color: @color_footway_dashes;
dashes-width: eval( zlinear( 16, 3pt, 4pt ) );
}
linecap
The shape of the line edges. Possible values: none
, square
, round
.
linejoin
Shape of line joints. Possible values: round
, miter
, bevel
, auto
.
Text params
text
The text to draw next to a point or centered on a line or polygon.
node,area|z2-8[place=country] {
text: eval(locTag('name'));
// other params skipped
}
font-weight
Font weight. Possible values: bolder
, bold
, normal
, light
, lighter
.
node,area|z9-[place=town],
node,area|z10-[place=village],
node,area|z12-[place=hamlet] {
font-weight:light;
font-size:11;
font-stroke-width:2px;
font-stroke-color: @color_label_stroke;
}
font-size
Font size.
font-stroke-width
and font-stroke-color
Font stroke width and color.
text-color
Text color.
node,area|z2-8[place=country] {
text: eval(locTag('name'));
text-color: @color_name_text;
text-priority: 10;
// other tags skipped
}
text-priority
When labels compete for space, text-priority
determines which text appears first.
text-allow-overlap
Allows labels to overlap so multiple pieces of text can occupy the same area.
text-big-padding
Reserves twice as much padding around the text. Use this for major settlements (city, town, suburb, etc.) to prevent labels from obscuring the map.
icon-image
The name of the image to display at a point or in the center of a polygon.
node,area|z17-[amenity=library] {
icon-image: "library.svg";
icon-scale: 0.37;
icon-tint: @color_icon_tint;
}
icon-image
supports inline style with base64 data.
// same as poi_circle_small.svg
icon-image: eval(data("PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSI4IiB2aWV3Qm94PSIwIDAgOCA4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNyA0QzcgNS42NTY4NSA1LjY1Njg1IDcgNCA3QzIuMzQzMTUgNyAxIDUuNjU2ODUgMSA0QzEgMi4zNDMxNSAyLjM0MzE1IDEgNCAxQzUuNjU2ODUgMSA3IDIuMzQzMTUgNyA0WiIgZmlsbD0iIzgwODA4MCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTggNEM4IDYuMjA5MTQgNi4yMDkxNCA4IDQgOEMxLjc5MDg2IDggMCA2LjIwOTE0IDAgNEMwIDEuNzkwODYgMS43OTA4NiAwIDQgMEM2LjIwOTE0IDAgOCAxLjc5MDg2IDggNFpNNCA3QzUuNjU2ODUgNyA3IDUuNjU2ODUgNyA0QzcgMi4zNDMxNSA1LjY1Njg1IDEgNCAxQzIuMzQzMTUgMSAxIDIuMzQzMTUgMSA0QzEgNS42NTY4NSAyLjM0MzE1IDcgNCA3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg=="))
icon-scale
Scales the image so it appears larger or smaller than its original size.
icon-tint
icon-tint
recolors the image. #FFF
stays white, #CCC
becomes a lighter version of the tint color, #888
matches the tint color, #444
becomes a darker version, and #000
stays black. Colors blend smoothly between these points.
icon-offset-x
and icon-offset-y
Offsets the image relative to its anchor point. By default, the image is centered on the map point. For example, icon-offset-y: 0;
lines up the bottom of a pin icon with the target point. Values range from 0 to 1, where 0 represents the bottom or left edge and 1 represents the top or right edge.
image-allow-overlap
Allows icons to overlap.
Details parameters
Use details-text
and details-description
to set the name and description for GeoJSON objects. details-text
appears as the title, and details-description
appears as the description. If both values are empty, taps on the object are ignored. You can use expressions in these parameters.
* {
details-text: eval(tag('name'));
details-description: eval(tag('description'));
}
Expressions
Filters and drawing parameters can depend on external factors, be calculated with formulas, or vary by zoom level.
Calculated values must always start with the eval()
function.
The following functions can be used inside:
min
and max
Returns the minimum or maximum value from the parameters. The number of parameters is not limited.
any
Returns the first non-null
value from the parameters. You can pass any number of arguments.
data
Decodes base64 string. Can be used for icon-image
and fill-image
.
tag
Returns the value of the specified tag, or null
if it is missing.
locTag
Returns a localized tag value based on the user’s language settings. For example, if the preferred languages are English, Russian, and the native language, locTag('name')
checks name:en
, then name:ru
, then name
, and uses the first match. Guru Maps supports be
, cs
, da
, de
, en
, es
, fr
, it
, ja
, ko
, nl
, pl
, ru
, sv
, uk
, zh
. Use locTag()
for these languages; for others, call tag()
explicitly.
cond
Evaluates a logical expression. If the first argument is true, the function returns the second argument; otherwise it returns the third.
// check addr:housenumber
text: eval( cond( tag('addr:housenumber'),
// if there is addr:housenumber, then concatenate next condition
tag('addr:housenumber') . cond( any( locTag('name'), tag('addr:housename') ),
// if there is name or addr:housename - put them between ()
' (' . any( locTag('name'), tag('addr:housename') ) . ')',
// empty line otherwise
''),
// if there is no housenumber just use any from name or addr:housename
any( locTag('name'), tag('addr:housename') ) ) );
boolean
Converts the value to a Boolean. If the value is missing or equals 0
, No
, Off
, or False
(case-insensitive) the function returns false
; otherwise it returns true
.
zlinear
Smoothly changes the value as the zoom changes. The first parameter is the initial zoom level, followed by the values for each subsequent zoom level starting from that point.
line|z13-[highway=residential] {
width: eval( zlinear( 13, 1px, 1pt, max(2pt, 4m) ) );
color: @color_small_road;
linecap: round;
}
In this example, the road width is 1 pixel at zoom level 13, 1 point at zoom level 14, and the greater of 2 points or 4 meters at zoom level 15 and above.
metric
Converts the numeric parameter to meters.
line|z12-[highway=tertiary] {
width: eval( zlinear( 12, 1px, 1pt, 1pt, max(3pt, metric(any(tag(lanes),2)*2)) ));
}
In this example, the number of lanes is multiplied by 2, giving the distance in meters. max(3pt, metric())
returns whichever is larger: the width in meters or the width in points.
Expression operators
Expressions support the mathematical operators +
, -
, *
, /
, the string concatenation operator .
, and the comparison operators <
, >
, ==
, and ~=
(substring match).