SVG to VML converter

A Lange watch face and strap drawn as SVG outlines, black on white..

Converting a watch was the SVG to VML test we were building up to

 

Lange watch

While I was doing some printing of an SVG watch Graeme had drawn, we thought it would be fun to see it render in Outlook. This lead to us working on an SVG to VML converter. Below is some of the process, and a look at VML layout and support. Mostly cropped screenshots of VML tests from my Outlook 2010 email client. VML was deprecated ~ 2011, and looks the same in all versions up to 2019. Click on images for full-size, or email yourself a test below.

 

Resources

 

What is VML

VML is a 2D vector format supported in desktop Outlook, which uses Microsoft’ Word renderer. Although deprecated, it’s still all there, in the background. Email designers use VML to fill support gaps, most often with background images thanks to Stig Morten. Given the lack of VML authoring tools, if you want more than a button you’d have to hand code it, which Mark Robbins wrote about. So we decided to write an SVG to VML converter to display vectors in Outlook, and explore VML’s capabilities. SVG evolved out of a few 2D vector graphic formats that were around ( ~ 1998 ), one of which was VML ( Vector Markup Language ). So SVG is partly derived from VML, but not identical. There’s not a VML equivalent to everything SVG, but there’s enough overlap for our purposes. We're trying to make use of the, ‘whole lot of commonality’ between the specs.

 

SVG to VML converter

The core task is to convert all the SVG elements to VML

The core task is to convert all the basic SVG elements to VML

 

We need to convert all the basic SVG elements into VML. Top row are predefined shapes, these are built in shapes like circle or rectangle. Middle row are custom paths, constructed from the sub-elements: cubic and quadratic bezier curves, lines and elliptical arcs. Bottom row are image and text elements. Each of these basic elements needs its own converter, which you then combine into one. Early on we had two converters, one which keeps predefined elements as they were. e.g. an SVG circle to a VML circle. Another which converts all SVG shapes into VML paths e.g. an SVG circle into a VML path that’s a circle. It’s semantics, as you can create all the predefined shapes from paths. But for compatibility reasons such as transforms, we went with converting all basic SVG shapes into VML paths.

 

Custom paths

 

Early failed VML path test with a mess of lines all over the place

Early failed VML test, looks like an Etch a sketch.

 

A quadratic bezier curve, looks like the letter S on its side

Quadratic bezier curves a sub-element of paths

 

Chained quadratic bezier curves

Chained quadratic bezier curves

 

More chained quadratic bezier curves, bunch of curvy lines intersected like a sound wave

More bezier'

 

Number of elliptical arc in different colors drawn on top of each other, some are working, some aren't.

Different ways to define an elliptical arc ( sub-element of paths ), some are working, some aren't.

 

The words, A. Lange & Söhne (name of a fancy watch maker) in a curve shape in white against gold background.

Getting somewhere, lettering from a watch drawn in Illustrator.

 

StyleCampaign in white against black, in a flourishy, blackletter typeface,

Complex path with lots of flourishes, at this point we were testing single paths only.

 

SVG polygons to VML

3D Polygon red torus on a red background.

SVG polygons to VML, this torus was generated using our 3D to SVG tool.

 

Grey 3D monster with knife for an arm, in the middle of a walk cycle.

More 3D .obj to SVG polygons to VML

 

A 3D camera mount in grey, with some transparency.

Another SVG polygon to VML test, this time with some transparency.

 

Multiple SVG elements to VML

A. Lange & Söhne watch face with the strap, in white against a black background. Looks like a complex vector.

This was the test we were building up to, it contains multiple paths, polygons, circles, lines etc.

 

All the rest of the SVG

You can paste just an SVG path into the converter, and get a VML path back, but SVG files are often more complicated. Many contain multiple paths, not just the one. They’re given a color, placed into groups, and transformed into place. There’s a bunch of assembly instructions if you like. Where possible, we wanted to convert a whole SVG file to VML, from the opening to the closing tag.

Trying to make it more than a path converter opens a can of worms. SVG and VML each have features the other doesn’t, or only partial support for some stuff. But it's still worth trying to automate some basic features, in order to make it more practical. We’re trying to convert what we can, and ignore the rest. In many cases it converts just fine, but you’ll run into issues at some point. You can work around them by editing the SVG or VML, but you have to be comfortable doing that.

 

Converter support v1.

We can’t convert everything SVG to VML, as there isn’t always an equivalent. But to make the converter more practical, we’ve added support for these features.

 

Predefined shapes
  • Circle
  • Ellipse
  • Rectangle
  • Polygon
  • Polyline
  • Line
Paths
  • Cubic bezier curve
  • Quadratic bezier curve
  • Line
  • Elliptical arc

 

Text
  • Textbox
  • Transforms
  • Textpath

 

Image
  • Transforms

 

Attributes
  • Color
  • Fill color
  • Stroke color
  • Stroke weight
  • Transparency
  • Coordsize

 

Transforms
  • Absolute & relative space
  • Fill color
  • Translate
  • Rotate
  • Scale
  • Skew
  • Matrix

 

File structure
  • Absolute & relative space
  • Groups
  • Sub-groups
  • Styles
  • Inline
  • Alt text
  • Comments

 

 

We can add more support but it gets a bit gnarly from here. Some SVG features only have a partial VML equivalent, or no semantic equivalent. There’s also features in the VML spec which aren’t supported in Outlook. We tried to cover the basics, and this feels like a sensible place to stop. A lot of work going forward isn't adding extra features so much as making it more robust.

 

Stress testing

 

16 different email marketing logos, in a 4x4 grid. Large group of logos all rendered correctly in Outlook using VML

Stress testing Dylan Smith’s collection of email marketing logos

 

File size comparison

With the ( above ) collection of email logo's, all but the Klaviyo logo converted in one pass, as it needed a gradient which we applied after. This test allowed us to catch optimized SVG code. This is where characters or white space get removed to reduce file size. We’ve put some precautions in for minified code, but skip it if you can. I also compared the SVG and VML file-sizes of all the logos (see slide 16 in the deck for more detail ), and they looked to be roughly the same.

 

An illustration of a gameboy (handheld device for playing games) in yellow against a dark pink background. Has some text underneath biggest just says Illustrations, website it was from.

We picked up on getting the stroke weight and opacity right here, the text is also SVG. ( source )

 

Cartoon Banana with a smile on its face, word Banana underneath in the typeface GT Maru, by Grilli Type

Stress testing GT Maru SVG, by Grilli Type, we had to fix rotating elliptical arcs ( part of transforms ).

 

Miilkiina in blackletter style, black against dark gray

Miilkiina’ logo gave us no problems, adds a lot of personality for 5kb.

 

Row of six social media icons, black against purple

Don’t think we had any issues with these

 

 

VML layout

We spent a bit of time looking at VML' layout capabilities. Like SVG, VML uses a coordinate system for layout so it's very unrestricted. It's like divs on steroids, you can put stuff anywhere. We can recreate our HTML layouts in VML, and extra stuff besides. There’s also some limited responsive design capabilities, such as stacking and making your VML assets fluid. Weird stuff, like you can place an HTML module inside a VML textbox and stick it anywhere. This is an area we need to dig into more.

 

A responsive SVG slider with three tabs on a tablet, and looking different on a mobile

Interactive SVG slider using SMIL, this whole section is an SVG.

 

In 2018, we made a responsive SVG slider that combined live text, raster and vector images. I realized SVG wasn’t just for displaying vectors, but was a whole alternative layout engine. So when we started playing with VML our minds went straight to layout. It's not that I expect people to start designing entire emails with VML, but you could. So its hard to ignore, even if its not likely to make it into production. There are more feasible images-off enhancements you can make, such as logos, VML image placeholders and custom type headings etc.

 

The words StyleCampaign in pink, big yellow polygon torus in front, a 3D game character drinking and a pink pig in front

Outlook has a max-with of 2112px

 

Black of text in back, social icons in middle and Stylecampaign in front. Shows how all the elements are layered up on the z-axis front to back.

Here we were playing around with z-order ( layer order ).

 

The z-order (front to back) of the three layers has shifted, the block of text is now in the center. show how you can shift layers around.

We’ve shuffled it around so the text block is in the middle.

 

A collage of vectors, text and raster images (blocked), overlapping each other to show that we can put elements anywhere using VML for layout

I know it’s a mess but you get the idea, no tables and boxy layouts, images-off

 

A collage of vectors, text and raster images (downloaded), overlapping each other to show that we can put elements anywhere using VML for layout

Images-on, the two images are using VML chromakey.

 

VML textpath

We’ve added support for VML textbox, and textpath. SVG text doesn’t have a container and VML does, so you have to give it one during the conversion. The text within VML textbox can be selected and copied. It can render in other email clients unless you tell it otherwise. Other clients ignore the VML container setting it’s width and position, but will still read its contents. Textpath can’t be selected, it's type as image or decorative, text on a path also doesn't appear to be affected by darkmode.

 

A paragraph of text that uses textbox, with text on top drawn in a circle using textpath

VML textbox and textpath

 

Three diagonal lines with three lines of text spreading out from its direction. Centered, Left-justified and right-justified examples.

Multiple lines of rotated VML text on a path

 

VML textbox doesn’t rotate, so you have to put your text on a path and rotate that ( line above visible for reference ). A paragraph of text spreads out around the path depending on line breaks and line height. Were also testing alignment here.

 

Three lines of pink text drawn around a circle, in different alignments

Circle path, you can also set the text to fit the shape, which would close the circle.

 

Three lines of blue text following a wavy line

Same as above just with more of a custom shaped path

 

VML textbox

Two paragraphs of text side-by-side drawn using VML textbox

These two VML textboxes stack into a single column if the client window is narrowed.

 

The right side paragraph of text, has been replaced by an HTML email module

You can put a whole HTML module within a VML textbox ( right ).

 

The HTML email module is now on top of the text on the left

As it’s now a VML container you can place it anywhere.

 

The HTML email module has a button that's linked up, I'm rolling my mouse over it and you can see the url

Individual elements can be linked up, VML textbox can be selected and copied.

 

Raster images

SVG filters don’t have an equivalent in VML, but VML does have some image effects. Below we’ve adjusted the gain and gamma, to make it match the dark background.

“Bitmaps are an essential part of VML. Raster and vector data may be intermingled. Raster data may be combined with vector data by clipping the raster to a vector path. Limited transformations (chromakey, gamma, picture and black level adjustments) may be applied to raster data.” ( source )

 

Photo of the tide out on a beach, on a black background. Stylecampaign overlaid, and a paragraph of text using textbox to the left. Image has an effect applied to it and the text is clearly a custom font so its a vector.

VML image with effects applied, textbox and custom type

 

Fluid VML

VML text can reflow ( see paragraph above and below ), SVG text can’t and scales like an image if you try. You can probably get the textbox to be fluid, as well as other VML assets like vectors and images. We did have a fluid test working at one point with one of the Santa models, but just on the horizontal axis. Its width would squash, but not its height. Based on that I think fluid VML is likely doable, it’s one of those things we need to get back to. That along with being able to stack content, gives you some basic responsive design capabilities.

 

Photo of the tide out on a beach, words Stylecampaign overlaid in a custom font so a vector, the paragraph of text has got narrower than the same test above as VML text can wrap unlike SVG

VML textbox can reflow ( see paragraph left )

 

Stacking VML groups

Somewhere along the way we realized that VML groups can behave like block elements, they stack as the email client window is resized ( only if you want them too ). Here we go from a four column ( four VML groups ) to two on the image below. We could also go 4,3,2,1 if we wanted.

 

Four watches in a row. Black outlines against white background (same fancy Lange watches as before, each is a slightly different model)

Stacking VML groups 4 – 2

 

Our four Lange watches in a row, have now stacked into 2x2,

Narrow the email client window the columns center, and stack 2 × 2.

 

Two Lange watches this time on a row, white outlines against black

Stacking 2 – 1, we can control stacking by how elements are grouped.

 

Two Lange watches this time, stacked down into one column and centered

Dropped to one column and centered.

 

Three groups of VML assets, two pigs side-by-side and some social icons centered underneath

Here we have three VML groups that stack as the window narrows.

 

The two pigs have stacked into one column

Now one column and centered.

 

Further down, we can see that the social icons are also stacked under the pigs into a single column and centered.

Social icons down the bottom still.

 

Alt text

When working with VML groups, we’ve added an 'alt text all grouped elements' checkbox to the converter. If present it’s generated from group id names ( which you can edit in order to improve your alt text if needed ), otherwise it’s left blank, alt="". We made this optional as you might only require one alt text to describe multiple groups. If I just need one description, I add it by hand on the first line:

/* Adding alt text to VML by hand with one description */

<v:group id="catlayer" alt="Black yawning cat sitting in the sun" coordsize="600,480"

style="position:static;top:0;left:-300;width:600;height:480">

 

Extrude

A row of five Xmas cartoon-y vectors in different colors, each with a shadow generated by VML extrude

Adding shadows with VML extrude, a VML only feature.

 

The Row of 5 cartoon Xmas vectors now look like 3d plastic toys, as they have been extruded (stretched out from 2d to 3d-ish, its 10pm hope my descriptions aren't too sloppy)

The original flat artwork has been extruded, and looks like a plastic toy.

 

Known issues

These are some of the main features that might give you trouble, or just aren’t supported in Outlook. You can edit your SVG or VML to workaround them.

Thing / issue
  • Defs / Partial VML support
  • Clip-path / No semantic equivalent
  • SVG filters / No semantic equivalent
  • Gradients / Messy haven’t done them
  • Animation / No Outlook support
  • iFrame / No Outlook support
  • Mouse events / No Outlook support
  • Avoid if possible / Minified code

 

Defs partial support

Using shapetype 30 pigs is only 13 kb, a bit of overhead from 5 kb but not 150 kb. VML shapetype allows you to define a single path, and then make instances of it. All these instances reference the same pig data, you can also change things like the color or scale etc. of each pig. Its base outline remains the same, what you do with it afterwards is up to you. SVG supports this feature but with a group of paths, VML only supports one path. So we’ve left defs ( shapetype in VML ) out of the converter, because partial support is messy. Though this doesn’t stop anyone from using shapetype as it’s supported in Outlook.

 

Sad pink pig all on its own in a sea of pink.

Testing defs, or Shapetype in VML.

One pig path is ~5 kb, if we wanted 30 of them you’d expect 150 kb.

 

Now there's 30 pig pinks through the magic of shapetype, though you can only see 20 in this crop

30 pig instances ( 20 seen above ), 13 kb not 150 kb

 

Litmus’ logo

Litmus' logo is made up of ten identical shapes, we’ve drawn a path for one and defined it as a shapetype. Made 10 instances of it, rotated, and given them a different color. This reduces the file size from 4 KB to 2 KB. In SVG these are called 'Defs' or instances, and can be applied to groups of paths. In VML it can only apply to one path. As there’s only partial support it’s not in the converter, but you can apply it by hand.

 

Litmus circular logo made up of ten identical shapes like an orange, in different colors. As they are identical shapes they are ideally suited for some shapetype optimizations

Litmus logo 4 kb down to 2 kb using VML shapetype

 

Clip-path

A clip-path in SVG is a layer that clips everything behind it, and there’s no direct semantic equivalent to SVG clip-path in VML. This test is a VML shape element that has a background image, that is clipped by the path. It will have no effect on anything else within the composition. Instead of filling the shape with a color, we’re filling it with an image. Here we’re faking a 3D transform, the image within the shape has been edited to appear skewed, and then clipped by the path.

 

A skewed image with a photo inside of a sandy dune-y beach (its Scotland)

VML image test faking a 3D transform

 

Gradients

The converter doesn’t support gradients in v1, it will output the paths in a default solid color. You can then apply a gradient by hand, as we did with the Klaviyo logo above. This article on CSS background gradients written by Cosmin Popovici, has a section on VML gradients and you can view the gradient fill Microsoft doc.

 

Klaviyo logo in a solid black color left, and with its green/yellow gradient added in afterwards right

Klaviyo logo solid and with VML gradient applied by hand

 

Interaction

All the interaction tests we’ve run have been blocked by Outlook, not completely ruling it out but the obvious stuff hasn’t worked.

Mouse events

This is a hard one to show in static screenshots, we’re testing mouseover interaction in VML. When you rollover parts of the watch face, either the hands rotate or change color ( from white to blue ). This is it working when viewed in IE as an .mht file ( see below ), so we know our code is right, Outlook just ignores it.

 

Back to the Lange wactches, in IE this time doing nothing

Rollover interaction working in IE not Outlook

 

The watch hands have turned blue and one has moved as I added some rollover stuff in, (rollover this and do that) it works in IE but not Outlook

What should happen in Outlook but only works in IE.

 

VML handles

Here we we’re testing VML handles, there’s no SVG equivalent, we were just curious if it worked. What should happen is you can edit your VML, by dragging the yellow nodes to alter the shape of the path. Below I altered the shape of the arrow far left. VML handles get blocked by Outlook, there's no support. Not sure what I would’ve done with this had it worked, just interested to see if it was still in there.

 

3D santa with a bunch of arrows drawn on top of him in Outlook

Testing VML handles ( no Outlook support ).

 

Same 3D santa test as above, this time within Word the arrow has handles and they work

Same test working within Word

 

Remote loading

Here we're testing VML iframe, which allows you to load VML content externally. It would also enable support for dynamic VML content, such as personalized charts etc. Unfortunately while this worked for us in IE ( below ), it came in blank in Outlook. Unsurprisingly they've blocked it.

 

Bit sad looking demo, just an arrow against grey in IE, but its being remotely loaded in which would have been great if it had worked in Outllok (it doesn't)

VML iFrame working in IE ( remote loading ), blank in Outlook. Would have meant support for dynamic content.

 

MHT converter

A useful tool in all this was a VML / HTML to MHT converter, we wrote for previewing VML in IE. IE doesn’t support VML anymore ( no browser does ), but you can trick it by converting your VML to MHT. There’s a ‘Click here to view in a web browser’ message that comes up in Outlook sometimes. When you click it, it displays the email including the VML in IE, from there we realized what was going on. It was particularly useful with a few of these tests that use interaction etc. While Word and IE are reliable proxies, some things work in Word / IE but not Outlook. Though generally speaking we found IE was a better proxy than Word, but we still used Word often for quick previews.

 

VML rendering

VML is supported in all desktop Outlook email clients, it’s currently at 9 % marketshare ( 4th ) as of May 2021. You can target only the email clients that support VML, or use MSO to drill down further. Combined vector support in email is ~ 74 %, this includes both VML and SVG. We're testing on Outlook 2010 and Windows 10 Mail on a PC, which is where all these cropped screenshots are from. We used Litmus to preview versions of Outlook we don't have. From our testing VML renders the same across all desktop Outlook email clients up to 2019.

 

11 screenshots from Litmus, showing different versions of Outlook rendering the camera mount, they all look identical except one is dark mode

VML support in Outlook ( Litmus )

 

Bunch of Litmus screenshots of all the clients that support VML, showing the collection of email logos and they all look identical

Email marketing logo’ preview ( Litmus )

 

Bunch of Litmus screenshots of all the clients that support VML, showing the gameboy and they all look identical

Gameboy preview ( Litmus )

 

The shapetype pigs all looking identical in Litmus in multiple Outlook clients

VML shapetype support ( Litmus )

 

More Litmus previews with the rendering looking solid, this type the word StyleCampaign in black-letter

Stylecampaign lettering preview ( Litmus )

 

Win 10 Mail split

I did notice a slight rendering split between Windows 10 Mail and all the Outlooks. Mainly Win 10 doesn’t support textpath, Outlook does. Interestingly textpath doesn’t render in Word either. Beyond that vectors render the same, but I will test further.

 

Left shows how textpath isn't supported in Win 10 Mail, circle path with no text on it. While right shows same test rendering fine in Outlook, with text drawn in a circle.

The split with Win 10, it doesn’t support textpath ( left ), Outlooks do ( right ).

 

The Lange watch rendering fine in Win 10 Mail, while it differs slightly it renders vectors fine.

Windows 10 Mail using a slightly different Word-based renderer than Outlooks', it's solid at drawing vectors.

 

Darkmode

VML in Outlook Office 365, and Win 10 Mail dark mode below. I believe both do their own automatic dark mode switching ( just the background color here by the looks of it ). You can manually opt into Windows 10 Mail dark mode: ( settings / personalization / dark mode ). Colors are automatically inverted, though as you see below just the background is changed, the vector shapes aren’t affected. These tests weren’t designed for dark mode, but you can still get an idea of how VML is handled.

 

Showing the pigs rendered in Win 10 Mail dark mode. They have stayed the same color but the background ha switched from pink to dark brown

Windows 10 Mail has a dark mode you manually opt into, it automatically inverts colors.

 

The pigs rendered in Outlook 365 dark mode, looks to be the same as Win 10 Mail above

Outlook Office 365 also has a dark mode ( screenshots from Litmus )

 

Since I published this Nicole Merlin did an in-depth write up on fixing Outlook Office 365 dark mode issues, so I’m slipping it in. The gist of it is it’s VML textbox you need to look out for, she has some cool hacks for making sure your text stays legible. VML textpath ( e.g. text on a circle ), seems to be ignored by dark mode based on what I’ve seen.

 

The pigs rendered in Litmus, all looking the same. You get the idea, if it works in one Outlook it works in them all the same

Pig textpath preview in Outlook Office 365 ( Litmus )

 

Vector support

For the ~ 74 % support mentioned above, I ran some SVG / VML tests in Litmus early 2021. I'm getting my stats from Emailclientmarketshare:

 

 

VML support

  • Outlook 2007
  • Outlook 2010
  • Outlook 2013
  • Outlook 2016
  • Outlook 2019
  • Outlook Office 365
  • Windows 10 Mail

= 9 % ( May 2021, * down to 6 % Sep )

Inline SVG support

  • Apple Mail 13 & 14
  • OL Office 365 Mac
  • Outlook 2016 Mac
  • Samsung Mail 6 & 7
  • iOS
  • T-Online.de

= 59 %

External SVG support

  • Windows 10 Mail
  • Android 6
  • Android 7 Outlook app
  • Samsung Mail 6 & 7
  • AOL Mail
  • Comcast
  • GMX.de
  • Office 365 (web client)
  • Outlook.com
  • Web.de
  • Yahoo Mail!
  • Freenet.de

= 9 % ( iOS & Mac have dropped external SVG support ).

 

SVG support using both techniques ~ 65 % + 9 % for VML = ~ 74 % for vectors in email.

Inline SVG & VML = 59 % + 9 % = ~ 68 % for vectors in email.

External SVG & VML = 9 % + 9 % = ~18% for vectors in email.

You can use VML on its own, I was just interested to see where we are overall.

Also see caniemail.com for SVG support.

 

End on a nice big mustard yellow 3D torus

Thanks! - Anna

 

VML Resources