This page documents details on JOSM's [http://wiki.openstreetmap.org/wiki/MapCSS/0.2 MapCSS] implementation. [[TOC(inline)]] == General Structure == A MapCSS style sheet has rules of the form {{{ #!mapcss selector { prop: value; /* ... */ prop: value; /* and/or */ set: class; set: .class; } }}} 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 }}} MapCSS uses the '''comment''' format of CSS (`/* ... */`). Note that when commenting out large parts of a MapCSS file, some constructs may cause an unexpected end of the comment, for instance: {{{ #!mapcss /* *[highway][name =~ /^R(\.|:)? .*/] { /* the end of the regular expression defines the unexpected end of the comment */ throwWarning: tr("foo"); } */ }}} == 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: {{{ #!mapcss /* 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=public, 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 === {{{#!th align=left valign=top '''Selector''' }}} {{{#!th align=left valign=top '''Description''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top * }}} {{{#!td align=left valign=top Matches with any object }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{node}}}, {{{way}}}, {{{relation}}} }}} {{{#!td align=left valign=top Matches with the osm objects of the given type. }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{area}}} }}} {{{#!td align=left valign=top 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. {{{ #!mapcss 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. }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{meta}}} }}} {{{#!td align=left valign=top 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. {{{ #!mapcss meta { title: "Parking lanes"; /* title shown in the menu */ icon: "images/logo.png"; /* small icon shown in the menu next to the title */ } }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{canvas}}} }}} {{{#!td align=left valign=top Some style information not specific to nodes, ways or relations. {{{ #!mapcss canvas { background-color: #ffffea; default-points: false; default-lines: false; } }}} {{{#!th '''Key''' }}} {{{#!th '''Description''' }}} {{{#!th '''Value Format''' }}} {{{#!th '''Default Value''' }}} |- {{{#!td {{{background-color}}} }}} {{{#!td Specifies the overall background color. }}} {{{#!td ''Color'' }}} {{{#!td align=center {{{black}}} }}} |- {{{#!td {{{default-points}}} }}} {{{#!td Whether default point style should be added to nodes where no style applies. }}} {{{#!td ''Boolean'' }}} {{{#!td align=center {{{true}}} }}} |- {{{#!td {{{default-lines}}} }}} {{{#!td Whether default line style should be added to ways where no style applies. }}} {{{#!td ''Boolean'' }}} {{{#!td align=center {{{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: {{{ #!mapcss /* * 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. * The function parent_tag (see below) can be used to access tags from the parent. === 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: {{{ #!mapcss /* * 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. [=#condition_selector_operators] {{{#!th align=left valign=top '''Operator''' }}} {{{#!th align=left valign=top '''Description''' }}} {{{#!th align=left valign=top '''Example''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `=` }}} {{{#!td align=left valign=top Exact match of the value. }}} {{{#!td align=left valign=top {{{ #!mapcss 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 */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `!=` }}} {{{#!td align=left valign=top Value not equal }}} {{{#!td align=left valign=top {{{ #!mapcss 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*/ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `<`, `>`, `<=`, `>=` }}} {{{#!td align=left valign=top Comparision for numeric values. }}} {{{#!td align=left valign=top {{{ #!mapcss 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 */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{^=}}} }}} {{{#!td align=left valign=top Prefix match }}} {{{#!td align=left valign=top {{{ #!mapcss node[name ^= "myprefix"] /* value starts with 'myprefix' */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `$=` }}} {{{#!td align=left valign=top Postfix match }}} {{{#!td align=left valign=top {{{ #!mapcss node[name $= "mypostfix"] /* value ends with 'mypostfix' */ }}} }}} |----------------------------------------------- {{{#!td align=left valign=top `*=` }}} {{{#!td align=left valign=top Substring match }}} {{{#!td align=left valign=top {{{ #!mapcss node[name *= "my substring"] /* value contains the substring 'my substring' */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `~=` }}} {{{#!td align=left valign=top List membership }}} {{{#!td align=left valign=top {{{ #!mapcss *[vending~=stamps] /* the tag value for the tag 'vending' consists of a list of ;-separated values */ /* and one of these values is 'stamps' */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `=~` }}} {{{#!td align=left valign=top [http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum Regular expression] match }}} {{{#!td align=left valign=top {{{ #!mapcss 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 /.../ */ }}} Case-insensitive matching can be enabled via the embedded flag expression `(?i)` (see [http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#CASE_INSENSITIVE Pattern.CASE_INSENSITIVE]). }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `!~` (since r6455) }}} {{{#!td align=left valign=top negated [http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum Regular expression] match }}} {{{#!td align=left valign=top {{{ #!mapcss *[surface!~/paved|unpaved/] }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `∈` ([http://www.fileformat.info/info/unicode/char/2208/index.htm U+2208], since r6609) }}} {{{#!td align=left valign=top element of }}} {{{#!td align=left valign=top {{{ #!mapcss node[amenity=parking] ∈ *[amenity=parking] { throwWarning: tr("{0} inside {1}", "amenity=parking", "amenity=parking"); } }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `⧉` ([http://www.fileformat.info/info/unicode/char/29c9/index.htm U+29C9], since r6613) }}} {{{#!td align=left valign=top crossing }}} {{{#!td align=left valign=top {{{ #!mapcss area:closed:areaStyle ⧉ area:closed:areaStyle { throwOther: tr("Overlapping Areas"); } }}} }}} Since r6554, it is possible to prefix the "value" (i.e., expression after the operator) with a `*` in order to "de-reference" it (i.e., obtain consider it as another key and obtain its value). Thus, `[key1 = *key2]` compares the value of `key1` with the value of `key2`, and `[key =~ */pattern/]` considers the value of the key `pattern` as a regular expression and matches it against the value of `key`. In addition, you can test whether a tag is present or not: {{{#!th align=left valign=top '''Condition''' }}} {{{#!th align=left valign=top '''Example''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top Presence of tag }}} {{{#!td align=left valign=top {{{ #!mapcss 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.) */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top Absence of tag }}} {{{#!td align=left valign=top {{{ #!mapcss 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.) */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top Presence of tag by [http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum Regular expression] match (since r6547) }}} {{{#!td align=left valign=top {{{ #!mapcss way[/^addr:/] /* matches any `addr:*` key */ }}} }}} 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. {{{#!th align=left valign=top '''Condition''' }}} {{{#!th align=left valign=top '''Example''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top Testing for truth value }}} {{{#!td align=left valign=top {{{ #!mapcss way[oneway?] /* matches any way with a truth value in the tag 'oneway' */ }}} }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top Testing for false value (since r6513) }}} {{{#!td align=left valign=top {{{ #!mapcss way[oneway?!] /* matches any way with a false 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. {{{ #!mapcss relation[type=route] >[role="link"] way { /* matches any way which is a member of route relation with role 'link' */ color: blue; } }}} {{{#!th align=left valign=top '''Operator''' }}} {{{#!th align=left valign=top '''Description''' }}} {{{#!th align=left valign=top '''Example''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top `=` }}} {{{#!td align=left valign=top Exact match of the role name. The name name {{{role}}} is compulsory in this context. }}} {{{#!td align=left valign=top {{{ #!mapcss 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 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. {{{ #!mapcss 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. {{{#!th align=left valign=top '''Example''' }}} {{{#!th align=left valign=top '''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 || || {{{:unconnected}}} || true for nodes that are not used by any way (since r6687) || || {{{: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) {{{#!comment || {{{:modified}}} || changed objects (Note that the styles are not updated when you move a node, so you have to switch the style sheet on and off to get an updated view.) || }}} === Layer Identifier === Layers can be used to create more than one style for a single object. Here is an example: {{{ #!mapcss 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.[[br]] It overrides all existing subparts, so {{{ #!mapcss way::A { a; } way::B { b; } way::* { c; } }}} is equivalent to {{{ #!mapcss way::A { a; } way::B { b; } way::A { c; } way::B { c; } }}} And it initializes new subparts. In other words: {{{ #!mapcss way::* { a; } way::A { b; } }}} is equivalent to {{{ #!mapcss way::A {} way::* { a; } way::A { b; } }}} which is in turn the same as {{{ #!mapcss way::A { a; } way::A { b; } }}} or {{{ #!mapcss way::A { a; b; } }}} === Grouping === Rules with common declaration block can be grouped into one: {{{ #!mapcss area[landuse=forest] { color: green; width: 2; } area[natural=wood] { color: green; width: 2; } }}} is the same as {{{ #!mapcss area[landuse=forest], area[natural=wood] { color: green; width: 2; } }}} === Classes === You may assign classes to matched elements, and define other selectors using those classes: {{{ #!mapcss /* assigning classes */ selector { set class; /* or equivalently */ set .class; } /* matching classes */ way.class, node[foo=bar].class { /* ... */ } }}} Example for assigning/matching a class named `path`: {{{ #!mapcss 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; } }}} == 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 || {{{#!comment Do not document these yet, as I'm not sure they are needed at all: || {{{object-z-index}}} || You can multiple styles for one object (e.g. a normal line and a highlight). In case of equal {{{z-index}}}, the {{{object-z-index}}} decides the order of painting. || ''Number'' (can be negative) || 0 || || {{{modifier}}} || Whether the current layer is a proper main style ({{{modifier=false}}}) or just a decoration for the object ({{{modifier=true}}}). JOSM draws a default line / node symbol if it doesn't find any main node / line style. || {{{false}}} or {{{true}}} || {{{false}}} for the default layer and {{{true}}} for any other layer || }}} === 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. [[br]]> 15, 5 [[br]][[br]]or written as expression: [[br]] > {{{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 [http://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty 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}}}) || '''deprecated''' (use repeat-image instead) [[br]] line pattern similar to Mapnik's [https://github.com/mapnik/mapnik/wiki/LinePatternSymbolizer LinePatternSymbolizer] || ''Image'' || - || || {{{text-position}}} || set to {{{line}}}, if text should be drawn along the line || {{{line}}}, {{{center}}} || - || || {{{text-...}}}, {{{font-...}}} |||||| general text & font properties || || `repeat-image` || repeated image along a line ''[since 5801]'' || ''Image'' || - || || `repeat-image-width` || Width of the image (optional, see `icon-width`) ''[since 5811]'' || ''Number'' || - || || `repeat-image-height` || Height of the image (optional) ''[since 5811]'' || ''Number'' || - || || `repeat-image-align` || Alignment of the image. Top-, bottom edge or the (horizontal) center line of the image will be along the line ''[since 5801]'' || `top`, `center`, `bottom` || `center` || || `repeat-image-offset` || Offset from the line ''[since 5801]'' || ''Number'' || 0 || || `repeat-image-spacing` || Spacing between repeated images ''[since 5801]'' || ''Number'' || 0 || || `repeat-image-phase` || Initial spacing at the beginning of the line ''[since 5812]'' || ''Number'' || 0 || 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 === {{{#!th align=left valign=top '''Key''' }}} {{{#!th align=left valign=top '''Description''' }}} {{{#!th align=left valign=top '''Value Format''' }}} {{{#!th align=left valign=top '''Default Value''' }}} |------------------------------------------------------------------------------- {{{#!td align=left valign=top {{{text}}}   }}} {{{#!td align=left valign=top How to find the label text. No label is displayed, unless this instruction is present. }}} {{{#!td align=left valign=top {{{auto}}} Derive the text automatically. The default name tags are: "{{{name:}}}"+'''', "{{{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" }}} {{{#!td align=center valign=top - }}} |------------------------------------------------------------------------------- || {{{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"[[br]](JOSM preference "mappaint.font") || || {{{font-size}}} || font size || ''Number'' || 8[[br]](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. '' '''Image''' '' See [wiki:Help/Styles/Images]. '' '''Color''' '' * named color as found in [http://www.w3.org/TR/css3-color/#svg-color 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 [http://josm.openstreetmap.de/doc/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.Functions.html Javadoc of Functions] 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, [http://download.oracle.com/javase/6/docs/api/java/lang/Math.html 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 get(lst, n):: get the ''n''th element of the list ''lst'' (counting starts at 0) [''since 5699''] split(sep, str):: splits string ''str'' at occurrences of the separator string ''sep'', returns a list [''since 5699''] 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''), green(''clr''), blue(''clr''):: get value of color channels in rgb color model alpha(''clr''):: get the alpha value of the given color [''since 6749''] length(''str''):: length of a string length(''lst''):: length of a list [''since 5699''] concat(''str1'', ''str2'', ...):: assemble the strings to one JOSM_search("..."):: true, if JOSM search applies to the object regexp_test(regexp, string):: test if ''string'' matches pattern ''regexp'' [''since 5699''] regexp_test(regexp, string, flags):: test if ''string'' matches pattern ''regexp''; flags is a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all") [''since 5699''] regexp_match(regexp, string):: Tries to match ''string'' against pattern ''regexp''. Returns a list of capture groups in case of success. The first element (index 0) is the complete match (i.e. ''string''). Further elements correspond to the bracketed parts of the regular expression. [''since 5701''] regexp_match(regexp, string, flags):: Tries to match ''string'' against pattern ''regexp''. Returns a list of capture groups in case of success. The first element (index 0) is the complete match (i.e. ''string''). Further elements correspond to the bracketed parts of the regular expression. Flags is a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all") [''since 5701''] replace(string, old, new):: Replaces any occurrence of the substring ''old'' within the string ''string'' with the text ''new'' osm_id():: returns the OSM id of the current object [''since 5699''] {{{#!comment: untested JOSM_pref(''key'', ''default'') get JOSM preference JOSM_pref_color(''key'', ''default'') get color from JOSM preference }}} === Examples === * circle symbol for house number with size depending of the number of digits {{{ #!mapcss 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 {{{ #!mapcss *::* { 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 {{{ #!mapcss way { width: eval(random() * 20); color: eval(rgb(random(), random(), random())); } }}} * regexp matching example: change "nameXXXsubname" to "name::subname" {{{ #!mapcss *[name=~/.+XXX.+/] { _match: regexp_match("(.+?)XXX(.+)", tag("name")); text: concat(get(prop("_match",1), "::", get(prop("_match"),2)); } }}} == 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 * 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 {{{ #!mapcss 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)