wiki:Help/Styles/MapCSSImplementation

Version 18 (modified by bastiK, 13 years ago) ( diff )

update

This page documents details on JOSM's MapCSS implementation. At the moment (May-2012) it is under active development and anything may change without warning. TOC(inline)

General Structure

A MapCSS style sheet has rules of the form

selector {
    prop: value;
    ...
    prop: value;
}

The algorithm to find the styles for a given object is like this:

 - for each rule:
     if the selector applies, set the properties from the { } block
 - analyze the final list of properties and generate styles from it

Selectors

Selectors denote the filter expressions of a MapCSS rule. The rule is only applied to a map object, if its selectors match with the object.

Selectors in MapCSS are different from standard CSS for the web. MapCSS only supports a subset of the standard CSS selectors, but extends them with additional selectors required for OSM data.

Some basic examples:

/* applied to ways with a tag highway=residential */
way[highway=residential] {  /*  the styles */}

/* applied to new, closed ways on layer 1, provided they have the tag amenity=parking and access=parking, and provided 
 * the zoom level is between 11 and 14 
 */
way|z11-14[amenity=parking][access=public]:closed:new::layer_1 {...}


area[amenity=parking][access=public], area[amenity=parking][!access] {...}
relation[type=route][route=foot] > way::relation_underlay {..}

The different elements (type-, zoom- , condition selector, pseudo classes, layer identifier, grouping and child combinator) are explained below.

Type selector

Selector

Description

*

Matches with any object

node, way, relation

Matches with the osm objects of the given type.

area

Matches with any area regardless of whether the area border is only modelled with a single way or with a set of ways glued together with a relation.

area[natural=beach] {...} 
/* ... is equal to ... */
way[natural=beach], relation[type=multipolygon][natural=beach] {...} 

Note that area selects unclosed ways as well, so it may be useful to add the :closed pseudo class. The JOSM Validator will give a warning for unclosed ways that have an area style.

meta

The meta selector starts a special rule that should stand at the beginning of the file. It gives some general information on the style sheet. All software that supports MapCSS should be able to parse this sections without errors, so do not use exotic syntax extensions in this part.

meta {
    title: "Parking lanes";   /* title shown in the menu */
    icon: "images/logo.png";  /* small icon shown in the menu next to the title */
}

canvas

Some style information not specific to nodes, ways or relations.

canvas {
    background-color: #ffffea;
    default-points: false;
    default-lines: false;
}

Key

Description

Value Format

Default Value

background-color

Specifies the overall background color.

Color

black

default-points

Whether default point style should be added to nodes where no style applies.

Boolean

true

default-lines

Whether default line style should be added to ways where no style applies.

Boolean

true

Child selector

If a node is part of a way, we say that it is a child of this way. Similarly, if a node, a way, or a relation is a member of a relation, we say, that it is a child of this relation.

In MapCSS you can use a child selector which matches only if both the parent and the child object match.

Example:

/*
 * only matches for a way which is a child of a relation with tags 
 * type=route and route=foot
 */
relation[type=route][route=foot] > way {...}

Notes:

  • Zoom selector and Layer identifier are only relevant for the part to the right of the > sign.

Parent selector

In addition to child selectors, JOSMs supports the the notion of a parent selector. Note, that parent selectors are a JOSM-specific extension of MapCSS not present in other MapCSS implementations.

Similar to a child selector, a parent selector only matches if if both the parent and the child object match. In contrast to to the child selector, the character < is used.

In contrast to the child selector, the parent object will be "selected". In other words, the properties in the {...}-Declaration Block apply to the object on the right hand side of the "<" sign.

Example:

/*
 * matches for a highway which has at least one node tagged as traffic_calming=*
 */
node[traffic_calming] < way[highway] {...}

Condition selector

Selectors can include a set of conditions. If any of these conditions evaluates to false, the selector doesn't match and the style rule isn't applied.

An attribute condition specifies a condition on a tag of an OSM object.

Operator

Description

Example

=

Exact match of the value.

way[highway=residential]                   /* without quotes always case insensitive */
node[name="My name"]                       /* use quotes for if value includes spaces or if case sensitive matching is important */
node["MY_Special_TAG"="another value"]     /* use quotes for tag names if case sensitive matching is required */
node["ÖPVN"=tram]                          /* use quotes for tag keys with special characters */
                                           /*   note that these are not common in OSM at the moment */

!=

Value not equal

way[highway!=residential]                   /* without quotes always case insensitive */
node[name!="My name"]                       /* use quotes if value includes spaces or if case sensitive matching is important */
node["MY_Special_TAG"!="another value"]     /* use quotes for tag names if case sensitive matching is required */
node["name:fr"!="mon nome"]                 /* use quotes for tag names with special characters like colons*/

<,>, <=, >=

Comparision for numeric values.

node[population > 50000]                    /* without quotes always case insensitive */
node[ele <= 3000]                           /* use quotes for if value includes spaces or if case sensitive matching is important */

^=

Prefix match

node[name ^= "myprefix"]                    /* value starts with 'myprefix' */

$=

Postfix match

node[name $= "mypostfix"]                    /* value ends with 'mypostfix' */

*=

Substring match

node[name *= "my substring"]                  /* value contains the substring 'my substring' */

~=

List membership

*[vending~=stamps]                          /* the tag value for the tag 'vending' consists of a list of ;-separated values    */
                                            /* and one of these values is 'stamps'                                             */

=~

Regular expression match

name[name=~/^My_pattern.*/]                 /* the value of the tag 'name' matches with the regular expression '^My_pattern.*' */
                                            /* Note, that reqular expressions have to be enclosed in /.../                     */                  

In addition, you can test whether a tag is present or not:

Condition

Example

Presence of tag

way[highway]                     /* matches any way with a tag 'highway'                                              */
way["VALSOU"]                    /* use quotes if case sensitive matching is required                                 */
way["name:fr"]                   /* use quotes if the tag name includes special caracters (white space, colons, etc.) */

Absence of tag

way[!highway]                     /* matches any way which does not have a tag 'highway'                                              */
way[!"VALSOU"]                    /* use quotes if case sensitive matching is required                                 */
way[!"name:fr"]                   /* use quotes if the tag name includes special caracters (white space, colons, etc.) */

You can test whether the the value of a tag is logical truth value. The value is evaluated to true, if it is either "yes", "true", or "1". All other values are evaluated to false.

Condition

Example

Testing for truth value

way[oneway?]                  /* matches any way with a truth value in the tag 'oneway'  */

Link selector

In a child selector, you can formulate conditions on the link between a parent and a child object.

If the parent is a relation, you can formulate conditions for the role a member objects has in this relation.

relation[type=route] >[role="link"] way {  /* matches any way which is a member of route relation with role 'link' */ 
   color: blue;
}

Operator

Description

Example

=

Exact match of the role name. The name name role is compulsory in this context.

relation >[role=residential] way           /* without quotes always case insensitive */
relation >[role="My name"]   way           /* use quotes for if the role value includes spaces or if case sensitive matching is important */

The operators !=, ^=, $=, *=, and ~= are supported too. Please refer to condition selector operators.

Nodes in ways and members in relations are ordered. You can formulate conditions on the position of a node in a way or a member object in a relation.

relation[type=route] >[index=1] way {  /* matches the first way which is a member of route relation  */ 
   color: blue;
}

Zoom selector

You can decorate a type selector with a zoom selector. The zoom selector restricts the range of zoom levels at which the respective MapCSS rule is applied.

Example

Description

way|z12 {...} At zoom level 12
way|z13-15 {...} From 13 to 15
way|z16- {...} 16 and above
way|z-12 {...} 12 and below
way {...} any zoom level

The precise definition of scale ranges for each zoom level may change in the future. By rule of thumb you can expect to be approximately at zoom level n when imagery displays slippymap tiles of level n.

Pseudo Classes

:closed true for ways where the first node is the same as the last and for any multipolygon relation
:new all new objects
:connection true for nodes that are used by more than one way
:tagged What JOSM considers tagged, i.e. an object that with a tag key other than the following: source*, source_ref, note, comment, converted_by, created_by, watch*, fixme, FIXME, description, attribution (version r4008; in this list, * is a glob)

Layer Identifier

Layers can be used to create more than one style for a single object. Here is an example:

way[highway=secondary] {
    width: 3;
    color: yellow;
}

way[highway=tertiary] {
    width: 2;
    color: orange;
}

way[access][access!=public]::non_public_access_layer {
    width: +2; 
    color:red; 
    dashes: 2; 
    object-z-index:-1.0;
}

way[bridge]::bridge_layer {
    width: +3; 
    color:#000080;
    opacity:0.5;
    object-z-index:1.0; 
}

This draws all secondary and tertiary roads in yellow and orange respectively. Any road with an access tag other than public will get an extra line style below (object-z-index:-1.0;) the main line. If that part of the street happens to be a bridge, it will also get a half transparent blue overlay. The relative width value (width: +2;) refers to the width on the default layer (2 or 3 in this case).

The name for the layer can be any identifier.

default
If you omit the layer in the selector, this is the same as using ::default.
*
In addition, you can use the * layer to override and initialize all layers.
It overrides all existing subparts, so
way::A { a; } 
way::B { b; } 
way::* { c; } 
is equivalent to
way::A { a; } 
way::B { b; } 
way::A { c; } 
way::B { c; }
And it initializes new subparts. In other words:
way::* { a; } 
way::A { b; } 
is equivalent to
way::A {} 
way::* { a; } 
way::A { b; } 
which is in turn the same as
way::A { a; } 
way::A { b; } 
or
way::A { a; b; }

Grouping

Rules with common declaration block can be grouped into one:

area[landuse=forest] { color: green;   width: 2; }
area[natural=wood] { color: green;   width: 2; }

is the same as

area[landuse=forest], area[natural=wood] { color: green;   width: 2; }

Properties

General properties

Key Description Value Format Default Value
z-index                                 specify the order the objects are drawn: The objects with higher z-index are drawn on top of objects with lower z-index Number (can be negative) 0
major-z-index this is similar to z-index, but it has higher priority than z-index. So if one object has a higher major-z-index than the other, it is drawn on top. If the major-z-index is the same, z-index decides. Number (can be negative) Depends on style element: area: 1, casing: 2, left-/right-casing: 2.1, line-pattern: 2.9, line: 3, point: 4, default-point: 4.1, line-text: 4.9, point-text: 5

Icon and symbol styles

Key Description Value Format Default Value
icon-image The icon at node position Image -
icon-opacity Opacity of the icon image Opacity 1.0
icon-width Width of the icon. If only one of the properties icon-width and icon-height is given, the image will be scaled proportionally. The icon will keep the original size, if neither icon-width nor icon-height is set. Number -
icon-height Height of the icon. (See icon-width) Number -
symbol-shape                               Display a symbol at the position of the node square, circle, triangle, pentagon, hexagon, heptagon, octagon, nonagon, decagon -
symbol-size Size of the symbol Number, can be relative ("+4") 10
symbol-stroke-width outline stroke width Width 1.0 if symbol-stroke-color is set
symbol-stroke-color line color Color #FFC800 if symbol-stroke-width is set
symbol-stroke-opacity line opacity Opacity 1.0
symbol-fill-color fill color for the shape Color blue, unless either symbol-stroke-width or symbol-stroke-color is set
symbol-fill-opacity fill opacity Opacity 1.0
text-..., font-... general text & font properties
text-anchor-horizontal horizontal text label placement left, center, right right
text-anchor-vertical vertical text label placement above, top, center, bottom, below bottom

Do not rely on the default values for symbol-... properties (except for opacity). They are intended for "quick & dirty" style sheets and should be set to an explicit value.

Line styles

Key Description Value Format Default Value
width Line width Width -
color Line color Color value of fill-color or (if unset) JOSM's default untagged color (#808080)
opacity How transparent the line is. Opacity 1.0
dashes An array of alternating on/off lengths list of numbers, e.g.
> 15, 5

or written as expression:
> list(3, 4, 5, 6)
-
dashes-offset shift the dash pattern by a certain amount Number (>= 0) 0
dashes-background-color The color to use in between the dashes (optional) Color -
dashes-background-opacity Opacity value for the dashes background Opacity value of opacity
linecap Shape at the end of the line (see here) none, round, square none
linejoin Shape at the line corners round, miter, bevel round
miterlimit                                   Applies for linejoin: miter. Sets the maximum overshoot when line segments meet at a very small angle Number (>= 1.0) 10.0
offset Move line to the left or right (when looking in way direction). This could be used to draw multiple lanes for one way or mark left and right side of a way differently. Number (positive value moves line to the left, negative to the right) 0
pattern-image line pattern similar to Mapnik's LinePatternSymbolizer Image -
text-position set to line, if text should be drawn along the line line, center -
text-..., font-... general text & font properties

All these properties (except for text-... and font-...) exist also with the casing- prefix. The casing is a second independent line element, that is drawn below the normal line and can be used to draw a thin frame around the line in another color.

Key Description Value Format Default Value
casing-width              Width of the border on both sides of the main line. In JOSM < 5214: Total width of the casing Width (revers to width if relative width is specified) -
casing-color Casing color Color value of fill-color or (if unset) JOSM's default untagged color (#808080)
casing-opacity How transparent the casing is. Opacity 1.0
casing-... ... ... ...

Similar to casing-, there is also the left-casing- and right-casing- prefix. It draws additional lines to the left and to the right of the main line.

Area styles

Key Description Value Format Default Value
fill-color Color in which to fill the area Color -
fill-image Image pattern Image -
fill-opacity How transparent the fill is; applies to both color and image Opacity 1.0
text-position set to center, if text should be drawn in the center of the area line, center -
text-..., font-... general text & font properties

Required properties to create an Area style: fill-color or fill-image

Text & Font properties

Key

Description

Value Format

Default Value

text  

How to find the label text. No label is displayed, unless this instruction is present.

auto

Derive the text automatically. The default name tags are: "name:"+<LANG>, "name", "int_name", "ref", "operator", "brand" and "addr:housenumber".

Configure a list of tag names in the preference "mappaint.nameOrder" in order to change this list.

String

Denotes the key of the tag whose value is used as text.

Expressions

You can enter an expression to compute the text to be displayed. Examples:

  • eval("this is a static text") - renderes a static text
  • eval(concat(tag("first"), "-", tag("second"))) - displays the concatenated tags "first" and "second"

-

text-color the text color Color white for lines and nodes, #c0c0c0 for areas (JOSM "text" and "areatext" color preferences)
text-offset-x shift the text horizontally, (not supported for text along line) Number 0
text-offset-y (can also be written as text-offset) shift the text vertically, positive values shift the text in upwards direction Number 0
text-halo-radius size of text background border (to make text visible on background with a similar color) Number -
text-halo-color color of the text halo Color complement of the text color
text-halo-opacity transparency for the text halo Opacity 1.0
font-family font family String "Helvetica"
(JOSM preference "mappaint.font")
font-size font size Number 8
(JOSM preference "mappaint.fontsize")
font-weight bold or not bold, normal normal
font-style italic or not italic, normal normal

Width

  • 14.0 (any positive number)
  • default (use JOSM's default line width, which is 2, but can be configured)
  • thinnest (draws the line as thin as possible)
  • +3 (with plus sign in front) adds the amount to the width on the default layer. This applies only for styles that are not on the default layer, e.g. highlights. Another way to write this would be prop("width","default")+3. For casing-width, this refers to the width value on the same layer.

Color

  • named color as found in this list
  • html style: #ff0000
  • rgb(0.0, 1.0 , 0.2) - rgb value with arguments from 0.0 to 1.0

Opacity

  • from 0.0 (transparent) to 1.0 (opaque)

String

  • any character sequence, in quotes, e.g. "images/fill.png". If the string is an identifier, quotes are optional. (Quote and backslash sign can be escaped.)

Number

  • integer or floating point (in simple form e.g. 0.3). In general can be negative, but most properties do not support negative numbers
  • has a special meaning if you put a "+" sign in front (relative width)

Eval expressions

See source for details and an up to date list.

+, -, *, /
arithmetic operations
||, &&, !
boolean operations
<, >, <=, >=, ==
comparison operators
asin, atan, atan2, ceil, cos, cosh, exp, floor, log, max, min, random, round, signum, sin, sinh, sqrt, tan, tanh
the usual meaning, details
cond(b, fst, snd)
b ? fst : snd
if (b) then fst else snd
list(a, b, ...)
create list of values, e.g. for the dashes property
prop(p_name)
value of the property p_name, e.g. prop("width")
prop(p_name, layer_name)
property from the layer layer_name
is_prop_set(p_name)
true, if property p_name is set
is_prop_set(p_name, layer_name)
true, if property p_name is set
tag(key_name)
get the value of the key key_name from the object in question
parent_tag(key_name)
get the value of the key key_name from the object's parent(s)
has_tag_key(key_name)
true, if the object has a tag with the given key
rgb(r, g, b)
create color value (arguments from 0.0 to 1.0)
red(clr), blue(clr), blue(clr)
get value of color channels in rgb color model
length(str)
length of a string
concat(str1, str2, ...)
assemble the strings to one
JOSM_search("...")
true, if JOSM search applies to the object

Examples

  • circle symbol for house number with size depending of the number of digits
    node[addr:housenumber] { 
        symbol-shape: circle; 
        symbol-size: eval((min(length(tag("addr:housenumber")), 3) * 5) + 3); 
        symbol-fill-color: #B0E0E6; 
    
        text: "addr:housenumber"; 
        text-anchor-horizontal: center; 
        text-anchor-vertical: center; 
        text-offset-x: -1; 
        text-offset-y: -1; }
        
    node[addr:housenumber]::hn_casing { 
        z-index: -100; 
        symbol-shape: circle; 
        symbol-size: +2; 
        symbol-fill-color: blue; 
    }
    
  • invert colors
    *::* {
        color: eval(rgb(1 - red(prop(color)), 1 - green(prop(color)), 1 - blue(prop(color))));
        fill-color: eval(rgb(1 - red(prop(fill-color)), 1 - green(prop(fill-color)), 1 - blue(prop(fill-color))));
    }
    
  • random stuff
    way {
        width: eval(random() * 20);
        color: eval(rgb(random(), random(), random()));
    }
    

Compatibility notes

MapCSS 0.2

Grammar

  • descendant combinator is not supported, use child combinator instead.
  • JOSM MapCSS is not liberal with white spaces in the selector, they are only permitted before and after comma and greater sign (Grouping and Child combinator).
  • way[oneway=yes] does not have any magic, you can use way[oneway?] instead
  • set is not supported, instead of
    way[highway=footway] { set path; color: #FF6644; width: 2; }
    way[highway=path]    { set path; color: brown; width: 2; }
    way.path { text:auto; text-color: green; text-position: line; text-offset: 5; }
    
    you can write
    way[highway=footway] { path-set : true; color: #FF6644; width: 2; }
    way[highway=path]    { path-set : true; color: brown; width: 2; }
    way[eval(prop(path-set))] { text:auto; text-color: green; text-position: line; text-offset: 5; }
    
  • no stacking of declaration blocks, you have to provide explicit layer names
  • no @import
  • JOSM does not require eval(...) to be wrapped around expressions, but for compatibility with other MapCSS implementations you should write it out.

Properties

At the moment, JOSM does not support the following properties:

canvas:
fill-color is called background-color, the rest is not supported
line:
image
label:
font-variant, text-decoration, text-transform, max-width
shield:
not supported

JOSM uses the MapCSS 0.1 way to specify casing-width, i.e. casing-width: 9; is an absolute value. You can write casing-width: +4; to specify a 2px casing on both sides.

Halcyon (Potlatch 2)

  • Text label is placed in the center of the icon. For compatibility with Halcyon put
    node { text-anchor-vertical: center; text-anchor-horizontal: center; }
    
    at the beginning of your style sheet.
  • standard z-index seems to be different from 0 (FIXME: what is it?)
  • image: circle; corresponds to symbol-shape: circle;

Kothic

  • Kothic has support for eval, which probably differs from JOSM's eval.
  • Kothic understands units, whereas JOSM always calculates in pixel.
  • The extrusion features are not available in JOSM

Ceyx

  • seems to have [tunnel=1] instead of [tunnel=yes] (Halcyon) or [tunnel?] (JOSM)

Attachments (2)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.