Tuesday 13 January 2015

Optimising HTML Email for Outlook (2010, 2013)

Sending HTML emails is a tough business. Thanks to the dearth of support for most css properties in various email clients, it becomes a huge challenge to generate an HTML email content that renders properly on all email clients, like Gmail, Yahoo mail, Thunderbird, Outlook, etc.

Its already tough to generate a html markup compatible with various email clients, making sure which css properties are supported where, and using only the common ones. It becomes a huge pain, as we end up using the old table layout for the HTML markup. And above all that, there is the pain of dealing with Outlook email client. No matter how much we hate it, most enterprises rely on Outlook for their day to day business. So making sure our HTML emails render beautifully on Outlook becomes a priority, no matter how impossible the task may be.

In this post we will talk about the small tweaks we can make in our HTML markup, to make sure the email renders smoothly and beautifully in Outlook 2010 and 2013 on windows and on mac.

Outlook 2010 often crashes on opening big HTML emails on it. We will discuss ways to optimise our content to fix this too.


Always remember what css properties you can use. https://www.campaignmonitor.com/css/

This list generally serves as a good reminder for what you can use while making an HTML email

BUT, if you want to optimise for Outlook,

1) Use only table layout for your markup. Do not use any divs in your markup. They cause issues as outlook associates some default styles with them.

2) Do not use padding/margin css properties anywhere. Only use table layout to render your content. It may be painful, but it is rewarding.


3) Do not use spacer images  in your email markup. Try to reduce the number of images in your email. The more images there are, the more time Outlook will take to download them and render the email. Instead of spacer images, try to use   where you would otherwise use spacer images.
(This is one of the reasons for Outlook crashing for bigger emails)

4) If you are using an image, always use https: URLs for the images. This helps in some cases where outlook treats some http url as a bad url and gets stuck.




One last hack if very big emails are still crashing outlook.
There is a property in Outlook settings for "Message Format" called 
"Reduce message size by removing format information not necessary to display the message”



Make sure that this property is checked. If this is unchecked it may slow down the email rendering by about 20%. Which is a lot. Every millisecond matters.


If you do all the above,  and do not deviate from it, then your html email should get rendered on Outlook pretty fast and properly, without crashing it.

If you still face any issues with big emails, feel free to contact me. Would love to help.
Cheers!










Wednesday 17 December 2014

Developing a single phonegap app for mobile phones and tablets- Fluid design and splitview

Note: This was written in 2012


PhoneGap is an HTML5 app platform that allows you to author native applications with web technologies and get access to APIs and app stores. If you don’t know about Phonegap already, i would suggest you take a look at http://phonegap.com/about .


Its incredibly powerful and easy to use. And reduces your development time by tonnes if you plan on developing for multiple platforms. And we can reduce it further by making sure that we can use the same app on mobile as well as tablet screens. If you develop an app for mobile screens, then obviously it would work on tablets too. But from the usability point of view it would not be a good experience for the user, as the font sizes would be small, the app would be spread with too much info on the screen unlike the tablet specific apps which have grid or pane structures. This post is about developing a single app for mobile phones and tablets. Doing that would involve two aspects. Fluid design and the multiple pane view for tablets.

As phonegap apps are all about HTML, JS and CSS, thats where you would need to make changes in order to achieve a unified app.

1) The pane structure-
For the pane structure we use the splitview plugin for jquery plugin.  https://github.com/asyraf9/jquery-mobile/
The plugin is very basic. It just creates a 2 pane structure for large screens. something like -

// image of 2 panes - cropped

The plugin comes with 2 css files
-jquery.mobile.splitview.css
-jquery.mobile.grids.collapsible.css
And iscroll which it uses to scroll.

Also the thing to look out is that this plugin uses its own jquery mobile version. YES, thats the catch. for now if you want to use this plugin you would have to fork the whole repository and use the jquerymobile which the splitview plugin references. (see the code on github)

The order of css and js files is important. It is advised to include them in the following order

jquery.mobile.css
jquery.mobile.splitview.css
jquery.mobile.grids.collapsible.css
jquery-1.7.1.js
jquery.mobile.splitview.js
jquery.mobile.js
iscroll-wrapper.js
iscroll.js

Follow the example as closely as you can and get a local copy working. Then you can start taking a peek into the code. :)

The code structure-

To use the plugin you need to have a particular code structure.


<div data-role="panel" data-id="menu" >     
   <div data-role="page"   data-hash="false">
     <div data-role="header" >
      </div>

     <div data-role="content" >
     </div>

     <div data-role="footer">
    </div>
  </div>

</div>

<div data-role="panel" data-id="main" data-hash="crumbs" data-context="a#default">

   <div data-role="page" >

       <div data-role="header">
       </div>

       <div data-role="content">

       </div>
       <div data-role="footer" > </div>

   </div>
</div>

As you can see there is a data-role = panel. This is a pane of the view. You can have only 2 panes using this plugin. the left one would have a
data-id="menu"
and the right one would have a  data-id="main"

Inside these panels you have the normal jqm pages.  
There are 3 modes for the splitview plugin has.  For deciding this it uses this condition -

var $query = $.mobile.media('screen and (min-width: 480px)') && ($.mobile.media('(-webkit-max-device-pixel-ratio: 1.2)') || $.mobile.media('max--moz-device-pixel-ratio: 1.2)'));
       var isSplitviewSupported =  ($query || ($.mobile.browser.ie && $(this).width() >= 480)) && $.mobile.ajaxEnabled;
     
So if isSplitviewSupported is true,  then based on if the screen width is greater or less than 768, it shows the splitview or popover modes, whose screenshots you have seen above.

If splitview is not supported, then it removes the panel html structure and the mail panel completely and just leaves the page in the menu panel which jqm picks up as the active page.
If you want the main panel page to remain instead of the menu panel one, you can change the behaviour in its code.




How it works in a nutshell:

It simply creates 2 panels and defines a way to load pages into those panels instead of the just adding the class to the dom and making it the active class. If you look closely








I am just going to cover the basics of using the plugin.



loadPageToMenuPanel: function(href, args) {
       var $currPanelActivePage = $('div:jqmData(id="menu")').children('div.' + $.mobile.activePageClass);
       $.mobile.pageContainer = $('div:jqmData(id="menu")');
       var opts = {
           fromPage:$currPanelActivePage,
           reverse:false,
           changeHash:false,
           pageContainer:$('div:jqmData(id="menu")')
       };
       $.extend(opts, args);
       $.mobile.changePage(href, opts);
      // $.mobile.activePage = $('div:jqmData(id="menu") > div.'+$.mobile.activePageClass);
   }



loadPageToMainPanel: function(href, args) {
       if(href=="menu.html"){
               href="oldMenu.html";
       }

       var $currPanelActivePage = $('div:jqmData(id="main")').children('div.' + $.mobile.activePageClass);
       $.mobile.pageContainer = $('div:jqmData(id="main")');
       var opts = {
           fromPage:$currPanelActivePage,
           reverse:false,
           changeHash:false,
           pageContainer:$('div:jqmData(id="main")')
       };
       console.log("changing page:"+href);
       if(href!="share.html" && href!="search.html")
           $.extend(opts, args);
       $.mobile.changePage(href, opts);
       $.mobile.activePage = $('div:jqmData(id="main") > div.' + $.mobile.activePageClass);

   },


@media only screen and (max-width : 35.6cm),
only screen and (max-device-width : 35.6cm){
}


@media only screen and (max-width : 25.4cm),
       only screen and (max-device-width : 25.4cm){    
}



@media only screen and (max-width : 15.2cm),
       only screen and (max-device-width : 15.2cm){
    
}

@media only screen and (max-width : 7.6cm),
       only screen and (max-device-width : 7.6cm){

}