How Many Users Resize Their Browser?
August 2017
TL;DR: 2-3% of users resize their browser, and you should care.
In data visualization, “responsive” design is no longer a buzzword, but simply part of the design process. As a community, there is no shortage of discussion about how to design for mobile versus desktop, and all the challenges and solutions that go along with it. But lost in all that noise is the transition between those worlds, i.e., how does our code work when a user resizes the browser instead of just on load?
How you anticipate user behavior will influence how you structure your code. If you think “only developers resize,” then you might be content to render your vis with dimensions once, on load. This is, in fact, much easier, so why waste the extra effort?
In the past few years, I have often wrestled with this question. Like you though, I prefer to make decisions driven by data. Assuming this question had been answered, I did some thorough Googling. There were two posts that addressed this exact question with a data-driven approach. However, I was unsatisfied with the results. One was from 2014, which is before many of us were even data-born, the other scrolljacks, which makes me trust nothing, and both have methodologies that don’t quite reflect actual resize usage.
So I created my own script to track this behavior. The gist is that it compares browser width (not height) on a debounced resize, and sends a tracking event once if they differ. Why just width? Take a look at the video below:
On both iOS and Android, scrolling up/down actually makes the navbar to toggle visibility, and thus changes the height of the browser. This triggers a window resize event. However, with few exceptions, you rarely need to handle a resize event with a height change alone. The main reason to do so is if you need the graphic to be exactly the height of the browser at all times (e.g., with scrollytelling). For most graphic use cases, the initial height (or the computed height accompanied at the time of a width resize) is just fine for calculations.
Ok, so finally some raw numbers:
Device | Views | # Resizes | % Resized |
---|---|---|---|
Mobile (+ Tablet) | 8,023 | 158 | 2.0% |
Desktop | 3,581 | 83 | 2.3% |
I’m actually surprised a bit by both numbers. I expected mobile to be lower because a resize here basically means an orientation change, which I never do. I expected desktop to be higher because I often find myself moving windows around.
Does 2% matter?
Obviously it is your choice if you want or need to put the in the effort. If you are delivering critical information to your users then the answer should always be yes. If it is for fun, then you probably don’t need to stress about it. Regardless, I think it is a better way to structure your code because it makes it more modular and flexible. But think of it this way; if you get 50k people to look at your work, that means 1,000 are going to resize the browser, and see something potentially broken.
How to handle resize
If you haven’t fit your code to handle this use case before, here is a basic template that I follow to make things easy.
// psuedocode for basic resize structure
function setup() {
setupDOMElements...
bindData...
enterAppendElements...
}
function resize() {
getNewDimensions...
updateScales...
updateElementsSizeAndPosition...
}
function init() {
// call setup once on page load
setup()
// call resize once on page load
resize()
// setup event listener to handle window resize
// okay
window.addEventListener('resize', resize)
// better (using something like lodash.debounce)
window.addEventListener('resize', debounce(resize, 150))
}
init()
Wrapping up
If anyone has done this internally, would like to run my code to get more data, or has ideas for improvements, please let me know! Below is a stripped down version of the snippet I used:
// d3 and lodash.debounce included
const bodySel = d3.select('body')
let previousWidth = bodySel.node().offsetWidth
function resize() {
const width = bodySel.node().offsetWidth
if (previousWidth !== width) {
previousWidth = width
// SEND TRACKER EVENT ONCE
}
}
function init() {
window.addEventListener('resize', debounce(resize, 150))
}
init()
Get in touch: russell@polygraph.cool or @russellviz.