MapCSS/0.1
Play with it!
The easiest way to get acquainted with MapCSS is to play with it.
You can have a go at http://www.geowiki.com/halcyon/ . Just edit the stylesheet on the right and click 'Refresh' to see your changes. You'll find it instantly accessible if you've ever written any CSS for a webpage before. (Halcyon was unavailable when checked on 2013-01-29.)
This is a first draft. See MapCSS/0.2 for improvements under discussion to the MapCSS spec.
Vocabulary
Line properties
definition | example | Halcyon | Kothic | |
---|---|---|---|---|
z-index | Specifies a sublayer within an OSM layer; Halcyon supports values of 0-10 | + | + | |
width | Line width. Halcyon currently supports numbers only (i.e. 5, not 5px) | width: 5 | + | + |
color | Colour of the line - either a hex value or a CSS colour name | color: blue color: #0000FF |
+ | + |
opacity | How transparent the line is, from 0 (transparent) to 1 (opaque) | opacity: 0.5 | + | + |
dashes | An array of alternating on/off lengths | dashes: 2,2,4,2 | + | + |
linecap | The style for the end of the line: 'none' (default), 'round' or 'square' | + | + | |
linejoin | The style for line corners: 'round' (default), 'miter' or 'bevel' | + | + | |
fill-color | Colour in which to fill the area, if closed - hex value or CSS colour | fill-color: lightgreen | + | + |
fill-opacity | How transparent the fill is, from 0 (transparent) to 1 (opaque). Halcyon: Works only on fill-color, fill-image is always full opaque. | fill-opacity: 0.2 | + | + |
fill-image | The URL (absolute or relative) of an image with which to fill the area | fill-image: fills/grass.png | + | - |
casing-width | Width of the casing (border) of the line. This is the width of the entire line, so for a 1px border on either side of a 7px line, you would specify a casing-width of 9 | casing-width: 9 | + | + |
casing-color | The colour (hex or CSS name) of the casing | + | + | |
casing-opacity | The transparency of the casing | + | + | |
casing-dashes | An array of alternating on/off lengths | + | + | |
casing-linecap | Style for the end of the casing line (defaults to value of "linecap") | - | + | |
casing-linejoin | The style for casing line corners (defaults to value of "linejoin") | - | + |
Point/icon properties
definition | example | Halcyon | Kothic | |
---|---|---|---|---|
icon-image | URL (absolute or relative) of an image to use as an icon | + | - |
Label properties
definition | example | Halcyon | Kothic | |
---|---|---|---|---|
font-family | Name of the font to use | font-family: DejaVu | + | - |
font-size | Size of the text (Halcyon supports number only at present, no units) | font-size: 12 | + | + |
font-weight | 'bold' or 'normal' | font-weight: bold | + | - |
font-style | 'italic' or 'normal' | font-style: italic | + | - |
text-decoration | 'none' or 'underline' | text-decoration: underline | + | - |
text-transform | 'none' or 'uppercase' | text-transform: uppercase | + | - |
text-color | A hex value or CSS colour name | text-color: #07CF20 | + | + |
text-position | Whether the text follows the path of the way ('line') or is centred on the area ('center') | text-position: center | + | +/- (only center now) |
text-offset | The vertical offset from the centre of the way or point. An offset of 5, on a line of width 3, would put the text "along" the line rather than within it. Similarly, an offset of 8, on a point with a 16-high icon, would put the text below the icon. | text-offset: -5 | + | - |
max-width | The maximum width of a text label for a point, after which it should wrap onto the next line | max-width: 30 | + | - |
text | The tag key whose value is used for the label. For example, 'text: name' would render the name tag | text: name | + | + |
text-halo-color | The colour (hex or CSS) of the 'halo' or 'pull-out' used to make the text stand out from features underneath it | text-halo-color: white | + | + |
text-halo-radius | The radius of the halo | text-halo-radius: 2 | + | + |
Shield properties
Shield properties are not yet supported by Halcyon but are likely to be shield-image and shield-text.
Grammar
Selectors - elements
The selector elements are the core OSM objects:
- node
- way
- relation
When a rule applies to two selectors, we can group them with a comma:
way[highway=primary], way[highway=trunk]
The descendant combinator is used when one object is contained in another. For example, a way in a relation, or a node in a way.
way[highway=footpath] node[barrier=gate] { icon-image: icons/gate.png; } relation[type=route] way[highway] { stroke-color: red; }
We can be liberal in how we treat white space: the latter would be unambiguous as
relation [type=route] way [highway] { stroke-color: red; }
Selectors - tests
Basic tests are added as you'd expect:
way[highway=primary] /* way with the highway tag set to primary */
You can also simply test whether a tag is set or not, in one of two ways:
way[highway] /* way with the highway tag set */ way[!highway] /* way with the highway tag not set */ way .highway /* way with the highway tag set (see pseudo-classes below) */
A wide range of attribute selectors (special conditions) are supported:
way[highway=~/primary/] /* regex */ way[!highway] /* way without a highway tag */ node[place=city][population<50000] node[place=city][population>=50000]
and in a little bit of invisible magic,
way[oneway=yes]
also looks for =true or =1.
The test for a zoom level works well using the CSS namespace selector:
way|z12-[population<50000] way|z1-11[population>50000]
and of course, if it's not specified, it applies to all zoom levels. Theoretically this could be extended to cope with other units of measurement, e.g. way|s50000 for a 1:50,000 printed map.
The role in a relation is exposed via the 'role' pseudo-tag, so you can test for:
relation[type=route] way[role=proposed] { color: blue; }
(This is not yet supported by Halcyon.)
Declarations
Declarations are almost exactly as you'd expect, echoing common CSS vocabulary where possible - see above.
Additional declarations:
{ exit; } /* stops parsing (just a performance optimisation) */ { set tag=value; } /* set a tag */ { set tag; } /* set a tag to 'yes' */
You can compute values using an eval instruction:
{ opacity: eval('population/100000'); } { set width_in_metres=eval('lanes*3'); }
(Note that Halcyon currently only supports numeric eval, though string eval is planned.)
Halcyon has the ability to 'stack' renderings for a particular rule, so you can have several stokes for a particular way.
This means you can have more than one declaration block:
way|z12[highway=primary] { z-index: 0; width: 5px; stroke-color: red; } { z-index: 1; width: 1px; stroke-color: black; dashes: 1, 3, 2, 3; }
Classes
You can set tags beginning with a full-stop to simulate classes:
{ set .minor_road; }
You can then use the .minor_road test (as above) in the selector:
way .minor_road { width: 2pt; color: yellow; }
This opens up possibilities when used with the @import rule and a media type. You can have a set of rules for each medium (e.g. direct from an OSM database, or from the product of osm2pgsql), each of which set pseudo-classes. The main stylesheet is then applied to these styles:
@import url("osmtags.css") osmtags; @import url("osmpostgis.css") osmpostgis;
(The @import rule is not yet supported by Halcyon.)
Pseudo-classes
Interactive clients can support :hover and :active pseudo-classes.
The :area pseudo-class applies if a way is 'closed' (first and last nodes are the same).