SVG to VML
From my extensive research (this wikipedia post) the SVG specification is, in part, based off the VML spec. When comparing the two formats, there are a lot of similarities so I’ve written up this brief guide to help you manually convert SVG to VML.
This is not a quick or easy process but could be good if you wanted to convert your brand logo to VML so it will always show in MSO Outlook even with images turned off. Someone more skilled than me could probably build a tool to convert SVG to VML automatically. If you know of such a tool or are planning to build one I’m love to know about it.
If you’re interested in SVG I also have a post about using SVG in email.
This article covers:
- Wrapper - Creating a wrapper
- Line - Drawing a line
- Square - Drawing a square
- Circle - Drawing a circle
- Custom shape - Drawing a custom shape
- Colour - Adding colour to the shapes
- Stroke - Adding a stroke to the shapes
- Accessibility - Accessibility considerations
Both formats can have an outer wrapper, however the VML wrapper is optional. If you’re only inserting a single VML element you can do it without a wrapper.
This specifies the xml namespace for a document. This is optional in both cases but for VML if it’s not on the shape, then it must be added to the HTML tag
Because these are vector images, they can be scaled to any size, so we need to define the dimensions of the space we’re working in. I like to think of it like the artboard size or canvas size that you would use in design software. So if we place something 10 from the top and 10 from the left, it’ll be relevant to the sizes we define here.
SVG viewBox: The SVG
viewbox has 4 values min-x, min-y, width and height, for now we’ll ignore the first 2 and assume they are both set to
VML coordsize: VML
coordsize only has 2 values width and height, so these should match the last 2 values of the
I need to read more into it but it looks like
coordorigin may be comparable to the first 2 values for
We can set the actual size of our image with
height in the
style attribute. This works the same in both formats
SVG has a couple of options for alt text, we can use
<title>alt text</title> inside the
<svg> wrapper. Or we can use
role="img" to define this as an image and
aria-label="alt text" for the alt text.
VML will converted to an
<img> when it’s displayed in Outlook, so we can simply add
alt="alt text" to the wrapper.
The line size and colour are done as a stroke in both SVG and VML. SVG uses
stroke-width VML uses
strokeweight, with VML we need to specify a unit on the
strokeweight so I’ve added
pt however this is not a relative unit so may need adjusting if the shape size is changed.
The colour of the line is set as
stroke in SVG, with VML it’s expanded a little to
SVG starts the line with
y1 to define the start point from the left and top and ends the line with
y2 to define the end point from the left and top.
VML combines the X and Y coordinates, so we set 2 values in
from (X then Y) and 2 values in
to (X then Y).
Can be done with
width attributes or in a
style attribute. Either way it’s a direct conversion from SVG to VML.
SVG uses the
y attributes to position the square from the left and top. For VML we can do this in a style attribute by setting
position: absolute then converting
Square rounded corners
For SVG rounded corners are added with
ry attributes. These can either be numbers or percentage.
For VML we need to change the elements from
<v:roundrect> then add an
arcsize attribute. The value can be a fraction or a percentage e.g
SVG has 2 options
<circle /> or
<ellipse /> element to draw a circle. For VML we just have
SVG has special attributes for setting the size but in VML we set the
<circle /> just sets one value
<ellipse /> has 2
These values all set the size of the radius (measured from the centre point to the edge). For VML we set the full height and width. So we need to multiple it by 2.
rx="90" ×2 =
ry="110.5" ×2 =
SVG has special attributes for setting the position but in VML we set the
style, we also need to add
position: absolute; here.
SVG sets the position using
SVG does positioning from the centre point of the circle, so again we need to do some conversion. Subtract the width from the position and you’ll get the VML position value.
Custom shape element
SVG uses a
path element with the coordinates defined in a
d attribute, and VML uses a
v:shape element with with the coordinates defined in a
Custom shape path
The path is defined with a combination of letters and numbers. The numbers are in pairs and give coordinates
x y and the letters give commands to those.
VML can only use whole numbers so first we need to round these off.
MMove to. This sets the starting point and works the same for both formats.
LLine to. Draws a straight line between the previous set of corordinates given and all the following sets up until a new letter is used. SVG will default to using
Lwhen nothing is defined but VML needs the
Lto be defined. For example after a
Cwhich has 6 values, we need to add
Lto start drawing a line.
HHorazontal line. This is a short cut used with
Lthat keeps the
ycoordinate. This is only in SVG, to convert it to VML you need to look at the value of the previous corordinates. So
100 200 H150would keep the
200value so would become
100 200 150 200.
VVertical line. This is a short cut used with
Lthat keeps the
xcoordinate. This is only in SVG, to convert it to VML you need to look at the value of the previous corordinates. So
100 200 V150would keep the
100value so would become
100 200 100 150.
CCurve. There are 6 values, think of them as 3 pairs of
x y. The first pair control the start of the curve, the second pair control the end of the curve and the third pair set the end point. This is the same for both VML and SVG.
XClose path. This closes the path by drawing a line back to the first “Move to” coordinates. In SVG we use
Zin VML we use
EEnd. This is only for VML and is used to end the path.
There are a number of other commands such as arcs and quadratic curves which I’m not covering yet. The above commands are the most common and should be enough to get you started.
For all the above shapes we can add a fill colour. SVG uses
fill="" VML uses
fillcolor="" so it’s pretty simple to convert. VML only supports setting colour as, 3 digit hex, 6 digit hex, colour names and rgb. So if the SVG is set any other way you will need to convert that.
If you need to set a transparent background with VML, you can use
VML will always add a stroke by default. SVG does not. In the above examples I’ve added
stroked="f" to remove the stroke. However if you want to use it in VML you can either leave that off or set it to
stroked="true" then set the colour with
strokecolor="red" and the thickness with
The most important thing to remember is VML is an image. So try adn treat is as such. This includes not adding text inside the VML and if you do have to add text keep it minamal and add an
I believe Outlook will actually renders the VML as an image and displays it in an
<img> element. So you can see it on the screen but you can’t interact with it and assistive technology will just pick it up as an image. This means any links inside the VML aren’t clickable for any users. But you can add an
href to the outermost element to make the whole object a link.
Outlook does make some attempt to create alt text based on any text inside the VML but it is far from reliable and it will add the element name which can make things confusing. To get around this you can add an
alt attribute to the outer element to pass alt text.
- VML spec
- VML docs
- SVG spec
- SvgPathEditor Can help with rounding numbers, and adjusting for viewbox with 4 values.