This page documents details on JOSM's [http://wiki.openstreetmap.org/wiki/MapCSS/0.2 MapCSS] implementation. At the moment (Mar-2011) 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 == Examples for selectors are {{{ way[highway=residential] {...} 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 === {{{node}}}, {{{way}}}, {{{relation}}}:: applies to the osm objects of the given type *:: accepts any object {{{area}}}:: The "{{{area}}}" type selector is a convenient way to select areas, e.g. {{{ area[natural=beach] {...} }}} is the same as {{{ 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; } }}} === Zoom selector === You can restrict the scale at which a given rule applies. || {{{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''. === Condition selector === You can add any number of conditions, which must all be fulfilled, otherwise the block of declarations will not be executed for that object. Possible conditions are: || {{{way[building]}}} || way with building tag set || || {{{way[!building]}}} || way with building tag not set || || {{{way[oneway?]}}} || way with oneway set to {{{yes}}}, {{{true}}} or 1 || || {{{way[highway=residential]}}} || way with tag {{{highway=residential}}} || || {{{way[highway!=residential]}}} || way that doesn't have the tag {{{highway=residential}}} || || {{{node[place=city][population<50000]}}} || city-node with population less than 50000 || || {{{*[amenity=vending_machine][vending~=stamps]}}} || any object, that is a vending machine and offers stamps (assumes that the value is a list of semicolon delimited entries) || || {{{way[highway][name*="straße"]}}} || any highway where the string "straße" is contained somewhere in the value of the {{{name}}} tag. (Quotes are required if characters other than "a"-"z", underscore or dash are used.) || || {{{*[name=~/.../]}}} || [http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#sum Regex] || In addition, eval expressions can be used in the brackets, e.g. || {{{way[eval(prop("opacity")<0.2)]}}} || any way where the current value of the {{{opacity}}} property is less then 0.2 || || {{{node[eval(JOSM_search("role:forward_stop | role:backward_stop"))]}}} || JOSM search expression - in this case any node that is member of a relation as {{{forward_stop}}} or {{{backward_stop}}} || === 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) {{{#!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: {{{ 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 {{{ 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; } }}} === Child combinator === You can select nodes that are part of specific ways and any object that is member of a certain relation: {{{ relation[type=route][route=foot] > way|z12-::relation_underlay {...} }}} Zoom selector and Layer identifier are only relevant for the part right of the ">" sign. === 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) || depends on the created style element: -1000 for areas, 0 for lines, 1000 for node style elements || {{{#!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-size}}} || Size of the icon. It will be scaled proportionally, such that the larger side (width or height) has the given length. The icon will keep the original size, if this property is not set. || ''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 || || {{{pattern-image}}} || line pattern similar to Mapnik's [http://trac.mapnik.org/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 || 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}}}              || Casing width || ''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-}}}... || ... || ... || ... || === 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 property is set || > {{{auto}}} [[br]]derive the text automatically. The default name tags are: "{{{name:}}}"+'''', "{{{name}}}", "{{{int_name}}}", "{{{ref}}}", "{{{operator}}}", "{{{brand}}}" and "{{{addr:housenumber}}}". [[br]]Configure a list of tag names in the preference "{{{mappaint.nameOrder}}}" in order to change this list.[[br]][[br]]> ''String'' [[br]]denotes the key of the tag whose value is used as text[[br]][[br]]''Expressions''[[br]]You can enter an expression to compute the text to be displayed. Examples:[[br]]{{{eval("this is a static text")}}} - renderes a static text[[br]]{{{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"[[br]](JOSM preference "mappaint.font") || || {{{font-size}}} || font size || ''Number'' || 8[[br]](JOSM preference "mappaint.fontsize") || || {{{font-wheight}}} || 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 [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/browser/josm/trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java 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, [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 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 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 JOSM_search("..."):: true, if JOSM search applies to the object {{{#!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 {{{ 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}}} point/icon: :: {{{icon-width, icon-height}}} 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)