SVG Markers

W3C

SVG Markers

W3C First Public Working Draft 09 April 2015

This version:
http://www.w3.org/TR/2015/WD-svg-markers-20150409/
Latest version:
http://www.w3.org/TR/svg-markers/
Latest editor's draft:
https://svgwg.org/specs/markers/
GitHub repository:
https://github.com/w3c/svgwg/tree/master/specs/markers
Feedback:
www-svg@w3.org with subject line “[svg-markers] … message topic” (archive)
Editor:
Cameron McCormack, Mozilla Corporation <cam@mcc.id.au>

Abstract

This specification defines SVG markers, a feature for placing re-usable graphical elements along the outline of an SVG shape.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document is the 09 April 2015 First Public Working Draft of SVG Markers. The purpose of this specification is to define a number of improved SVG marker features.

Comments on this First Public Working Draft are welcome. Comments can be sent to www-svg@w3.org, the public email list for issues related to vector graphics on the Web. This list is archived and senders must agree to have their message publicly archived from their first posting. To subscribe send an email to www-svg-request@w3.org with the word subscribe in the subject line.

This document has been produced by the W3C SVG Working Group as part of the Graphics Activity within the W3C Interaction Domain. The goals of the W3C SVG Working Group are discussed in the W3C SVG Charter. The W3C SVG Working Group maintains a public Web page, http://www.w3.org/Graphics/SVG/, that contains further background information. The authors of this document are the SVG Working Group participants.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

A list of current W3C Recommendations and other technical documents can be found at http://www.w3.org/TR/. W3C publications may be updated, replaced, or obsoleted by other documents at any time.

This document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is non-normative.

A marker is a graphical object that is painted at particular positions along a path, line, polyline or polygon element, together known as the markable elements. There are four ways markers can be placed on these elements:

There are probably better terms to use than "vertex" and "segment" markers. At least, "vertex" would go more naturally with "edge", but we should use more natural sounding names.

The graphics for a marker are defined by a marker element. The ‘marker-start’, ‘marker-end’, ‘marker-mid’, ‘marker-segment’ and ‘marker-pattern’ properties, together known as the marker properties, reference marker elements.

Markers can be animated, and as with use elements, the animated effects will show on all current uses of the markers within the document.

Markers on a given element are painted in the following order, from bottom to top:

1.1. Module interactions

This module replaces and extends the definition of markers in SVG 2 (the "Markers" section in the "Painting: Filling, Stroking and Marker Symbols" chapter). [SVG2]

2. The ‘marker’ element

marker
Categories:
Container element
Content model:
Any number of the following elements, in any order:a, clipPath, cursor, filter, foreignObject, image, marker, mask, script, style, switch, text, view
Attributes:
DOM Interfaces:

The marker element defines the graphics that are to be used for drawing markers on a markable element.

Attribute definitions:

Name Value Lacuna value Animatable
markerUnits strokeWidth | userSpaceOnUse strokeWidth yes

The markerUnits attribute defines the coordinate system for attributes markerWidth, markerHeight and the contents of the marker. Values have the following meanings:

strokeWidth
markerWidth, markerHeight and the contents of the marker represent values in a coordinate system which has a single unit equal the size in user units of the current stroke width (see the ‘stroke-width’ property) in place for the graphic object referencing the marker.
userSpaceOnUse
markerWidth, markerHeight and the contents of the marker represent values in the current user coordinate system in place for the graphic object referencing the marker (i.e., the user coordinate system for the element referencing the marker element via a marker property).
Name Value Lacuna value Animatable
markerWidth, markerHeight <length> | <percentage> | <number> 3 yes

The markerWidth and markerHeight attributes represent the size of the viewport into which the marker is to be fitted according to the viewBox and preserveAspectRatio attributes. A value of zero for either attribute results in nothing being rendered for the marker. A negative value for either attribute is an error (see Error processing).

Name Value Lacuna value Animatable
refX <length> | <percentage> | <number> | left | center | right 0 yes
refY <length> | <percentage> | <number> | top | center | bottom 0 yes

We will add top/center/bottom, left/center/right keywords to refX/refY on marker/symbol. Resolved at London F2F. Values inspired by 'background-position'.

The refX and refY attributes define the reference point of the marker which is to be placed exactly at the marker's position on the markable element. They are interpreted as being in the coordinate system of the marker contents, after application of the viewBox and preserveAspectRatio attributes.

Name Value Lacuna value Animatable
orient auto | auto-start-reverse | <angle> | <number> 0 yes (non-additive)

The orient attribute indicates how the marker is rotated when it is placed at its position on the markable element. Values have the following meaning:

'auto'

A value of 'auto' indicates that the marker is oriented such that its positive x-axis is pointing in the direction of the path at the point it is placed.

This needs to reference a definition for how directionality of a given start/mid/end vertex is calculated. Part of that (which should be moved somewhere more appropriate) is in the path element implementation notes. Some wording from SVG 1.1 appears to have been lost, compare with this.

Here's an example that is a bit unclear currently: <svg> <marker id="m" orient="auto" overflow="visible"> <rect x="-1" y="-0.5" width="1" height="1" fill="green"/> </marker> <path d="M50,0C50,50 50,100 50,100" marker-end="url(#m)" stroke-width="100" stroke="red"/> </svg>
The second control point and the endpoint coincide, should this mean that the direction of the endpoint is a) unknown [aka default to 0 degrees] or b) that you have to look at the previous segment(s)/command(s) until a direction can be established?

If the marker is a segment marker, then the direction the marker is oriented is, if considering the incoming and outgoing directions as unit vectors, in the direction of the sum of these two vectors. If this sum is zero, then the marker is oriented in the incoming direction.

If the marker is on the first or last vertex of a closed subpath, then the incoming direction taken from the final path segment and the outgoing direction is taken from:

  • the first path segment of the following subpath, if the following subpath does not begin with a 'moveto' command, and
  • the first path segment of the current subpath, if the following subpath does begin with a 'moveto' command or if there is no following subpath.
'auto-start-reverse'

A value of 'auto-start-reverse' means the same as 'auto' except that for a marker placed by ‘marker-start’, the orientation is 180° different from the orientation as determined by 'auto'.

This allows a single arrowhead marker to be defined that can be used for both the start and end of a path, point in the right directions.

<angle>
<number>

An <angle> value represents the angle the marker's positive x-axis makes with the positive x-axis in the user space of the markable element, and a <number> value with no unit represents an angle in degrees. For example, if a value of '0' is given, then the marker will be drawn such that its x-axis will align with the x-axis of the user space of the graphic object referencing the marker. A value of '90deg' will result in the marker being drawn with its positive x-axis in the direction of the positive y-axis of the markable element's user space.

The orientation occurs after the marker has been fitted into its viewport. See the Details on how markers are rendered section below for an illustrative example.

Name Value Lacuna value Animatable
position <length> | <percentage> | <number> as if not specified yes

If the marker element is a child of a markable element, then the presence of a position attribute indicates that the marker is a positioned marker and that it will be painted at the specified distance along the path. If the value is negative or greater than the length of the path, then no marker will be painted. If this attribute is specified on a marker that is not a child of a markable element, then it has no effect beyond being exposed in the DOM.

Should a negative or greater than path length value be an "in error" / "unsupported" value?

Name Value Lacuna value Animatable
href URL [URL] as if not specified yes

When a marker element is being used as a positioned marker, the href attribute indicates that the marker referenced by the attribute is to be used as the definition of the marker. The graphical content of the referencing marker element and any of its attributes that affect marker processing are ignored. Authors must not place any child graphical content in the referencing marker or specify the viewBox, preserveAspectRatio, refX, refY, markerUnits, markerWidth, markerHeight or orient attributes on it.

We should say something about referencing marker elements that have an href with the marker properties. I suspect we should just allow this. Whether we want to allow the full element-referencing thing that you can do with gradients, with selective overriding of attributes, I'm not sure.

The contents of the marker are relative to a new coordinate system. The markerUnits attribute determines an initial scale factor for transforming the graphics in the marker into the user coordinate system for the referencing element. An additional set of transformations might occur if there is a viewBox attribute, in which case the coordinate system for the contents of the marker will be transformed due to the processing of attributes viewBox and preserveAspectRatio. If there is no viewBox attribute, then the assumed default value for the the viewBox attribute has the origin of the viewBox coincident with the origin of the viewport and the width/height of the viewBox the same as the width/height of the viewport.

The user agent style sheet sets the ‘overflow’ property for marker elements to hidden, which causes a rectangular clipping path to be created at the bounds of marker's viewport. Unless the ‘overflow’ property is overridden, any graphics within the marker which goes outside of the marker's viewport will be clipped.

Properties inherit into the marker element from its ancestors; properties do not inherit from the element referencing the marker element. Note however that by using the context-stroke value for the ‘fill’ or ‘stroke’ on elements in its definition, a single marker can be designed to match the style of the element referencing the marker.

marker elements are only rendered directly when they are used as children of a markable element and have a position attribute specified. This causes the marker to be painted as a positioned marker. All other marker elements are not rendered directly and must be referenced by one of the marker properties to be rendered. The ‘display’ property does not apply to the marker element; thus, marker elements are not directly rendered even if the ‘display’ property is set to a value other than none, and marker elements are available for referencing even when the ‘display’ property on the marker element or any of its ancestors is set to none. marker elements that are used as positioned markers can simultaneously be referenced by the marker properties to be used as segment markers and repeating markers.

Event attributes and event listeners attached to the contents of a marker element are not processed; only the rendering aspects of marker elements are processed.

Make interaction work on positioned markers.

The following example shows the use of positioned markers to place symbols at particular distances along a path.

  <svg xmlns="http://www.w3.org/2000/svg"
       width="600" height="200" viewBox="0 0 600 200">

     <defs>
       <marker id="Square" markerWidth="10" markerHeight="10"
               refX="5" refY="5" orient="auto">
         <path d="M 5,1 L 9,5 5,9 1,5 z" fill="#6a9100"/>
       </marker>
       <marker id="Circle" markerWidth="10" markerHeight="10"
               refX="5" refY="5" orient="auto">
         <circle cx="5" cy="5" r="2" fill="dodgerblue"/>
       </marker>
     </defs>

     <path d="M 100,50 C 100,250 500,-50 300,150"
           fill="none" stroke="deeppink" stroke-width="3">
       <marker href="#Square" position="0"/>
       <marker href="#Square" position="100%"/>
       <marker href="#Circle" position="50px"/>
       <marker href="#Circle" position="calc(100% - 50px)"/>
       <marker refX="5" refY="5" position="50%">
         <!-- the cross -->
         <path d="M 3,3 L 7,7 M 3,7 L 7,3"
               fill="none" stroke="black" stroke-width="2"/>
       </marker>
     </path>
  </svg>
  
Image showing the use of positioned markers.

Child marker elements are used to position two square and two circular markers. The cross marker is defined inline and does not need an ID.

3. Referencing ‘marker’ elements

A number of marker properties allow specifying a marker using a <marker-ref> value.

<marker-ref> =
<url> |
child |
<child-selector>

where:

<child-selector> =
select(compound selector#)

Values have the following meaning

<url>
Indicates that the marker element referenced by the <url> value will be used. If the URL reference is not valid (e.g., it points to an object that is undefined or the object is not a marker element), then the marker reference is also not valid.
child
Indicates that the last child marker element of the element where the property is specified will be used. If there is no such element, then the reference is not valid.
<child-selector>
Indicates that the first matching descendent marker specified by the <child-selector>, applied in the context of the element where the property is specified, will be used. If no element matches any of the selectors contained in the <child-selector>, or the first match is not a marker, then the reference is not valid.

4. Vertex markers: the ‘marker-start’, ‘marker-mid’ and ‘marker-end’ properties

Name: marker-start, marker-mid, marker-end
Value: none | <marker-ref>
Initial: none
Applies to: markable elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value: as specified, but with <url> values (that are part of a <marker-ref>) made absolute
Animatable: yes

The ‘marker-start’ and ‘marker-end’ properties are used to specify the marker that will be drawn at the first and last vertices of the given markable element, respectively. ‘marker-mid’ is used to specify the marker that will be drawn at all other vertices (i.e., every vertex except the first and last). Possible values for ‘marker-start’, ‘marker-mid’ and ‘marker-end’ are:

none
Indicates that no marker symbol will be drawn at the given vertex or vertices.
<marker-ref>
Indicates that the marker element referenced by the <marker-ref> value will be drawn at the given vertex or vertices. If the reference is not valid, then no marker will be drawn at the given vertex or vertices.

For polygon elements, the last vertex is the same as the first vertex, and for path elements that end with a closed subpath, the last vertex is the same as the first vertex of that final subpath. In this case, if the value of ‘marker-end’ is not none, then it is possible that two markers will be rendered on that final vertex.

Note that ‘marker-start’ and ‘marker-end’ refer to the first and last vertex of the entire path, not each subpath.

The following example shows a triangular marker symbol used as a vertex marker to form an arrowhead at the end of two paths.

<svg xmlns="http://www.w3.org/2000/svg"
       width="275" height="200" viewBox="0 0 275 200">
    <defs>
      <marker id="Triangle" viewBox="0 0 10 10" refX="1" refY="5" 
              markerUnits="strokeWidth" markerWidth="4" markerHeight="3"
              orient="auto">
        <path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"/>
      </marker>
    </defs>

    <g fill="none" stroke-width="10" marker-end="url(#Triangle)">
      <path stroke="crimson" d="M 100,75 C 125,50 150,50 175,75"/>
      <path stroke="olivedrab" d="M 175,125 C 150,150 125,150 100,125"/>
    </g>
  </svg>
Image showing the use of an automatically oriented marker.

The triangle is placed at the end of the path and oriented automatically so that it points in the right direction. The use of context-stroke ensures the fill of the triangle matches the stroke of each path.

5. Segment markers: the ‘marker-segment’ property

Name: marker-segment
Value: none | <marker-ref>
Initial: none
Applies to: markable elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value: as specified, but with <url> values (that are part of a <marker-ref>) made absolute
Animatable: yes

This is a new feature, which allows markers symbols to be placed at the center of path edges, as is common in for example line graphs.

The ‘marker-segment’ property is used to specify the marker that will be drawn at the center of each length path segment. Possible values are:

none
Indicates that no marker symbol will be drawn at the given vertex or vertices.
<marker-ref>
Indicates that the marker element referenced by the <marker-ref> value will be drawn at the center of each path segment. If the reference is not valid, then no marker will be drawn at the path segment centers.

The following example shows the use of both vertex markers and segment markers to construct a line graph.

  <svg xmlns="http://www.w3.org/2000/svg" width="400" height="200">

    <marker id="Circle" markerWidth="8" markerHeight="8" refX="4" refY="4"
            markerUnits="userSpaceOnUse">
      <circle cx="4" cy="4" r="3" fill="deeppink"/>
    </marker>

    <marker id="Cross" markerWidth="10" markerHeight="10" refX="0" refY="0"
            viewBox="-5 -5 10 10" markerUnits="userSpaceOnUse"
            fill="none">
      <path d="M -4,-4 L 4,4 M -4,4 L 4,-4" stroke="white" stroke-width="4"/>
      <path d="M -4,-4 L 4,4 M -4,4 L 4,-4" stroke="black" stroke-width="2"/>
    </marker>

    <!-- grid lines -->
    <path stroke="#888" d="M 40,20 360,20 M 40,40 360,40 M 40,60 360,60
                           M 40,80 360,80 M 40,100 360,100 M 40,120 360,120
                           M 40,140 360,140 M 40,160 360,160 M 40,180 360,180"/>

    <!-- the graph line -->
    <polyline points="50,100 100,20 150,50 200,130 250,80 300,170 350,100"
              fill="none" stroke="deeppink" stroke-width="2"
              marker="url(#Circle)" marker-segment="url(#Cross)"/>
  </svg>
  
Image showing the use of segment markers.

Segment markers are used to place crosses at the center of each line segment in the line graph.

6. Repeating markers: the ‘marker-pattern’ property

Name: marker-pattern
Value: <marker-gap>? <marker-ref-group> [ <marker-gap> <marker-ref-group> ]* <marker-gap>?
Initial: none
Applies to: markable elements
Inherited: yes
Percentages: refer to the length of the path
Media: visual
Computed value: as specified, but with <url> values (that are part of a <marker-ref>) made absolute
Animatable: yes

where:

<marker-gap> =
<length> | <percentage> | <number>
<marker-ref-group> =
none | <marker-ref>+

This is a new feature, which allows markers to be placed at positions unrelated to the segments used to form the path.

The ‘marker-pattern’ property is used to specify a pattern of markers and gaps to be repeated along the length of the markable element. Values have the following meanings:

none
Indicates that no marker will be painted at the current position along the path.
<marker-gap>
Indicates the length of a gap in the repeated pattern of markers.
<marker-ref>
A reference to a marker that will be placed at the current position along the path. If the reference is not valid, then no marker for that <marker-ref> will be painted.

If a value other than none is given, and the sum of the <length>s, <percentage>s and <number>s is not positive, then it is an invalid value.

Unlike vertex markers, the orientation of an orient="auto" repeating marker that happens to lie on a vertex does not take into account the incoming and outgoing directions. Instead, it is simply oriented such that its positive x-axis is aligned with the direction of the path at its position.

The following example shows the use of the ‘marker-pattern’ property to specify a repeating pattern of two different markers spaced along a path.

  <svg xmlns="http://www.w3.org/2000/svg" width="600" height="200">

    <marker id="DoubleDash" markerWidth="8" markerHeight="12" refX="0" refY="0"
            viewBox="-4 -6 8 12" markerUnits="userSpaceOnUse" orient="auto">
      <rect x="-3" y="-5" width="2" height="10"/>
      <rect x="1" y="-5" width="2" height="10"/>
    </marker>
    <marker id="SingleDash" markerWidth="4" markerHeight="12" refX="0" refY="0"
            viewBox="-2 -6 4 12" markerUnits="userSpaceOnUse" orient="auto">
      <rect x="-1" y="-5" width="2" height="10"/>
    </marker>

    <path d="M 50,100 S 100,132 150,86 200,173 250,76 300,81
                        350,136 400,87 450,166 500,87 550,96"
          stroke="deeppink" stroke-width="2" fill="none"
          marker-pattern="40 url(#DoubleDash) 40 url(#SingleDash)"/>
  </svg>
  
Image showing the use of repeating markers.

Markers specified with the ‘marker-pattern’ property are placed along the path at fixed distances, not relative to the path vertices.

7. Marker shorthand: the ‘marker’ property

Name: marker
Value:
[ none | <marker-ref> ]{1,4} [ / <‘marker-pattern’> ]?
| <marker-ref>{0,4} [ <length> | <percentage> | <number> ] [ <length> | <percentage> | <number> | <marker-ref> ]*
Initial: not defined for shorthand properties
Applies to: markable elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value: see individual properties
Animatable: yes

The ‘marker’ property sets values for the ‘marker-start’, ‘marker-mid’, ‘marker-end’, ‘marker-segment’ and ‘marker-pattern’ properties. Values for have the following meanings:

none | <marker-ref>
Sets ‘marker-start’, ‘marker-mid’ and ‘marker-end’ to the specified value, and sets ‘marker-segment’ and ‘marker-pattern’ to none.
[ none | <marker-ref> ]{2}
Sets ‘marker-start’ and ‘marker-end’ to the two values specified, and sets ‘marker-mid’, ‘marker-segment’ and ‘marker-pattern’ to none.
[ none | <marker-ref> ]{3}
Sets ‘marker-start’, ‘marker-mid’ and ‘marker-end’ to the three values specified, and sets ‘marker-segment’ and ‘marker-pattern’ to none.
[ none | <marker-ref> ]{4}
Sets ‘marker-start’, ‘marker-segment’, ‘marker-mid’ and ‘marker-end’ to the four <marker-ref> values specified, and sets ‘marker-pattern’ to none.
[ none | <marker-ref> ]{1,4} / <‘marker-pattern’>
Sets ‘marker-start’, ‘marker-segment’, ‘marker-mid’ and ‘marker-end’ to the four <marker-ref> values specified before the slash, and sets ‘marker-pattern’ to the value after the slash.
anything else
Sets ‘marker-start’, ‘marker-segment’, ‘marker-mid’ and ‘marker-end’ to none, and sets ‘marker-pattern’ to the specified value.

8. Knocking out the stroke: the ‘marker-knockout-left’ and ‘marker-knockout-right’ properties

The marker knockout properties are still under heavy development and are subject to change. Feedback on how authors might prefer to specify marker knockout shapes is welcome.

Name: marker-knockout-left, marker-knockout-right
Value: <knockout-offset> | <knockout-shape> [ at <knockout-offset> ]?
Initial: 0
Applies to: marker
Inherited: no
Percentages: see prose
Media: visual
Computed value: as specified
Animatable: yes

where:

<knockout-offset> =
[ <length> | <percentage> | <number> ]
<knockout-shape> =
[ <length> | <percentage> | <number> ] inverted? circle |
[ <length> | <percentage> | <number> ]{2} inverted? ellipse |
[ <length> | <percentage> | <number> ]{1,2} inverted? [ rectangle | triangle ]

This is a new feature, which allows authors to specify parts of a stroke that should be clipped away when a marker is placed on a path. This helps with arrowheads, where the stroke must not be visible behind the pointy end, and with hollow markers as seen in metro maps, where the center of a marker is transparent and the stroke should not show through.

When specified on a marker element, the ‘marker-knockout-left’ and ‘marker-knockout-right’ properties together specify a shape to clip away when when painting the stroke of an element that uses the marker. ‘marker-knockout-left’ specifies the left side of the shape and ‘marker-knockout-right’ the right side. These two sides are joined together with straight lines.

The <knockout-offset> part of the value, if specified, is the offset from the marker position, outwards, along the tangent, that the knockout shape side is placed at. This is the knockout shape side position. If it is omitted, then the offset is assumed to be zero. The value can be negative. Percentage values refer to the width of the marker contents viewport.

The <knockout-shape> part of the value, if specified, is the left or right side of the knockout shape. Values have the following meanings:

[ <length> | <percentage> | <number> ]{2} inverted? ellipse

The knockout shape side is an arc. The lengths or percentages specified are the x-radius and y-radius of the ellipse from which the arc is taken. A length is interpreted as being in the marker contents coordinate system. If the first value is a percentage, then it refers to the width of the marker contents viewport, and if the second value is a percentage then it refers to the height of the marker contents viewport.

If the inverted keyword is not specified, then the arc is constructed by placing the center of the ellipse at the knockout shape side position. First we consider only the 180° arc of the ellipse which points in the direction of the start of the start of the path, if this is the left knockout shape side, or the end of the path if this is the right knockout shape side. If the y-radius is less than or equal to half of the stroke width of the path the marker is on, then this 180° arc is the final knockout shape side. Otherwise, we intersect the arc with the two lines that are offset, by half of the stroke width, from the tangent to the marker orientation. The resulting arc with its start and end points on these two lines is the final knockout shape side.

If the inverted keyword is specified, then the arc is constructed by placing the center of the ellipse at a distance of two times its x-radius along the tangent to the marker orientation, in the direction of the start of the path if this is the left knockout shape side, or the end of the path if this is the right knockout shape side. We consider only the 180° arc of the ellipse that is pointing in the opposite direction. If the y-radius is less or equal to half of the stroke width of the path the marker is on, then this 180° arc is the final knockout shape side. Otherwise, we intersect the arc with the two lines that are offset, by half of the stroke width, from the tangent to the marker orientation. The resulting arc with its side and end points on these two lines is the final knockout shape side.

[ <length> | <percentage> | <number> ] inverted? circle

The knockout shape side is an arc. The shape is computed in the same way as the ellipse shape, but with both radii of the ellipse being the specified length or percentage, and with a percentage referring to the size of the marker contents viewport.

[ <length> | <percentage> | <number> ]{1,2} inverted? rectangle

The knockout shape side comprises one or two rectangles. These rectangles are aligned such that their top and bottom edges are parallel to the tangent to the marker orientation. The length or percentage is a width and the second, if specified, is a height. Percentage values here refer to the width and height of the marker contents viewport, respectively.

If the inverted keyword is not specified, then the knockout shape side is a single rectangle. The width of the rectangle is the specified width value. The height of the rectangle is the maximum of the stroke width of the path on which the marker exists and the specified height value, if it is specified. If it is not specified, then the height of the rectangle is just the stroke width. The rectangle is posisioned such that the center of its right hand edge is positioned at the knockout shape side position and the extent of its width is in the direction of the start of the path, if this is the left knockout shape side, or the end of the path if this is the right knockout shape side.

If the inverted keyword is specified, then the knockout shape side comprises two rectangles. If the specified height is greater than or equal to the stroke width, then the height of these rectangles is zero; otherwise, their heights are half of the difference between the stroke width and the specified height. The top edge of one of the rectangles is half of the stroke width away from the marker orientation tangent line, with its bottom edge closer to the tangent line. The other rectangle has its bottom edge half of the stroke width away from the tangent line and its top edge closer to the tangent line. The right edges of the rectangles are aligned with each other and also with the line perpendicular to the marker orientation tangent line. The extent of the widths of the rectangles is in the direction of the start of the path, if this is the left knockout shape side, or the end of the path if this is the right knockout shape side.

[ <length> | <percentage> | <number> ]{1,2} inverted? rectangle

The knockout shape side comprises one or two rectangles. These rectangles are aligned such that their top and bottom edges are parallel to the tangent to the marker orientation. The length or percentage is a width and the second, if specified, is a height. Percentage values here refer to the width and height of the marker contents viewport, respectively.

If the inverted keyword is not specified, then the knockout shape side is a single rectangle. The width of the rectangle is the specified width value. The height of the rectangle is the maximum of the stroke width of the path on which the marker exists and the specified height value, if it is specified. If it is not specified, then the height of the rectangle is just the stroke width. The rectangle is posisioned such that the center of its right hand edge is positioned at the knockout shape side position and the extent of its width is in the direction of the start of the path, if this is the left knockout shape side, or the end of the path if this is the right knockout shape side.

If the inverted keyword is specified, then the knockout shape side comprises two rectangles. If the specified height is greater than or equal to the stroke width, then the height of these rectangles is zero; otherwise, their heights are half of the difference between the stroke width and the specified height. The top edge of one of the rectangles is half of the stroke width away from the marker orientation tangent line, with its bottom edge closer to the tangent line. The other rectangle has its bottom edge half of the stroke width away from the tangent line and its top edge closer to the tangent line. The right edges of the rectangles are aligned with each other and also with the line perpendicular to the marker orientation tangent line. The extent of the widths of the rectangles is in the direction of the start of the path, if this is the left knockout shape side, or the end of the path if this is the right knockout shape side.

[ <length> | <percentage> | <number> ]{1,2} inverted? triangle

...

A diagram showing the construction of these shapes would be helpful.

Need to define how the two shape sides are joined together. It's taking the top and bottom points from both shapes, drawing vertical lines to the edge of the stroke shape, then drawing two horizontal lines to join them together.

The two knockout shape sides must not intersect, although they may touch. If they do intersect, then no knockout is performed for that marker when painting the stroke.

For example, using 8px inverted triangle at -4px for ‘marker-knockout-left’ and 8px triangle for ‘marker-knockout-right’ is allowed, as the two straight lines that form the left shape side do not intersect with either of the two straight lines that form the right shape side. However, using 8px triangle at -4px for both properties would obviously cause an intersection, and so would not be allowed.

Image showing various marker knockout shapes.

An illustration of the use of inverted and non-inverted circle, rectangle and triangle knockout shapes, at both 0px and 10px offsets. The value beneath each pink stroke is used for both ‘marker-knockout-left’ and ‘marker-knockout-right’. (The marker itself here has no content and does not render anything.)

While this is nice for straight line segments, if the path is curved at the marker position then it might be preferable to have the knockout shapes aligned with the tangent at the knockout shape side position, rather than with the marker orientation. Especially if the knockout is being used as a fancy dash pattern. Then we would likely want to join the left and right sides of the shape with a curved shape (along the stroke) and not just a rectangle. If we allow this, then computing that shape is going to be hard, and will mean that determining whether the left and right sides of the knockout shape intersect, and determining what the intersections of all of the knockout shapes on a path are, is also going to be hard. Perhaps that can be handled by extending dashing line caps with these shapes rather than here? Regardless of whether it is handled by marker knockouts or new line caps, it's going to be non-trivial to compute the right shapes.

Another thing to note is that knockouts here are like setting up a clipping path to remove parts of the stroke when it's painted. That means that if the stroke intersects itself over the knockout areas, it's going to be knocked out of all bits of the stroke that go through those areas. That may or may not be fine depending on your use cases.

9. Details on how markers are rendered

For each marker that is drawn, a temporary new user coordinate system is established so that the marker will be positioned and sized correctly, as follows:

The rendering effect of a marker is as if the contents of the referenced marker element were deeply cloned into a separate non-exposed DOM tree for each instance of the marker. Because the cloned DOM tree is non-exposed, the SVG DOM does not show the cloned instance of the marker.

For user agents that support Styling with CSS, the conceptual deep cloning of the referenced marker element into a non-exposed DOM tree also copies any property values resulting from the CSS cascade and property inheritance on the referenced element and its contents. CSS 2.1 selectors can be applied to the original (i.e., referenced) elements because they are part of the formal document structure. CSS 2.1 selectors cannot be applied to the (conceptually) cloned DOM tree because its contents are not part of the formal document structure.

For illustrative purposes, we'll repeat the marker example shown earlier:

  <?xml version="1.0" standalone="no"?>
  <svg width="4in" height="2in" 
       viewBox="0 0 4000 2000"
       xmlns="http://www.w3.org/2000/svg">
    <defs>
      <marker id="Triangle"
        viewBox="0 0 10 10" refX="0" refY="5" 
        markerUnits="strokeWidth"
        markerWidth="4" markerHeight="3"
        orient="auto">
        <path d="M 0 0 L 10 5 L 0 10 z" />
      </marker>
    </defs>
    <rect x="10" y="10" width="3980" height="1980"
         fill="none" stroke="blue" stroke-width="10" />
    <desc>Placing an arrowhead at the end of a path.
    </desc>
    <path d="M 1000 750 L 2000 750 L 2500 1250"
          fill="none" stroke="black" stroke-width="100" 
          marker-end="url(#Triangle)"  />
  </svg>
  

The rendering effect of the above file will be visually identical to the following:

  <?xml version="1.0" standalone="no"?>
  <svg width="4in" height="2in" 
       viewBox="0 0 4000 2000"
       xmlns="http://www.w3.org/2000/svg">
    <desc>File which produces the same effect
        as the marker example file, but without
        using markers.
    </desc>
    <rect x="10" y="10" width="3980" height="1980"
         fill="none" stroke="blue" stroke-width="10" />
    <!-- The path draws as before, but without the marker properties -->
    <path d="M 1000 750 L 2000 750 L 2500 1250"
          fill="none" stroke="black" stroke-width="100"  />
    <!-- The following logic simulates drawing a marker 
         at final vertex of the path. -->
    <!-- First off, move the origin of the user coordinate system
         so that the origin is now aligned with the end point of the path. -->
    <g transform="translate(2500,1250)" >
      <!-- Rotate the coordinate system 45 degrees because
           the marker specified orient="auto" and the final segment
           of the path is going in the direction of 45 degrees. -->
      <g transform="rotate(45)" >
        <!-- Scale the coordinate system to match the coordinate system
             indicated by the 'markerUnits' attributes, which in this case has
             a value of 'strokeWidth'. Therefore, scale the coordinate system
             by the current value of the 'stroke-width' property, which is 100. -->
        <g transform="scale(100)" >
          <!-- Translate the coordinate system by 
               (-refX*viewBoxToMarkerUnitsScaleX, -refY*viewBoxToMarkerUnitsScaleY)
               in order that (refX,refY) within the marker will align with the vertex.
               In this case, we use the default value for preserveAspectRatio
               ('xMidYMid meet'), which means find a uniform scale factor
               (i.e., viewBoxToMarkerUnitsScaleX=viewBoxToMarkerUnitsScaleY)
               such that the viewBox fits entirely within the viewport ('meet') and 
               is center-aligned ('xMidYMid'). In this case, the uniform scale factor
               is markerHeight/viewBoxHeight=3/10=.3. Therefore, translate by
               (-refX*.3,-refY*.3)=(0*.3,-5*.3)=(0,-1.5). -->
          <g transform="translate(0,-1.5)" >
            <!-- There is an implicit clipping path because the user agent style
                 sheet says that the 'overflow' property for markers has the value
                 'hidden'. To achieve this, create a clipping path at the bounds
                 of the viewport. Note that in this case the viewport extends
                 0.5 units to the left and right of the viewBox due to 
                 a uniform scale factor, different ratios for markerWidth/viewBoxWidth
                 and markerHeight/viewBoxHeight, and 'xMidYMid' alignment -->
            <clipPath id="cp1" >
              <rect x="-0.5" y="0" width="4" height="3" />
            </clipPath>
            <g clip-path="url(#cp1)" >
              <!-- Scale the coordinate system by the uniform scale factor
                   markerHeight/viewBoxHeight=3/10=.3 to set the coordinate
                   system to viewBox units. -->
              <g transform="scale(.3)" >
                <!-- This 'g' element carries all property values that result from
                     cascading and inheritance of properties on the original 'marker' element.
                     In this example, neither fill nor stroke was specified on the 'marker'
                     element or any ancestors of the 'marker', so the initial values of
                     "black" and "none" are used, respectively. -->
               <g fill="black" stroke="none" >
                  <!-- Expand out the contents of the 'marker' element. -->
                  <path d="M 0 0 L 10 5 L 0 10 z" />
                </g>
              </g>
            </g>
          </g>
        </g>
      </g>
    </g>
  </svg>
  

View this example as SVG (SVG-enabled browsers only)

10. IDL

10.1. Interface SVGMarkableElement

The SVGMarkableElement interface is implemented on all markable elements, and provides access to the markers that are placed on the element's path.

[NoInterfaceObject]
  interface SVGMarkableElement {
    readonly attribute SVGMarkerList markers;

    long getMarkerIndexFromPoint(DOMPoint point);
  };

  SVGLineElement implements SVGMarkableElement;
  SVGPathElement implements SVGMarkableElement;
  SVGPolygonElement implements SVGMarkableElement;
  SVGPolylineElement implements SVGMarkableElement;
Attributes:
markers (readonly SVGMarkerList)
The list of markers on this element.
Operations:
long getMarkerIndexFromPoint(DOMPoint point)
Returns the index into the SVGMarkerList of the marker that is at the specified point. Normal hit testing rules apply; the value of the ‘pointer-events’ property on the elements that comprise the markers, as well as its value on this element, is honored, and the top-most marker is selected when there are multiple markers whose content is at the given point.
Parameters
  1. DOMPoint point
    The point to check for intersection with the markers on this element. The DOMPoint is interpreted as a point in the user space of this element.
Returns
The index into this element's SVGMarkerList of the marker at the given point, or -1 if there is no such marker.

10.2. Interface SVGMarkerElement

The SVGMarkerElement interface corresponds to the marker element.
interface SVGMarkerElement : SVGElement {

    // Marker Unit Types
    const unsigned short SVG_MARKERUNITS_UNKNOWN = 0;
    const unsigned short SVG_MARKERUNITS_USERSPACEONUSE = 1;
    const unsigned short SVG_MARKERUNITS_STROKEWIDTH = 2;

    // Marker Orientation Types
    const unsigned short SVG_MARKER_ORIENT_UNKNOWN = 0;
    const unsigned short SVG_MARKER_ORIENT_AUTO = 1;
    const unsigned short SVG_MARKER_ORIENT_ANGLE = 2;

    readonly attribute SVGAnimatedLength refX;
    readonly attribute SVGAnimatedLength refY;
    readonly attribute SVGAnimatedEnumeration markerUnits;
    readonly attribute SVGAnimatedLength markerWidth;
    readonly attribute SVGAnimatedLength markerHeight;
    readonly attribute SVGAnimatedEnumeration orientType;
    readonly attribute SVGAnimatedAngle orientAngle;
             attribute DOMString orient;

    void setOrientToAuto();
    void setOrientToAngle(SVGAngle angle);
  };

  SVGMarkerElement implements SVGFitToViewBox;
Constants in group “Marker Unit Types”:
SVG_MARKERUNITS_UNKNOWN (unsigned short)
The marker unit type is not one of othe other predefined types. It is invalid to attempt to define a new value of this type or to attempt to switch an existing value to this type.
SVG_MARKERUNITS_USERSPACEONUSE (unsigned short)
The value of attribute markerUnits is 'userSpaceOnUse'.
SVG_MARKERUNITS_STROKEWIDTH (unsigned short)
The value of attribute markerUnits is 'strokeWidth'.
Constants in group “Marker Orientation Types”:
SVG_MARKER_ORIENT_UNKNOWN (unsigned short)
The marker orientation is 'auto-start-rotate' or is not one of the predefined types. It is invalid to attempt to define a new value of this type or to attempt to switch an existing value to this type.
SVG_MARKER_ORIENT_AUTO (unsigned short)
Attribute orient has value 'auto'.
SVG_MARKER_ORIENT_ANGLE (unsigned short)
Attribute orient has an angle value.
Attributes:
refX (readonly SVGAnimatedLength)
Corresponds to attribute refX on the given marker element.
refY (readonly SVGAnimatedLength)
Corresponds to attribute refY on the given marker element.
markerUnits (readonly SVGAnimatedEnumeration)
Corresponds to attribute markerUnits on the given marker element. One of the Marker Unit Types defined on this interface.
markerWidth (readonly SVGAnimatedLength)
Corresponds to attribute markerWidth on the given marker element.
markerHeight (readonly SVGAnimatedLength)
Corresponds to attribute markerHeight on the given marker element.
orientType (readonly SVGAnimatedEnumeration)
Corresponds to attribute orient on the given marker element. One of the Marker Orientation Types defined on this interface. If the orient attribute is set to 'auto-start-rotate', then the value of orientType is SVG_MARKER_ORIENT_UNKNOWN.
orientAngle (readonly SVGAnimatedAngle)
Corresponds to attribute orient on the given marker element. If markerUnits is SVG_MARKER_ORIENT_ANGLE, the angle value for attribute orient; otherwise, it will be set to zero.
orient (DOMString)
Corresponds to attribute orient on the given marker element. This attribute simply reflects the value of the orient content attribute.
Operations:
void setOrientToAuto()
Sets the value of attribute orient to 'auto'.
void setOrientToAngle(SVGAngle angle)
Sets the value of attribute orient to the given angle.
Parameters
  1. SVGAngle angle
    The angle value to use for attribute orient.

10.3. Interface SVGMarkerInstance

The SVGMarkerInstance interface is used to represent an instance of a marker that is on a markable element. An SVGMarkerInstance can represent any kind of marker, including positioned markers.

What should we do about liveness? If it is live, we could have it know what index it is for, and always return information about the marker at that index (and return null for the element if that index is no longer valid).

interface SVGMarkerInstance {
    readonly attribute SVGMarkerElement element;
    readonly attribute float position;
    readonly attribute DOMPointReadOnly point;
    readonly attribute float angle;
  };
Attributes:
element (readonly SVGMarkerElement)
The marker element that defines the marker. If the marker is a vertex marker, segment marker or repeating marker, then this will be the marker element that the relevant marker property referenced. If the marker is a positioned marker, then this will be the child marker element of the markable element.
position (readonly float)
The distance along the equivalent path of the markable element that the marker is positioned at.
point (readonly DOMPointReadOnly)
The point, in the user space of the markable element, that the marker is positioned at. The DOMPointReadOnly object is read only.
angle (readonly float)
The orientation of the marker relative to a vector pointing in the direction of the positive y-axis of the markable element's user space.

10.4. Interface SVGMarkerList

The SVGMarkerList interface is used to expose the list of markers that are painted on a given markable element. This list includes all vertex markers, segment markers, repeating markers and positioned markers. The list of SVGMarkerInstance objects is maintained in the order that the markers are painted.

The supported property indices of an SVGPathSegList object is all non-negative integers less than the length of the list.

interface SVGMarkerList {
    readonly attribute unsigned long length;
    getter SVGMarkerInstance? item(unsigned long index);
  };
Attributes:
length (readonly unsigned long)
The number of markers on this element.
Operations:
SVGMarkerInstance? item(unsigned long index)
Gets the SVGMarkerInstance at the given position in the list of markers on this element.
Parameters
  1. unsigned long index
    The index of the SVGMarkerInstance to return.
Returns
Returns the SVGMarkerInstance at position index in the list of markers on this element, or null if index is out of range.

11. References

11.1. Normative references

[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner, March 1997.
Available at http://tools.ietf.org/html/rfc2119.
[SVG2]
Scalable Vector Graphics (SVG) 2, N. Andronikos, T. Bah, A. Bellamy-Royds, B. Birtles, C. Concolato, E. Dahlström, C. Lilley, C. McCormack, D. Schepers, D. Schulze, R. Schwerdtfeger, S. Takagi, J. Watt, eds. World Wide Web Consortium, 09 April 2015.
This edition of SVG 2 is http://www.w3.org/TR/2015/WD-SVG2-20150409/.
The latest edition of SVG 2 is available at http://www.w3.org/TR/SVG2/.

12. Changes since SVG 2