MHTML - when you need data: URIs in IE7 and under

In the previous post I described what data: URIs are and how they are useful to reduce the number of HTTP requests. Now, the problem with data: URIs is that they are not supported by IE < 8. But, thanks to this article (in Russian), here's a way to work around that limitation: using MHTML for IE7 and under.

MHTML-a-what?

MHTML is MIME HTML, or if you insist on me spelling it out completely is like "Multipurpose Internet Mail Extensions HyperText Markup Language". In short it's HTML but like email with attachments. In one "multipart" email you can have several... hm, things - HTML version of the email, text-only version, attachment, another attachment...

MHTML is the same but for HTML. In one file you put a bunch of stuff (e.g. image files) and you save on the precious HTTP requests.

MHTML example

Let's check out an example. The HTML is actually not important, it's the CSS where we'll stick all our inline images. Once with data: sheme for all normal browsers and once with the mhtml: scheme for IE before 8.

The overall "template" would look like so:

/*
Content-Type: multipart/related; boundary="_ANY_SEPARATOR"

--_ANY_SEPARATOR
Content-Location:somestring
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAA[...snip...]SuQmCC
*/

#myid {
  /* normal browsers */
  background-image: url("data:image/png;base64,iVBORw0[...snip...]");
  /* IE < 8 targeted with the star hack */
  *background-image: url(mhtml:http://phpied.com/mhtml.css!somestring);
}

The multipart stuff goes into a CSS comment. You then use data: URI scheme for all normal browsers. Then you use the star hack to target IE browsers before 8. For these browsers you give the URL of the CSS, exclamation and then a string that uniquely identifies the desired "part" in the multipart comment. Simple, eh? Didn't think so, but hey, it's not exactly rocket science.

Demo example with more parts

Check out a demo page that has two "parts" in the multipart MHTML comment.

The HTML is noting special and the CSS goes like:

/*
Content-Type: multipart/related; boundary="_ANY_STRING_WILL_DO_AS_A_SEPARATOR"

--_ANY_STRING_WILL_DO_AS_A_SEPARATOR
Content-Location:locoloco
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC
--_ANY_STRING_WILL_DO_AS_A_SEPARATOR
Content-Location:polloloco
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAABkAAAAUBAMAAACKWYuOAAAAMFBMVEX///92dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYvD4PNAAAAD3RSTlMAACTkfhvbh3iEewTtxBIFliR3AAAAUklEQVQY02NgIBMwijgKCgrAef5fkHnz/y9E4kn+/4XEE6z/34jEE///A4knev7zAwQv7L8RQk40/7MiggeUQpjJff+zIpINykbIbhFSROIRDQAWUhW2oXLWAQAAAABJRU5ErkJggg==
*/

#test1 {
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC"); /* normal */
  *background-image: url(mhtml:http://phpied.com/files/mhtml/mhtml.css!locoloco); /* IE < 8 */
}

#test2 {
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUBAMAAACKWYuOAAAAMFBMVEX///92dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYvD4PNAAAAD3RSTlMAACTkfhvbh3iEewTtxBIFliR3AAAAUklEQVQY02NgIBMwijgKCgrAef5fkHnz/y9E4kn+/4XEE6z/34jEE///A4knev7zAwQv7L8RQk40/7MiggeUQpjJff+zIpINykbIbhFSROIRDQAWUhW2oXLWAQAAAABJRU5ErkJggg=="); /* normal */
  *background-image: url(mhtml:http://phpied.com/files/mhtml/mhtml.css!polloloco); /* IE < 8 */
}

div {
  width: 100px;
  height: 100px;
  font: bold 24px Arial;
}

Drawback

In addition to the drawbacks of data: URIs (bigger CSS, small CSS change invalidates your cached inline images), this method has the obvious drawback that the inline images are repeated twice. But sometimes... a person's gotta do what a person's gotta do ;)

This entry was posted on Friday, April 10th, 2009 and is filed under CSS, ie, images, performance. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


Get notification for future posts: follow me on Twitter or subscribe to my RSS feed

Somewhat related posts

46 Responses to “MHTML - when you need data: URIs in IE7 and under”

  1. MHTML - when you need data: URIs in IE7 and under | Dailytuts.net - Daily tutorial for peoples Says:

    [...] Continued here: MHTML - when you need data: URIs in IE7 and under [...]

  2. Konstantin Says:

    Interesting article! Unfortunately, this doesn’t work for me in both IE6 and IE7 (on Windows XP). The divs just have a blank background. There are no special security settings for the browsers (it’s a stock Windows XP install, with nothing more than IE). I don’t really know what further information I can supply that would be helpful for debugging.

  3. Konstantin Says:

    For some reason, I can’t save other webpages as .mht either. Maybe my installation is broken, but I actually don’t know what could have broken it.

  4. Konstantin Says:

    It worked in another VM in IE6. I don’t quite know why it’s broken in the other VM (as I said, it’s a straight-from-disc Windows XP installation with no further modifications).

  5. Stoyan Says:

    Thanks for the comment/report, Konstantin. I tested with an XP VM (on a Mac) and it worked for me, dunno what can be happening with your install, but please drop a comment if you figure it out.

    Thanks again,
    Stoyan

  6. Windmill Electricity: Cheap Power Alternative | DIY Home Power Says:

    [...] MHTML - when we need data: URIs in IE7 as well as under [...]

  7. Hedger Says:

    Great post! Thanks for sharing.
    Did you test it on IE7 on Vista?
    I’ve found this http://www.eggheadcafe.com/software/aspnet/33808138/mhtml-doesnt-work-in-vis.aspx
    Thanks.

  8. Stoyan Says:

    Hey Hedger, nope, only XP virtual machine.

  9. Ideas at random ... Says:

    Tested this technique out on Windows Vista with IE7 and the background images are not viewable.

  10. anthony Says:

    But now isn’t your CSS file is getting the image twice, once in the comments for IE<8 and then once again for everyone else?

  11. Wat is de beste manier om de registratie bedorven dossiers te herstellen schoon te maken en? | Windows Xp Registry Repair Says:

    [...] MHTML - when you need data: URIs in IE7 and under / phpied.com [...]

  12. Stoyan Says:

    @anthony - yep, that’s a drawback. One solution would be to include browser-specific stylesheets.

  13. Hedger Says:

    Though IE7 is the default browser on Vista, I’d assume that the MHTML issue would apply to all IEs on Vista.
    To make MHTML work on IE with Vista, all we need is to do two things.

    * Output the MHTML document with the content-type “text/plain”.
    There are a lot test examples on http://people.dsv.su.se/~jpalme/ietf/mhtml-test/mhtml.html
    You may try this one http://people.dsv.su.se/~jpalme/ietf/mhtml-test/mhtml-1.txt for example.

    * Redirect do that MHTML file to its hosted URI which “mhtml:” as prefix.
    eg: mhtml:http://people.dsv.su.se/~jpalme/ietf/mhtml-test/mhtml-1.txt

    This would work on IE7/Vista http://www.hedgerwow.com/360/dhtml/base64-image/demo.php?v=2009

    Thanks.

  14. Bernie Says:

    There is a solution where you don’t have to put both images (IE + others) into one file.

    It’s not a must to put the image-data for the mhtml source into the same css file. It’s possible to reference to an other file, that can have any file extension, so it’s possible to put the mhtml data into an own txt file, wich is delivered as text/plain by the webserver, so it’s also working in IE7 Vista.

    Take a look at: http://www.betalon.com/html/release.htm

    I’ve tested this with: IE 6 (XP), IE 7 (XP), IE 7 (Vista), FF 3 (XP), Safari (XP)

    The CSS file is: http://www.betalon.com/static/release/css/screen.css
    The MHTML contents are in this file: http://www.betalon.com/static/release/css/screen.iecss!imagk

    So in the browsers which support data-urls the image contents will be loaded only once.

    Don’t be afraid to contact me if there is any problem with this solution.

  15. Renewable Energy With Windmills | DIY Home Power Says:

    [...] MHTML - when we need data: URIs in IE7 as well as under [...]

  16. Links XLV • Peter Kröner, Webdesigner & Frontendentwickler Says:

    [...] Explorer: Data-URIs in IE7 and under – Der IE8 kann es von Haus aus und mit diesem Trick auf die älteren [...]

  17. MHTML - when you need data: URIs in bIE7/b and under / phpied.com « Windows 7 Live Info Says:

    [...] Stoyan wrote an interesting post today onMHTML - when you need data: URIs in bIE7/b and under / phpied.comHere’s a quick excerptUnfortunately, this doesn’t work for me in both IE6 and bIE7/b (on bWindows/b XP). The divs just have a blank background. There are no special security settings for the browsers (it’s a stock bWindows/b XP install, with nothing more than IE). … [...]

  18. Schepp Says:

    Sorry, Stoyan - please delete the above. My mind was still switched to German mode…

    What I wanted to say: very nice tipp!

    I made use of this technique on one of my customers’ site, where the customer always complained that the loading times of the image gallery pages took so long. Which is no wonder, as they consist of up to 130 thumbs that induce a lot of HTTP-overhead. In addition he used to visit his page with IE7/8, which made it even worse (Google Chrome dealt quite OK with it for example).

    So now I do a serverside check for the user agent, and serve the right technology for the respective browsers: The IEs get all thumbs stuck together in an external MHTML-file (which is nice, as it makes it browser-cacheable), Webkit and Firefox get the thumbs embedded as Data URIs. All other browsers take the traditional route, with a little tweaking in that I load the images from 3 different subdomain (all pointing to the same folder) and therefore get around the HTTP-1.1-limitation of only 2 connects per host in parallel (now up to 6 in parallel).

    The MHTML and HTML-files are being GZIP-compressed which saves about 50% of the image-data load. THE MHTML-file also gets browser-cached through the help of mod_expires. And all the base64-transcoded data gets cached on the server-side in order to save CPU-cycles and time.

    Here is the page in question:
    http://www.sky-fun.de/fallschirmspringen-fotos-bilder.php

    Thank you very much again for your blog and regards from Germany!

    Schepp

  19. Stuart Says:

    This article (and the accompany data: URI one) saved me! Thanks for your efforts.

    A tip for other readers: the format of the MHTML template is important. In my experience, the boundary declaration needs double-quotes (not single-quotes), and the blank lines after Content-Type and before data string must be present.

    Thanks!
    Stuart

  20. Ridurre le richieste HTTP con Mime HTML e data:URL » jblog: news e appunti per webmaster Says:

    [...] Phpied.com - MHTML - when you need data: URIs in IE7 and under [...]

  21. Gavin Doughtie Says:

    Has anybody written a canvas API for this yet?

  22. gingerbbm » Blog Archive » HTML images using long GET strings Says:

    [...] same trick is used to for CSS and to reduce HTTP requests. And by reading that post I learned that we have to do it another way in IE. In IE we have to use MHTML and it involves a little more work on the server but we can still end [...]

  23. Caren Says:

    Thanks for the great post here!
    I was trying to produce the same result by putting the CSS and mhtml stuff in the tag in the html file. However, it didn’t work. Have you ever tried this? Thanks!

  24. Stoyan Says:

    Which tag, Caren? Seems like the tag was stripped from your comment

  25. Caren Says:

    Thanks for the quick response, Stoyan!
    What I was trying to do is put the multipart and CSS stuff in the tag in the html file. I’m not entirely sure what to put in the url which points to the path to the multipart , i.e. mhtml:http://phpied.com/files/mhtml/mhtml.css!locoloco. Does the path now point to the html file path itself? I also did some google search and found out that maybe content-id is another way to serve as the location here, but I’m still out of luck to get it work.
    I appreciate your help !

  26. waruna Says:

    Is there to specify relative urls instead of absolute urls
    for example
    use something like below
    *background-image: url(mhtml:mhtml.css!locoloco);
    instead of this
    *background-image: url(mhtml:http://phpied.com/files/mhtml/mhtml.css!locoloco);

    thanx

  27. Data URI 和 MHTML @ 随网之舞 Says:

    [...] MHTML和Data URI还比较类似,有更强大的功能和更复杂的语法,并且没有Data URI中“无法被重复利用”的缺点,但MHTML使用起来不够灵活方便,比如对资源引用的URL在mht文件中可以是相对地址,否则必须是绝对地址。hedger在《Cross Browser Base64 Encoded Images Embedded in HTML》针对IE的解决方案使用的是相对路径就是因为声明了Content-type:message/rfc822使IE按照MHTML来解析,如果不修改Content-type则需要使用MHTML协议,这个时候必须使用绝对路径,如《MHTML – when you need data: URIs in IE7 and under》。 [...]

  28. Sander van Veen Says:

    @schepp: What do you think of the technique called “CSS Sprites”? It creates one big images (which can be generated on server side) and send it to the client, instead of sending many small images. For more information: http://www.alistapart.com/articles/sprites

  29. Michael Turner Says:

    I having a problem with *.mht/mhtml. First, I can save web-pages as *mht - no problem. The problem is that I cannot open ANY *.mht/mhtml saved web-page from Microsoft. I save the “fact sheets” (knowledge base articles) for respective MS updates so that, when or if needed I have them available rather than having to always go online to view/read. Some time ago, exactly when I don’t remember, I had no problem with this. However now, when I attempt to open a *.htm saved MS web-page, IE7 grinds to a halt and stops responding. I have to run Task Manager to “end process” for IE. The same holds true for IE8. Additional info … I can open any *.mht saved web-page from any other web-site (so far) without any problem. Also, I can save MS web-pages a *.htm (html) and can open them without any problem. It’s only the MS web-pages I’m having problems with when saved as *.mht. I am using Windows XP Home w/SP2 (fully up-to-date as far as I know) and currently using IE7. MS help is worthless for any kind of assistance. I have been googling various topics and not finding anything that is close to what I am experiencing. Can you help? Thanks for listening.

  30. muthuraja Says:

    very nice post

  31. Mats Says:

    Problem with IE7 on some XP machines.

    The sample page in this article (http://phpied.com/files/mhtml/mhtml.html) will not run with IE7 on some XP machines in my intranet, on other XP machines with IE7 it works fine. I have compared IE settings but there are no differences. There is no error message, the images will just do not show. Any thoughts on this?

  32. Stoyan Says:

    Hi Mats,

    Other comments also reported an issue with XP. Looks like the solution would be to serve the MHTML document with text/plain and inside have the different multi-parts: css and images.

    I don’t have a test page for you to try, but check some of the URLs in the comments above.

    Thanks and please drop a comment if you can/cannot make it work.

    S

  33. Mats Says:

    This thread brings to our attention that sometimes IE7 can not save an archive file (mht) which seem to be related to my problem above, since what we are trying to accomplish actually is to include a web archive (mhtml) in the CSS.

    http://groups.google.com/group/microsoft.public.internetexplorer.general/browse_thread/thread/43f0ebcf38372f5d/60b609a62697af29?hl=en&q=%22web+page+could+not+be+saved%22+group:microsoft.public.*#60b609a62697af29

    Could this be it? I really can not have customers re-install IE7…

  34. High Performance Web Sites :: Aptimize: realtime spriting and more Says:

    [...] they’re not supported in IE7 and earlier. Recent blogs from web dev performance rock stars Stoyan Stefanov and Hedger Wang discuss a workaround for early versions of IE using MHTML. Aptimize has already [...]

  35. Twitted by zigazou Says:

    [...] This post was Twitted by zigazou [...]

  36. Schepp Says:

    @Sander van Veen You are right, this would have been the other option. In this case that image-gallery backend was already existing and I just revamped the frontend-part. Sprites would have worked OK here (if they would hit the server’s memory-limit while beeing built). But in CSS I definitely prefer dataURIsation over sprites as I now have a setup where I can code as usual and PHP transforms everything on the fly (MHTML for IE < 8, dataURIs for the rest). Sprites are more taxing on the server and take longer to autobuild and, depending on the combination of images, are not too effective in using their pixel-space.

  37. Data URIs explained | NCZOnline Says:

    [...] fair amount written about data URIs recently: my colleague Stoyan Stefanov has written a couple of posts about data URIs, and my former colleague Hedger Wang also penned a post about how to use data URIs [...]

  38. 陈成的博客 — Data URI小试 —— 在旺旺点灯(JS)上的应用 Says:

    [...] Stoyan, http://www.phpied.com/data-urls-what-are-they-and-how-to-use/, http://www.phpied.com/mhtml-when-you-need-data-uris-in-ie7-and-under/ R Reid, Detecting IE 8 Compatibility Modes with [...]

  39. Tung Says:

    Hi, thanks for the useful post! just wonder how it’s going to work if I embed the css within the html file? I have twisted the mhtml link in the css many ways but couldn’t get it work. Thanks again!

  40. Asbjørn Ulsberg Says:

    Excellent technique, but executed with conditional comments instead of stuffing everything in the same CSS file, you avoid all of the drawbacks you mention without adding any (to my knowledge, at least) new ones.

  41. Rubidot Says:

    Awesome! But why not just use the MHTML method for all browsers, instead of implementing both?

  42. Rubidot Says:

    nevermind… mhtml is not supported…

  43. High Performance Web Sites :: CSSEmbed - automatically data: URI-ize Says:

    [...] in Internet Explorer 6 & 7, where data: URIs aren’t supported. (See the blog post from Stoyan Stefanov and examples from Hedger Wang for more info on this MHTML [...]

  44. Embedded Images in TiddlyWiki Under IE6 via MHTML – Proof-of-concept Says:

    [...] only came across the MHTML image hack over the weekend, while listening to @jeresig on the new jQuery podcast (incidentally not the only [...]

  45. Ruslan Says:

    You can use online generator of data:uri css sprites

    http://duris.ru/lang/en/

    Supports MHTML for IE<8 & data:URI for other browsers

  46. Shawn Says:

    Has anybody successfully used this technique on a site protected with SSL? We are encountering a problem where IE7/8 is detecting the page contains “mixed content” and pops up that nasty Security Warning dialog even though all of the requests are over HTTPS (confirmed with wireshark).

Leave a Reply