From OpenStreetMap Wiki
Jump to: navigation, search

Suggested improvements for MapCSS 0.2

  • Clarify z-index behaviour and introduce new object-id assignment (suggestion by Komzpa)
  • More CSS-like behaviour for descendant/child selectors (suggestion by Sebastian Klein):
child: relation > node -- a node that is a member of that relation
descendant: relation node -- a node that is a member of that relation, or whose enclosing way is a member of that relation, or whose enclosing relation is...
  • Rename :area to :closed to remove ambiguity (suggestion by Sebastian Klein)
  • canvas (or background) object type to define background colour etc. (suggestion by Komzpa and Sebastian Klein)
  • Ability to have { interactive: no; } (or similar) so that interactive clients (e.g. Potlatch2) don't respond to mouse-clicks on that object
  • Introduce a font-variant: 'normal' (default), or 'small-caps' (Update: added to spec -spaetz)
  • Allow icon-width and icon-height (or icon-scale?) to use in combination with icon-image (Update: added to spec -spaetz)
  • Additional keywords for line width: thinnest (thinnest possible line for the target device) This requires anti-aliasing. If this drawing style is not supported, it should fall-back to a width value to draw a more or less thin line.)
  • I am not particularly in favor of a "thinnest" keyword. I think you should be able to just specify 0.01 as width and have the renderer figure out what to do with it (if it does not support subpixel, it should fallback to 1 pixel, etc). --spaetz
  • In standard CSS there's a keyword "thin" that maps to the thinnest representable device pixel (not device subpixels for specific color channels, and note that subpixel geometry is not necessarily the same between each physical color channel, and there may be more than the 3 RGB channels, notably on new screens that add a white or yellow subpixel: RGB channels are transformed and rescaled with some more or less linear transform; when printing, these RGB channels are generally converted to CMYK with an additional "blackness" generation method; inkjet printers also don't change the color inks, but adjust the subpixel size using special technics named "masks"); the size of "1px" is not one physical pixel but a virtual pixel with an average DPI setting; CSS has also introduced another unit for device pixels. 16:08, 22 July 2016 (UTC)
  • Introduce right/left option for lines and casings. Use cases: embankments, cycleway:left, may be useful for areas where inside vs outside is determined by direction. Stevage 01:19, 31 January 2011 (UTC)
  • Remove support for #abcdef colours and CSS colour names and replace them with rgb(0.0-1.0, 0.0-1.0, 0.0-1.0) (and variants for other colour spaces). Beelsebob 09:47, 7 February 2011 (UTC)
  • Remove fill-opacity, opacity, casing-opacity, extrude-edge-opacity, extrude-face-opacity, icon-opacity and shield-opacity and roll the behaviour into the respective colour properties, by allowing colours to be specified as rgba(0.0-1.0, 0.0-1.0, 0.0-1.0, 0.0-1.0). Beelsebob 09:47, 7 February 2011 (UTC)
    • Note that in standard CSS the opacity and RGBA colors combine together: the alpha value in RGBA colors (of 100% in RGB colors) is multiplied by the opacity to compute the final alpha channel used to render strokes, fills, texts or images/icons. These properties are then not redundant. It may be useful to keep opacity for icons or when using CSS color names or symbolic UI color names (in CSS3). — Verdy_p (talk)
  • Add casing-z-index, shield-z-index, text-z-index and icon-z-index to stop renderers having to treat the layer tag as a special magical case. Beelsebob 09:47, 7 February 2011 (UTC)
  • Why would node [x=y] be ambiguous? Disallowing this makes parsing significantly harder. Beelsebob 19:14, 12 March 2011 (UTC)
  • Add casings to icon-image or allow shields to be repurposed for nodes.
  • Use casing-width, casing-color, etc. for shields as well as lines. Can't the parser tell it's working on a shield?
  • Allow for scaling of image and fill-image in addition to icon-image --Skippern (talk) 19:03, 25 May 2014 (UTC)
  • Support selectors by tags whose tag name contain spaces or some punctuation. For now tag names cannot be surrounded by "quotes" (exact name), or by /slashes/ (matching tag names with regexps): they generate MapCSS syntax errors. — Verdy_p (talk)

Dealing with z-index and cascades more sensibly

Use the CSS subpart syntax to create multiple styles for a single element. Each subpart defines its own cascade of properties.


way[highway=footway] { width: 2; z-index: 3; }
way[fixme]::fixme_highlight { width: 10; z-index: 2; color: red; text: "fixme"; font-size: 12; }

draws footways with width 2 and highlights all ways if they have the FIXME key. The subpart name is a free identifier, but there are two special subparts:

The default subpart:

way[highway=footway]::default { width: 3; z-index: 2; }

can be interchangeably written as

way[highway=footway] { width: 3; z-index: 2; }.

Otherwise it is just an ordinary subpart.

The * subpart:

It is special in 3 ways:

  1. It is not rendered, so it is only there for "book keeping".
  2. It overrides all existing subparts:
    way::A { a; }
    way::B { b; }
    way::* { c; }
    is equivalent to
    way::A { a; }
    way::B { b; }
    way::A { c; }
    way::B { c; }
  3. 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; }
    way::A { a; b; }.)

-- Bk 15:13, 13 July 2010 (UTC)


  • exit: RichardF said: "It's an optimisation, really - a little hackish addition to tell the parser

to stop checking any rules from this point on, in circumstances where speed is really important. I agree it shouldn't be part of the core spec." and Komяpa says "IMHO this thing was invented just for easier debugging of Halcyon and shouldn't be present in mapcss at all." so we might want to delete it from the core spec.

more on dashes

add the following properties for advanced dashes drawing:

dashes-offset: <NUM>;
dashes-background-color: <COLOR>;

The offset is a number >= 0 that specifies how much to skip from the start of the pattern. Background color sets the color of the line in between the dashes. If the color is non-transparent, this can also be done with the casing property. Otherwise it can be simulated in the following way:

way {
  dashes: 30, 17, 2, 5;
  color: blue;

way::dashes-background {
  dashes: 5, 30, 17, 2;
  dashes-offset: 5;
  color: lightblue;

--Bk 11:25, 26 September 2010 (BST)

Dash gaps should be transparent, and drawn over the background of the line stroke (on which the "casing" border should also be drawn). For that it ia enoguh to define the standard CSS "background-color:" property.
The default background-color is transparent. The "casing" is the standard CSS "border". The CSS padding is just filled with the standard background color. The standard CSS content-box is filled with the line's "color" on top of the "background-color". We don't need a new property (standard CSS does not need it). For more complex layouts, CSS requires embedding several elements.
CSS also has other properties for boxes, notably rounded corners (used to convert the rectangular box into a path with quarter-elliptic arcs in the corners).
For strokes, it also has joining styles (miter, cap, butt, round) and a miter-limit (a max ratio of the miter length over line-with, over which the rest of the miter will be capped) for the miter joining style.
CSS draws only the even-numbered segments, never the odd-numbered ones that are left transparent over the background. CSS also has a property to specify the extebt of the background: by default it is the border-box (which covers the full width of the border line, but it can be set to the padding-box (the "frame" in MapCSS), or the content-box (the inner width of the line in MapCSS).
As MapCSS-based renderers will typically convert map data into SVG (or an SVG-like drawing API) which uses standard CSS, the mapping could be explicited for MapCSS properties to CSS properties (and to additional SVG objects automatically created). — Verdy_p (talk) 02:39, 13 April 2016 (UTC)

Generalized selectors (area)

In addition to the OSM specific basic selectors node, way and relation, it would be useful to have more "abstract" or GIS related selectors.

For a start we could have the area selector, which selects closed ways and Multipolygons.

Currently it would select a closed way with junction=roundabout, although it does not really represent an area. When osm has a real area data type in the future, this can be changed. --Bk 15:46, 2 October 2010 (BST)

area selector is now on the spec. If source data doesn't have relations, renderer could just not implement them. --Komяpa 10:00, 18 June 2011 (BST)
Junction-roundabouts have an implicit tag "area" whose default is "no". The same is true for all highways, junctions, waterways, railways, electric lines and similar (for pedestrian areas, we need to set "area=yes" in addition to "highway=pedestrian").
I think that any setting of the OSM tag "area=yes" or "no" should determine if an area is to be created or not (even if the defining way or relation is not completely closed; this case will be tracked by pseudo-selector "area:tainted", just like there's already "way:tainted" and "relation:tainted").
The mapping of tags with or without the area tag could be done in MapCSS stylesheets (MapCSS will typically include a builtin stylesheet for common cases such as roundabouts and highways).
Once this mapping is done, MapCSS will infer if it can create or not areas from polylines (ways and relations containing way members).
The case of relations containing way members is complex, because MapCSS first need to determine how ways are interconnected by matching pairs of endpoints, and changing their direction to create unidirectional polylines.
Then it will finding closest pairs of unconnected endpoints to create the final list of closed paths (when this occurs, it will map the added closing segments as ":tainted"). The result is a list of closed paths (rings).
Then it will determine if there are pairs of segments with identical pairs of successive nodes: those segments will be removed, silently, and rings will be reorganized by looking for alternate connections in other rings.
Then it will determine if there are intersections in each closed path on itself or between closed paths, and will determine inner and outer rings, splitting paths if necessary (such cases should also be marked as ":tainted" if this requires adding new nodes for intersections).
All this is necessary because ways in relations are frequently in the expected order, or because member ways are drawn in varying directions, or because there are a few self-intersections occuring outside OSM nodes (QA tools or JOSM detect these cases as errors, but OSM still accepts these geometries).
If source data does not have relations, it does not means there are no areas: areas can occur on closed ways, or any way with tag area=yes (even if it's not closed) or any way whose default tag value is yes according to another tag (closed ways are implicitly with area=yes, but highways, railways, waterways, electric lines have an implicit tag area=no). The explicit or implicit value of this tag should drive MapCSS, but some data queries could alter this by creating their own areas, e.g. in Overpass Turbo, or by altering the result set to force the tag to no so that the area will be rendered as a line only). — Verdy_p (talk) 03:09, 13 April 2016 (UTC)

Testing for relation member roles

see subpage

fill-color vs. fill

Why not use standard W3C properties?

I also wonder why.
Various properties have uncommon names, replacing border-color (by "casing-color"), background-color for the padding (by "frame-color"), background-color for the content (by "fill-color")...
From what I see, standard CSS properties have been replaced by new MapCSS-specific "shortcut" properties that consist in applying a CSS property to a specific subpart of the rendered object.
But in many cases, this is not justified as this makes no difference ("casing-color" is always the same as "border-color" and background-color is always the same as "fill color" (except that there's an implied inner content element to which this applies, so that it does not apply to the background of the border or padding).
The number of rendered elements (in SVG) does not exactly matches the number of cartographic elements referenced by MapCSS: they are first transformed into one or several embedded SVG elements.
And MapCSS automatically creates some "custom" objects, that are more complex than a single SVG polygon or line. This also applies to MapCSS "labels" that are formed by embedding an SVG text element within several containers. The same also applies to icons.
However the details of how these custom SVG objects are effectively structured when they are created from OSM elements is still unspecified (and this causes rendering differences, or simply confusion on which MapCSS attribute to use). — Verdy_p (talk) 22:45, 12 April 2016 (UTC)

Dealing with areas

How is the best way to deal with areas. way[condition]:closed and area[condition] seems to be treated differently, at least in JOSM. --Skippern 18:14, 4 July 2011 (BST)

area should cover multipolygons and closed ways. For historical reasons, JOSM handles this a bit different: Unclosed ways are included, but reported by the validator when an area style applies. Actually the abstraction can be seen as an advantage, as renderers can decide on their own, how areas are defined in detail.--Bk 19:30, 8 July 2011 (BST)

icon-image formats and scaling

What formats are supported by icon-image, and is it possible to scale the images? The reason I am asking is that I wish to use SVG graphics. In some cases I would also allow the option to scale images, either use various resolutions of the same SVG file on different zoom levels or in some cases evaluate values to determine resolution. --Skippern 01:30, 7 July 2011 (BST)

scaling is possible. image formats depends on renderer, for now usually png is supported. --Komяpa 13:39, 8 July 2011 (BST)
I found scaling, icon-width and icon-height are documented, but I saw a stylesheet use icon-size (not documented?), which worked for me, looking into making a ticket to accept .SVG in the renderer in question. --Skippern 15:56, 8 July 2011 (BST)
Opened trac ticket in JOSM --Skippern 16:12, 8 July 2011 (BST)
JOSM doesn't support scaling of fill-image, is this something forgotten by MapCSS or is this a JOSM problem? --Skippern 17:54, 13 September 2011 (BST)
I think it is missing in MapCSS so far. --Bk 10:48, 15 September 2011 (BST)

Nested rules

Will there be a rule to handle nested rules? For example one could make a nested rule for natural=wetland with subrules for wetland=* i.e. by giving a background colour in the parent rule and fill symbol in each of the sub rules.... --Skippern 12:45, 26 August 2011 (BST)

In current practice, you would give background color in a [natural=wetland] rule and define details in subsequent rules, that repeat the [natural=wetland] filter, a better example:
way[highway=secondary] { color: yellow; width: 5; }
way[highway=secondary][tunnel=yes] { dashes: 4,4; }
--Bk 17:04, 26 August 2011 (BST)
The reason I ask this is that I am writing a set of highly complicated rules, and nesting would allow me to simplify alot. What I am looking for is something like:
way[highway=secondary] { color: yellow; width: 5; way[tunnel=yes] { dashes: 4,4: } }
--Skippern 20:18, 26 August 2011 (BST)
Yes, I think nested rules would have a lot of potential, but maybe the idea is a little ahead of it's time...--Bk 14:59, 13 September 2011 (BST)
Such idea is far from W3G's standard CSS, but largely inspired by other CSS-like languages for HTML that allows such embedding of rules.
To enable this, a major change would be required in the parser (and because of the recursion, it would require using a LALR parser, with a stack, instead of a basic parser with a single state). The risk is that rendering could become slow, whilst the standard CSS syntax is extremely fast to parse with a single-state automata which allows lots of optimisations not possible with a generic LALR parser.
Also the number of states (independantly of the stack depth) is much lower, and we don't have to manage "shift-reduce" ambiguities with standard CSS, and no need to use backtracking. We also don't need to separate "shift" and "reduce" actions in the single-state parser, both can always be combined. The automata is then twice faster than with LALR ! It is not even needed to have a parser structured around a processing loop.
We've got the same difference between full DOM-based XML-parsers and simple SAX parsers (that don't have to manage the structure of content models): SAX parsers are extremely fast even if they cannot be used for all data models like generic XML parsers (which also require more memory to store the generated DOM).
Remember that performance is important (there are tons of elements to render even for a small rendering tile), and there are also typically a lot of rules with a lot of selectors: most of the time is spent in looking for selectors and see which one are the most specific, multiply this by the number of objects to handle, this is a lot of work!
There are also new rules to invent to specify how properties are inherited or overwritten in embedded rulesets: in basic CSS, the relative order of rules and the relative order of properties does not matter (instead the rules are selected according to the computed specificity of their selector). There are also complex cases when multiple selectors are combined. — Verdy_p (talk) 23:01, 12 April 2016 (UTC)

icon-image on areas

Shouldn't it be possible to use icon-image, or a similar rule on areas? i.e. a hospital icon rendered in the center of a hospital building polygon. --Skippern 21:17, 7 September 2011 (BST)

Good idea, e.g. like Mapnik does it. --Bk 14:53, 13 September 2011 (BST)

Labels from multiple keys

I am looking for a way to render a single string from several keys. I would for example for a navigation light (using seamark:light:colour=*, seamark:light:group=*, seamark:light:character=*, seamark:light:period=*, seamark:light:height=* and seamark:light:range=* into one single string)

Something along this line
eval(uppercase(abreviate(seamark:light:colour=*))) (seamark:light:group=*) seamark:light:character=* seamark:light:period=*sseamark:light:height=*mseamark:light:range=*M
Output should like like this
W (2) Fl 3s5m12M

--Skippern 14:26, 24 October 2012 (BST)

ability to highlight for user_id,timestamp, changeset

This would be usefull when trying to identify different patterns in the map from JOSM or other editors.