Responsive design best practices for embedding Tableau
Since the release of Tableau’s Embedding API v3, it’s become super easy and quick to embed dashboards on websites.
When it comes to responsive design, my go to guidance has been for customers to use Automatic sized dashboards and always make sure there’s at least a Phone layout if they expect content to be accessed by mobile devices. Also to never use floating objects, to avoid dashboard elements to jump to weird placements as the screen resizes.
But this isn’t the full story and it still presents issues e.g. when the screen get too small and numbers start to disappear and show as ######, not to mention that using Automatic layouts can (marginally) reduce load time performance.
To achieve a fully adaptive solution that dynamically scales all of the content inside the dashboard proportionally, one needs to take into account that dashboard designers these days really want to have full control of dashboard size using fixed sizes, multiple content zones (containers), long dashboards built for scrolling and also even trying to incorporate UI designs similar to modern websites (have a look at the incredible content by the Datafam community in Tableau Public to understand what I mean).
We highly recommend avoiding the use floating objects when embedding especially with Automatic sized layouts, as you can achieve the same final result with tiled containers with a little bit more work. The end result is way more predictable. There is a good introduction to tiled containers here.
In this article we present a technique for clients embedding Tableau in portals and sample code that may work in most scenarios (including using floating objects).
First a quick demo of the finished product, a fully adaptive experience:
Notice as we resize the screen, the whole embedded container resizes proportionally, until we hit our defined phone breakpoint and the page updates to use the phone layout.
- Try a Live demo: https://tableauresponsive.netlify.app
- Source Code: https://github.com/alexeski/tableau-embed-viz-responsive-apiv3
Here’s the step by step:
- Create your Dashboard with 3 layouts as follows
1.1 Default → Use Fixed Size, making sure the size will match the largest screen resolution your customers will ever need:
Note that our code will ensure the embedded dashboard will never scale beyond the custom size we set, otherwise it could cause pixelating. It will also ensure it’s centered into its containier on large screens.
1.2 Desktop → Leave it set to Default, so that it’s really using Fixed size, as per above
Important caveat (a bug?): Don’t ever click “Fit All”, otherwise you will “decouple” it from the Default layout and it will stick to “Fit all” = automatic when publishing, which probably isn’t what you want if we are using CSS scaling instead. You can tell it’s still coupled to Default (Fixed Size) when you can still see the empty space to the right of the container in the Web Authoring window. If this happens, just delete the Desktop layout and add it again, leave it set to Default and republish the workbook.
1.3 Phone → Set to Fit width and make sure to create a nice phone layout, instead of leveraging the automatic one generated by Tableau. In our code, we’ll not scale this layout and with “Fit Width” Tableau will take care of its resizing for us
ps: Looking some best practices on how to create mobile-optimized layouts? Check this great article by Agata Ketterick from Lovelytics.
1.4 Don’t add a Tablet layout, as it’s irrelevant. Tablets will render nicelly the scaled version of the Fixed Size Desktop dashboard using our code
1.5 If you have multiple published dashboards, make sure they ALL follow the same configuration as above.
2. Embed code dynamic scaling logic:
2.1 You need to define the media query breakpoint for the switch between phone and desktop, e.g. 576px
2.2 Confirm the dashboard layout has a fixed size (i.e. behaviour === “exactly”)
Note: at the time of writing, the Embedding API v3.5 seems to lack methods to access the behaviour and maximum/minumum sizes of dashboards, although the interface is present in the documentation. No worries, we can still get this via the worksheet’s prototype object.
2.3 Implement logic to listen for screen size change events and whether it’s hitting our breakpoint by comparing it with the current screen size
2.4 Implement the scalling via CSS Transforms, by computing the scalingFactor = currentWidth / maxWidth
For example: if currentWidth = 900 and maxWidth = 1200, scaling factor is .75
Also notice that we’re not scaling the Phone layout, as it’s taken care by “Fit Width”, as descibed in section 1.3 above.
2.5 Apply this little patch to ensure the positioning of the dashboard is correct whether we’re scaling above or below the maximum size , while ensuring the dash is always centered on the page and only show it on the page on the first page load once all the scaling has completed.
JS:
html:
CSS:
Notice we’re scaling all <tableau-viz> web components embedded in the page, but you may extend this logic to other types of Tableau components, such as <tableau-viz-authoring>.
- Try a Live demo: https://tableauresponsive.netlify.app/
- Source Code: https://github.com/alexeski/tableau-embed-viz-responsive-apiv3
I’d love to hear if you have leveraged this tecnique or a different one. Please share your feedback in the comments section!
Credits:
Source Code: The logic for this solution was originally written by John Hegele who came up with a library called TabScale which uses CSS properties to scale up or down the rendered Tableau viz within a page so that it fills up the page, regardless of the arbitrary size the user has chosen for the browser window. This worked great for Tableau Javascript api v2 and this article is a simplified implementation of his idea for v3.
Dashboard sample: Mobile-Optimized Superstore Sales Dashboard by Agata Ketterick (Lovelitics Lead Consultant, BI & Data Visualization). I had to tweak it so it’s using Fixed size for Default, instead of Automatic. Don’t miss her guide: Optimizing Tableau Business Dashboards for Mobile
R&D: Tim Payne (Tableau Embedded Analytics SE) for helping me with R&D, troubleshooting the API v3 nuances and with the writeup of this article.