Changes in VML for IE8, or "what feature can the IE dev team break for you today?"

The final version of Internet Explorer 8 has been released by Microsoft on the 20th of March. It’s packed with a fully CSS2.1 compliant rendering engine, separate process per tab (just like in Google Chrome, good for stability, bad for memory consumption), performances are claimed to have improve, it introduces new features that will benefit the user such as Accelerators and Web Slices (available in Firefox with the WebChunks addon), as well as interesting features that will benefit the developer, such as a debug tool inspired by Firebug, the onhashchange event and some other interesting things. What as not been included in Internet Explorer 8? The list is unfortunately too long:

  • A Javascript Virtual Machine that could compete with the ones shipped by other browser vendors. The performances of Safari (squirrelfish extreme), Chrome (V8), Firefox (Tracemonkey) and Opera (Carakan) are still far better. But why would Microsoft create a Web browser shaped for the next generation of Web Applications? They are actively promoting their Software As A Service platform and Silverlight, their own Rich Internet Application framework because they can make much more money by forcing developers to adopt their technologies than by making any contribution to the Open Web.
  • <canvas>, <svg> or <video> are missing, and again, this isn’t a big surprise. There is everything you need in Silverlight for vector graphics, audio and video , would the salesman say.
  • Only little support of CSS3. Considering the credit crunch this can actually be seen as an advantage. How would the developers justify their pay if they could use border-radius, border-image, text-shadow and such, straight away, without spending countless hours working around Internet Explorer weaknesses?

Now it’s time to get onto what they managed to break without telling anyone: VML. VML stands for Vector Markup Language, an XML based language aimed at describing vector graphics. It has been submitted to the w3c in 1998 and begins with the following status:

This document is a submission to the World Wide Web Consortium.  It is the initial draft of the specification of VML.  It is intended for review and comment by W3C members and is subject to change.

At the same time, Adobe proposed to the w3c a language with similar purposes: PGML. Eventually, the two standards were merged into what is now SVG… But Microsoft made the choice to ignore this standard and to implement only their original proposition into their browser. Considering the market share of Internet Explorer at that time (around 95%), was there any reason to bother about Web standards? The legacy of this regretted market share is that developers now have to deal with two standards when it comes to vector graphics on the Web, since SVG is the one used in every other browser. Fortunately, there are abstraction layers that allow Web developers to use such features with a lowest common denominator approach such as Dojo.gfx or raphaeljs. But sometime you need to get your hands dirty and to use directly VML for performance or technical reason. This is the case in my border-image script where I’m using only one VML element: image. This was before the first Internet Explorer 8 beta came out…

Although the VML specification hasn’t undergone any improvements or modifications since its publication back in 1998, Microsft development team felt like considerably changing the way their own standard should be handled:

  • The namespace declaration has to take a second argument to be functional:
    document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', "#default#VML");
    instead of simply:
    document.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
  • The selector for the behaviour rules needs to be slightly modified (more information follows).
  • For a standard compliance purpose, when setting dimensions or position of an element, the unit no longer defaults to ‘px’. It has to be explicitly specified
  • It is no longer possible to create a VML element outside of the DOM:
    var myFragment = document.createDocumentFragment();
    myFragment.insertAdjacentHTML('beforeEnd',
    '<v:rect id="myRect" fillcolor="blue" style="top:10px;left:15px;width:50px;height:30px;position:absolute;"></biv:rect>'
    );
    document.body.appendChild(myFragment);

    This rect element will not be displayed! And don’t try to modify its CSS properties with the developer tool, you are likely to crash the tab or even the browser, if you’re lucky. Fortunately, there is an easy fix for this bug: you just have to copy the outerHTML of the element into itself:
    var myRect = document.getElementById('myRect');
    myRect.outerHTML = myRect.outerHTML;
  • It’s no more possible to use % unit! This one is my favourite. The advantage of vector graphics is that they can be scaled without quality loss. Now tell me how you scale a graphic from which all components dimensions and position are set in pixels! You have to resort to using the onpropertychange event to recalculate one after the other those values each time you want to resize your graphic. But there is a lot of case where you simply can’t fix this bug. For example, if you had an rectangle in a div: the div has no dimensions and scales with its content, and you want the height of your rectangle to scale with the div. There was a time when it was possible to simply set the height of the rectangle to 100% (providing the position of the div is relative, of course). But it was probably too easy after all.
  • It’s no more possible to use the getAttribute method to access the values of a particular attribute of your element.
    var myRect = document.getElementById('myRect');
    // Not working in IE8
    myRect.setAttribute('fillcolor', 'green');
    // Still working everywhere
    myRect.fillcolor = 'green';

Remarkably, none of this change has been announced by the IE dev team, as far as I know. The only announcement made about VML can be found on a blog post:

Generic CSS prefix selectors are no longer supported in IE8 Standards Mode in order to provide standards-compliant CSS parsing. Most often, this affects pages trying to use CSS to attach behaviors to VML elements. This can cause a script error if set dynamically, or a silent failure when hard-coded into the CSS of a page. Ultimately the rule is not applied, leading to effects such as VML not displaying on a page.

v:* {
behavior: url(#default#VML);
}

SOLUTION: Explicitly specify each tag name you want to match when using CSS prefix selectors.

v: polyline
v: line {
behavior: url(#default#VML);
}

Can you spot the problem? There is actually nothing wrong with the * selector in CSS from a standard compliance point of view, to prevent the script from crashing if you set it dynamically, you simply have to put a space between the “v:” and the * (you need two backslashes in javascript):

v: * {
behavior: url(#default#VML);
}

I don’t really know what to think about that. On one hand it seems that some of this changes are just bugs (elements are still appearing in the developer tool with correct dimensions and position, they are simply not rendered), on the other hand, if they wanted to finish off VML and force developers to work with Silverlight, they couldn’t do it any better…

Just for fun, take a look at the VML documentation on MSDN, here is what you can still read:

  • About the height property:
    Units: A number with an absolute units designator (cm, mm, in, pt, pc, or px) or a relative units designator (em or ex). If no units are given, pixels (px) is assumed.
    Percentage: Value expressed as a percentage of the parent object’s height.
  • About the last parameter of the namespaces.add method:
    sUrl: Optional. String that specifies the URL of the element behavior to import into the namespace. Specifying this parameter is the same as calling the doImport method.

I learned about this namespace change in an obscure bug report in Microsoft connect. I had to figure out the rest by myself. I’m just afraid that I discovered those bugs too late. Now that Internet Explorer 8 has been made publicly available, there is only few chances for any change to be introduced in the rendering engine…

Update: Following the related post on ajaxian, Christian Effenberger pointed out that the setAttribute no longer work. I also want to state that the most obvious and easy way to fix all those bugs at once is to use the IE7 meta-tag:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

IE7 is still the most common Web browser according to its market shares, so you have to make your website compatible with it (still painful, but nothing compared to its predecessor). Once your website is compatible with IE7, add this meta-tag and you will have compatibility with IE8 for the same price, with good ol’ VML implementation. Disclaimer: I do not recommand browser sniffing or browser hacks and should not be held responsible for bad use of the previous advice, period.

Update2: Changed the IE7 meta-tag and the link to the announcement on the IEBlog, thanks to dflock.

12 thoughts on “Changes in VML for IE8, or "what feature can the IE dev team break for you today?"

  1. Pingback: Ajaxian » The VML changes in IE 8

  2. Pingback: The VML changes in IE 8

  3. Jeff Schiller

    Wow – I’m just floored. Great investigative work but this is really REALLY disappointing news (particularly that the IE team doesn’t feel the need to blog about this).

  4. Brad Neuberg

    Very sad. VML is used in a large number of web sites that reach alot of folks, including the new Google Docs drawing tool. It’s the only way currently to do vector graphics in IE….

  5. Pingback: Agile Ajax » IE8: That Sinking Feeling » Pathfinder Development

  6. dflock

    If anyone else gets bitten by this, the solution at the bottom of the post is mostly right – to kick IE8 into IE7 mode, but the code is wrong.
    This is the code that you need:

    <meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″/>

    This needs to go into the <head> section, before any other tags, except other meta tags.

  7. Sam Jacobson

    It’s working OK for me. Granted we only use a subset of VML, and there was a bit of messing around, but it’s not *all* doom and gloom. We have a custom solution for simple vector graphics (over a map). It’s purely javascript.

    The changes required to our custom VML/Canvas layer:

    - style.addRule('v\:*', 'behavior: url(#default#VML);');
    + style.addRule('v\:polyline', 'behavior: url(#default#VML);');
    + style.addRule('v\:fill', 'behavior: url(#default#VML);');
    + style.addRule('v\:stroke', 'behavior: url(#default#VML);');
    // we only use those 3 elements


    The setAttribute stuff *does* work, just not after the element has been added to the document. That fit in moderately well with what we were doing already, but I had to make a small change there (we were setting a couple of attributes after adding the element which stopped working with no error in IE8).

    I *didn’t* change “document.namespaces.add(‘v’, ‘urn:schemas-microsoft-com:vml’);”. It seems fine in IE8 (and the extra parameter seemed to break IE7).

    With those few changes our relatively small solution seems to be working fine in IE8 Standards mode (and still working in IE7). I think it’s like everything IE. You can do anything at all so long as you have a spare day to spend on it (although admittedly with the help of this page it was closer to a couple of hours).

    Thanks for the info here, it was much appreciated.

  8. Victor Campos

    Well, this post was very clarifying, but I’m still having some issues drawing with the v:shape, I got it to show up in the DOM representation, but still there’s no damn element displayed, no stroked line, nothing, anyone having the same problem?

    And thanks again for the post!

  9. Justin Wilson

    Thanks for this greatly detailed post… I was just stuck on getting a SVG/VML control working in all browsers my company supports (IE6-8, FF, Safari). I needed to make a control work where you could select different regions of a vector image and change it’s, and all matching shapes, color.

    Firefox and Safari, like usual, was a breeze.

    I initially got it working in IE7.. Then with a little bit of work IE6.
    I made the assumption that IE8 should be easier than it’s predecessors since it’s suppose to be more ‘standards compliant’. Boy, it was a PAIN.

    Yes the getAttribute/setAttribute didn’t work as expected. But I didn’t notice it kind of worked, in the same horrible kind of way that MS does everything with IE. If my VML element had more than one attribute it would only report the element as having a single attribute, the first one. So if all I needed to do was update/get the first element then I would be fine. It just so happened that the ‘fillcolor’ was not the first element. Ugggh

    I wish MS would just give up and use Gecko/Webkit and just focus on the GUI, like what Google has done with Chrome.

  10. Justin Wilson

    Victor, Make sure you’ve set dimensions. I too initially ran across this issue. I set dimensions (px) for my ‘s and the VML container. Once I did this the VML would show.

  11. Pingback: lrbabe » Blog Archive » The state of cross-browser vector graphics

Comments are closed.