Tuesday, June 28, 2016

Taming the size of a Salesforce Canvas

For an artist, facing a blank canvas can be a real challenge. For a Salesforce developer a Canvas app can be challenging for an entirely different reason - how to even define what size the Canvas is to start with?

In the ideal world you could just follow the docs and Automatically Resize the Canvas App to suit the content size. In practice this doesn't work so well for all scenarios.

I'm looking to embed an existing web application that was previously located in a Web Tab iframe into a Canvas Visualforce page using <apex:canvasApp />. My ideal goal is that the external web application blends in with Salesforce. There shouldn't be any jarring scrollbars on the iframe that make it look out of place.

The Web Tab approached worked well in that the width of the iframe didn't need to be defined and so it would get an <iframe width="100%">. Now the iframe can shrink and grow to follow along with any changes to the browser size. The nested app can correspondingly adjust its width to suit the available dimensions. The downside to this approach is that the iframes height needs to be specified. This is more problematic, and requires a fixed height that is sufficient to hold the majority of content. E.g. 3000px. Ech! Crazy vertical scroll bar!

Back the the Canvas iframe and the problem with dimensions. Firstly, a plain default Canvas app won't size past 2000px in height and 1000px in width. You need to explicitly set the maxHeight and maxWidth attributes to "infinite" (Documented in Docs but undocumented in other locations.). With the browser full width on a 1080 screen the default 1000px width limit is way too low. Sadly there is currently no corresponding minWidth/minHeight attributes.

Now we've pulled the limits off how big the iframe can get, how to correctly size it to both the browser window and the content within? As mentioned above, the auto resize should be just the thing here. Unfortunately it doesn't play so well with content that dynamically scales to the available space. I found it would either default to the minimum page width defined by the content, or worse still, shrink as the iframe content used Javascript to resize and then reacted to the auto resizing in an unending loop. If there was a way to define the minimum height and to let the iframe width stay at "100%" it would be infinitely more useful.

The autogrow() resizing script appears to come from canvas-all.js. It is basically a timer to periodically call resize. I haven't gone through the fine details, but I believe part of the code is for communicating with the parent iframe so that it can be resized accordingly.

How can I size a Canvas apps iframe in Visualforce to be the full window width with a height to fit the content?

At this stage I'm experimenting with either using a custom canvas-all.js implementation or manually calling Sfdc.canvas.client.resize(). I'll update this page when I get somewhere workable.

Another potential problem with the height is dynamic content, such a modal dialogs, that may not register as affecting the page height.

See also: