Skip to content

Latest commit

 

History

History
493 lines (371 loc) · 22.4 KB

MapCSS.creole

File metadata and controls

493 lines (371 loc) · 22.4 KB

For more information about MapCSS see

General Structure

A MapCSS style sheet has rules of the form

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

For each rule, if the selector applies the properties from the { } block are set. If a property has already been set, it will be overridden.

Additionally, comments can be made using // to comment the rest of the line out, or using /* and */ to comment out everything between these end points.

Selectors

Every selector may have several elements: type, class, zoom, condition, pseudo class, pseudo element, grouping and link.

E.g.

  • way.public[highway=residential]
  • way|z11-14[amenity=parking][access=public]:closed:new::casing
  • relation[type=route][route=foot] > way::relation_underlay

Type selector

First part of a selector; required.

Selector Description
* Matches with any object
node, way, relation Matches with objects of the given type
area Matches polygons (polygons as from osm2pgsql, incl. relations with type multipolygon)
point Currently an alias for 'node'
line Matches lines (way or relation)
canvas The background

The type of an object is retrieved from the 'types'-array in object-value (see API.md). You can add/remove types from your database query.

  • Compatibility MapCSS 0.2: YES

Class selector

After the type selector, separated by '.'. Optional. Can be negated by prepending with '!'.

Example:

way.minor_road {
  ...
}
way!.minor_road {
  ...
}

See below under 'Assignments - Classes'.

  • Compatibility MapCSS 0.2: YES

Zoom selector

After the class selector, separated by '|'. Optional.

The zoom selector restricts the range of zoom levels at which a rule is applied. If the zoom selector is omitted, the condition is valid for all zoom levels.

Selector Description
|z5 Only at zoom level 5.
|z5- Zoom level 5 and above.
|z-5 Zoom level 5 and below.
|z5-10 Zoom level 5 to 10.
  • Compatibility MapCSS 0.2: YES

Condition selector

After the zoom selector, may be specified multiple times. Every condition is enclosed in [...]. Optional.

You can combine several conditions, they will be combined by logical AND. E.g. *[highway=primary][bridge] matches all objects with tags highway=primary AND bridge=yes.

Matches are always case sensitive (except regexp). Valid characters for keys are letters, digits, '-', '_' and ':'. Valid characters for values are all characters expect '"', ''' and ']'. You may quote keys and values with '"' or ''' to use special characters.

The tag 'osm_id' will be set to the ID of the object.

Comparision expressions

Operator Description Compatibility
= Exact match of the value. E.g. [highway=residential]. MapCSS 0.2
!= Value not equal. Negation of =. MapCSS 0.2
<, >, <=, >= Comparision for numeric values (using floats). MapCSS 0.2
^= Prefix match. Value starts with 'string', e.g. [name^=Lon] matches "London". no standard
$= Suffix match. Value ends with 'string', e.g. [name$=dorf] matches "Enzersdorf". no standard
*= Substring match. Value contains 'string', e.g. [name*=ob] matches "Foobar". no standard
~= List membership. Tag value consits of a list of ;-separated values. E.g. [amenity~=atm] matches amenity=atm;bank. no standard
=~ Regular expression match. Value matches given regular expression, e.g. [highway=~/.*ary/] matches primary. Use [highway=~/.*ary/i] for case insensitive matches. For compatibility with JOSM also accepts [highway=~/(?i).*ary/] for case insensitive matches. MapCSS 0.2¹
!~ Negated regular expression match. Value matches all but given regular expression, e.g. [highway!~/.*ary/] matches residential but not primary. Use [highway!~/.*ary/i] for case insensitive matches. JOSM
@= List match. Tag value must exactly match one of the values of the specified list, e.g. [highway@=primary;secondary;tertiary]. no standard
  • You can prepend any of the expressions with ! to negate match, e.g. [amenity*=bank][!amenity*=atm] matches amenity=bank, amenity=bank;post_office but not amenity=bank;atm.
  • As value you may use an eval-statement as in the properties (see below) (except 'Regular expression match). E.g. node[place=city][population>eval(100*100)]

¹ MapCSS 0.2 does not define case insensitive matches.

You can test whether the value of a tag is logical truth value ("yes", "true", "1") or logical falsehood value ("no", "false", "0", ""). You can also prefix the condition by ! to invert match; this will also match if the tag is not set, therefore you might want to combine conditions with tag existance match, e.g. [bridge][!bridge?!] will match all map features which have a bridge tag but not a falsehood value.

Condition Description Example Compatibility
[tag?] Testing for truth value [building?] no standard, JOSM
[tag?!] Testing for falsehood value [wheelchair?!]no standard, JOSM
[!tag?] Testing for any value which is not truth value (not really useful?) no standard, JOSM
[!tag?!] Testing for any value which is not falsehood value (very useful, as many tags in OSM allow either 'yes' or a custom value like 'bridge=swing' [!bridge?!]no standard, JOSM

Eval expression

Additionally you can use an eval()-statement as selector. You should wrap the statement in eval(), but since 0.9 this is no longer necessary, e.g.

line[eval(tag('name') == 'bar')] { ... }
line[tag('name') == 'bar'] { ... }

For sure, this simple example can be written as line[name=bar], which also has the advantage, that an efficient database query can be constructed. The above selector would need to load all lines for the given bounding box and evaluate the statement for each. On the other hand, using eval() statements more powerful comparisions are possible, e.g. about the geometry of the object.

Another example:

line[highway][eval(parent_tag('name') == tag('addr:streetname'))] near[index=0][distance<100m] point[addr:housenumber] { ... }

This makes sure that the highway's name matches the streetname of the address node.

Test of tag presence/absense

Condition Description
[key] Tests whether object has tag 'key'.
[!key] Tests whether no 'key' is present.
[/^addr:/] Presence of tag by regular expression (can be negated; add 'i' after regular expression for case insensitivity)
  • Compatibility MapCSS 0.2: PARTLY, no check for 'no/false' yet

Pseudo classes

After the condition selector(s), separated by ':'. Several pseudo classes may be specified. They can also be negated by prepending by '!', e.g. '!:closed'. Optional.

Unsupported pseudo classes are evaluated as false.

The following pseudo classes are supported:

pseudo class Description
:active supported for compatibility with MapCSS 0.2; always treated as 'false'
:hover supported for compatibility with MapCSS 0.2; always treated as 'false'
:closed true for ways where the first node is the same as the last and for any multipolygon relation
:connection true for nodes that are used by more than one way
:unconnected true for nodes that are not used by any way
:tagged what is considered 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 (in this list, * is a glob). Note: osm2pgsql does not even import those object into the database.
:righthandtraffic true if there is right-hand traffic at the current location
:lefthandtraffic true if there is left-hand traffic at the current locatiown
:lang(fr) true when the active language equals the one in brackets (e.g. french in this example). Combined languages codes (like "fr-ca") are not supported.

Pseudo elements

After the pseudo class(es), separated by '::'. Optional.

Pseudo elements can be used to create more than one style for a single object, e.g. '::casing' to draw a casing. A property object-z-index may be specified to order pseudo elements.

If you omit the pseudo element descriptor in the selector, this is the same as using ::default.

You may enclose the pseudo element in brackets (e.g. "::(default)") to suppress creating a pseudo element from this statement. This is used internally to set default values.

To set properties for all possible pseudo elements, you may use '::*' or '::(*)'. This is used internally to set default values.

  • Compatibility MapCSS 0.2: not defined in standard

Grouping

You may use a list of properties with several selectors, separated by ','. E.g.

area[landuse=forest],
area[natural=wood]
{
  color: green;
  width: 2;
}
  • Compatibility MapCSS 0.2: YES

Link selector

You can combine several selectors to formulate conditions on relations between objects. The selector always consists of three parts: parent (or relating object) selector, link condition, object selector. E.g. relation[route=bus] >[role=platform] way[highway] matches any way with a highway tag which is member of a relation with route bus where the member role is platform. If the way is member of several relations the statement is processed multiple times.

You can access the tags of the parent with parent_tag(), though changes via set/unset are not available. The link condition will be set a couple of tags (depending on the type of condition), which can be accessed with link_tag(). These tags are also available as link condition (e.g. >[index=2]).

The following link conditions are available:

empty link selector

The object is member of a parent relation resp. a node of a parent way.

Link tags are not possible

E.g. relation[type=route] way[role=proposed]

The following pseudo tags are available for conditions:

  • role: the member role of the object in the relation.
  • sequence_id: The index of the object in the relation.

The same link tags will be set as in the '>' link selector (for the eval-function link_tag() ).

  • Compatibility MapCSS 0.2: YES

'>'

The object is member of a parent relation resp. a node of a parent way.

The following link tags will be set:

  • index: an arbitrary counter for each matching parent (starting with 1).
  • role: the member role of the object.
  • sequence_id: The index of the object in the relation.
  • member_id: The ID of the member.

TODO: http://josm.openstreetmap.de/wiki/Help/Styles/MapCSSImplementation#Linkselector defines 'index' as the nth matching object in the relation.

'<'

The object is a relation / way. The statement will be processed for all members / member nodes (which is the 'parent object' in that case. E.g. node <[role=stop] relation[route=bus].

The following link tags will be set:

  • index: an arbitrary counter for each matching parent (starting with 1).
  • role: the member role of the object.
  • sequence_id: The index of the object in the relation.
  • member_id: The ID of the member.

'near'

Objects which are "near" another object, e.g. way[highway] near[index=1][distance<50] node[addr:housenumber] matches any housenumber which is near a highway (max. 50 pixels). The index=1 selects only the closest highway.

The following link tags will be set:

  • index: the nth parent object near the current feature (starting with 1, the closest parent object).
  • distance: distance between the objects in pixels.

Note: If no condition on link tag 'distance' with '<' or '<=' or '=' is used (e.g. distance<50), features intersecting a bounding box of 100px around the child object will be found.

'∈' or 'within'

Objects which are within another object.

Example (which will colorize all buildings which have a housenumber node inside):

node[addr:housenumber] ∈ area[building] {
  fill-color: red;
}

'∋' or 'surrounds'

Objects which surround another object.

Example (which will label all housenumber inside buildings):

area[building] ∋ node[addr:housenumber] {
  text: eval(tag('addr:housenumber'));
}

'⧉' or 'overlaps'

Objects which overlap (share space, but are not completely contained by each other).

Example (highlight highway areas, e.g. pedestrian, which overlap parks):

area[leisure=park] overlaps area[highway] {
    fill-color: red;
}

Properties

You may specify arbitrary properties. They will be treated as text values. Declarations are written by enclosing a set of style specifiers in curly braces.

E.g.

{
  opacity: 0.5;
  color: #ff0000;
  fill-color: rgb(0.5, 50%, 127);
  text-color: #00f;
  width: 2px;
  text: "2px";
  icon: url("img/foo.png");
}
  • You may enclose strings by single or double quotes. Within quoted strings you can escape characters by prefixing them with '\', e.g. '\"'. You can use '\n' to create a new line.
  • Compatibility MapCSS 0.2: MOSTLY
    • no definition about quoting in MapCSS

See documentation for properties of styles based on the 'default' style definition:

Types

Depending on the type of property, special values are possible:

  • colors: You can specify colors as hex value (e.g. #ff0000, #f00) or as rgb(r, g, b) resp. rgba(r, g, b, opacity) or hsv(hue, saturation, value) or as name (all named CSS3 colors supported). When using rgb() or rgba(), the following values are possible: If the value is an integer, values between 0..255 are accepted. Floats are accepted in the range 0.0..1.0. Percentage values 0%..100% may be specified too. When using hsv(), hue is a value from 0..360, saturation and value can be expressed as integer (0..100), float (0.0..1.0) or percentage 0%..100%.
  • pixels: You may specify values which take a pixel-dependend value (e.g. width, offset, ...) with a unit, default: 'px' (Pixels on screen). Other supported unites: 'u' (Units in 900913 projection on the map), 'm' (Meters on the map; NOT IMPLEMENTED YET: currently 'u' is used instead).
  • You may specify URLs without url()

Assignments

You may assign values to tags of the current object. This is independent from the current pseudo element descriptor.

Declaration Description
set highway_class=minor; set tag 'highway_class' to value 'minor'.
set highway_class=eval(...); use an eval expression to set tag 'highway_class'.
set highway_class; set tag 'highway_class' to 'yes'.
unset highway_class; remove the tag 'highway_class'.

Example:

way[highway=unclassified],
way[highway=residential] {
  set highway_class=minor;
}
way[highway_class=minor] {
  color: #ffffff;
  width: 2;
}
  • Compatibility MapCSS 0.2: YES (though 'unset' is not defined in MapCSS)

Eval expressions

You can compute values using an eval instrucion:

{
  opacity: eval("tag(population)/100000");
  set description=eval(cond(tag(population)>1000000,"large city","small city"));

}

Either set a property for the current pseudo element or set a tag for the current object. You don't need to wrap the function in eval(), you can also just write: opacity: tag(population)/100000;.

See file eval.creole for details.

  • Compatibility MapCSS 0.2: YES

Assignments - Classes

You can set tags beginning with a full-stop to simulate classes:

{ set .minor_road; }

You can then use .minor_road (as above) in the class selector:

way.minor_road {
  color: #ffffff;
}
  • Compatibility MapCSS 0.2: YES

Geometry

The special property "geo" will be predefined on every object. You may change it with eval statements.

Example:

point[place=village] {
  geo: eval(buffer(prop(geo), 10px));
  fill-color: #00ff00;
}

This will draw a 10px wide buffer around every node with 'place=village'.

  • Compatibility MapCSS 0.2: not defined in standard

Combining features

In pgmapcss 0.3 a new feature has been introduced: 'combine'. It allows combining several similar features into one, e.g. all streets with the same name. This may improve text rendering (Streets in OpenStreetMap are usually split into short junks, as type of street changes: oneway, bus routes, lanes, ...).

You need a selector which matches the features you want to combine, there you add an instruction combine TYPE ID, where ID is usually an eval-statement on the tags you want to group the features on. The TYPE can be used as object type in a selector. Note that there is no ':' after "combine".

The tags of the input features will be merged, e.g. the tags of the following input features "amenity=bar kitchen=pizza;kebap" and "amenity=bar kitchen=pizza;noodles opening_hours=never" will be merged to "amenity=bar kitchen=pizza;noodles;kebap opening_hours=never". Modifications of tags via set/unset-statements BEFORE the combine-statement will be available in the combined feature.

The geometry of all input features will collected. Therefore it might be useful to merge the lines (line_merge).

Example:

line[highway] {
  combine street eval(tag(name));
}

street {
  geo: eval(line_merge(prop(geo)));
  text: eval(tag(name));
}

Media queries

Media queries are used to skip a section of the style under certain conditions. The syntax closely matches the official css syntax. The following conditions are supported:

Media condition Description
(user-agent: <string>) Only include @media section when the name of the editor / renderer matches the given string. The only accepted value is pgmapcss.
(pgmapcss-version: <version>) Only include @media section when the current version of pgmapcss matches the specified version, e.g. 0.8. Can be prefixed by min- or max- to compare ranges. (e.g. min-pgmapcss-version: 0.8 would match the following versions: 0.8, 0.9, 0.12, 1.0 but not not 0.4 and 0.7.
(renderer: <string>) pgmapcss is used with the specified renderer (currently only "mapnik" is supported).
(renderer-version: <version>) Check if the specified renderer version is used (assessed at compile time, dependening on the used template). min- and max- prefixes supported, see for details.

Conditions can be combined with and, chained with a comma (logical or) and negated (e.g. not (user-agent: pgmapcss)).

Examples:

@media (user-agent: pgmapcss), (user-agent: josm) and (min-josm-version: 7000) {
    /* something */
}

Language support

pgmapcss implements language support at different levels:

  • Properties like text can read localized names, e.g. text: auto.
  • The eval function localized_tag() will either return a localized version of the tag or the tag itself.
  • The pseudo class :lang(fr) evaluates statements only when the current locale matches the one passed as parameter.

Which language will be used?

If you use pgmapcss in database function mode (e.g. when rendering with Mapnik), the language to use will be decided at compile time, depending on the current locale or the value of the --lang parameter.

When using pgmapcss in standalone mode, the language will be decided at run time, depending on the current locale or the value of the --lang parameter. If the compiled script is used as CGI script, the language will be used from the "Accept-Language" HTTP header or the parameter lang (e.g. file.cgi?lang=ru).

Config option

Config options can be set by using @config config_option config_value;. They can also be set as parameters to pgmapcss, by using -c or --config, e.g. pgmapcss --config option1=value1 option2=value2.

See the file doc/config_options.md for a list of config options.

Define Type of property

The type of a property is specified by:

@type property_name property_type;

Currently supported types:

  • text: The value is used as is (default)
  • tag_name: The current value of the specified tag
  • numeric: Value may be a number. if a relative number (e.g. '+4') is specified, the value will be added to the value from the default pseudo element.
  • dashes: Value is 'none' or a colon separated list of integers. It may also be specified as list, e.g. "2;4" or list(2,4).
  • angle: like numeric, but make sure that value is correctly converted for Mapnik.
  • image: an image. prints a warning on compile when image is not found.
  • image_png: an image. prints a warning on compile when image is not found. if image is an svg, it will be converted to png.
  • list_append: result will be a list (a string, separated by ';'). Any additional value will be added to the list.

Possible values

The following statement defines possible values for a specific property:

@values property_name "value1;value2;value3";

Other values will be accepted in the MapCSS file, but will finally be replaced by the default value (the first value of the specified list or the value as defined in @default_value).

Default values

Define default values for properties like:

@default_value property_name value;

E.g.

@default_value offset 0;

Define default values to other properties

If the value of a property defaults to the value of another property, this is specified by:

@default_other property_name property_name_other;

E.g.

@default_other casing-linecap linecap; // value of 'casing-linecap' defaults to value of 'linecap'

If the value is empty (e.g. {@default_other casing-linecap ;}) the reference is removed.

Postprocess values

Define postprocess functions:

@postprocess property_name function;

E.g.

@postprocess text eval(text_transform(prop("text"), prop("text-transform")));

Depending properties

@depend_property main_property "dep_property1;dep_property2;...";

For @default_other, @values: don't process depending values if main property is not set.

Style-Elements depending on property

@style_element_property line "width;color";

A database row for style element 'line' will only be returned when the properties 'width' and 'color' are set.

Special configuration for certain properties

@property_config key "options;as;list";

Currently possible options:

  • 'return_after_statement': if the specified property appears in the current statement, all properties of the current statement (and previous statements) will be returned as separate result. The properties will be reset to the state before the current statement.