Prototyping Refloz (Reflow on Zoom)

Prototyping Refloz (Reflow on Zoom)

As part of the Readability 2.0 project, we're trying a few different approaches to making text beautiful and easily readable on a mobile device in Firefox for Android. When text isn't readable, most people think that increasing the size of the text is the answer to making it readable, and this is one approach, which we call "font inflation". This technique is described (in probably excruciating detail) in a previous blog post[1]. There are a couple of other approaches, though, that we've been toying with.

One solution is to offer users a "mini reader mode" - a pop-over or "light box" that contains the text, in a more readable format, which floats over the main page. Kats[1:1] is working on a prototype to show how this might work. The original idea for this was to have a floating box overlay the text in a given area, so that user could see both the box with the more readable text, but also the context in which that text fits into the underlying page by showing the page behind the box. The idea is novel and unique to Firefox, although it's not clear whether this prototype is going to ship in a release yet or not. In any case, Kats' prototype is really beginning to demonstrate the possibilities of this approach to improving readability.

Another approach is the "reflow on zoom" approach. Basically, the idea here is to reflow the page as the user zooms in, potentially narrowing the text frames in order to force text wrapping. This is a solution to the horizontal scrolling problem described in Font Inflation, Fennec, and You 1. The technical details of this aren't incredibly exciting - I added an API for specifying the max line box width, which, when changed, generates a reflow event[1:2]. This API is accessible from chrome javascript, meaning that webpages don't have access to this API, only javascript used as part of the rendering of the browser itself (what we call the "browser chrome", meaning the window decorations, the address bar, etc...). Inside of the browser itself, on mobile, I then specify the max line box width to be no greater than the width of the viewport (minus some padding so that text doesn't go right to the edge of the screen). Currently, this is still a pretty rough prototype. There are a number of things that still need to be polished before it can be ready for actual use. You can see an example of what the prototype looks like in the following image, though:

![Screen Capture 1, Without Reflow-On-Zoom](/content/images/2015/08/scap1_nvcfsb.png) ![Screen Capture 2 - With Reflow-On-Zoom](/content/images/2015/08/scap2_xupvi8.png)

The problem I'm currently working on is a positioning problem. There are two methods commonly used to trigger zoom on mobile - a double tap gesture, and a pinch gesture. If the user double taps the screen, it will find the element associated with a particular point where the double tap occurred and then zoom in to this element. Unfortunately, this is somewhat less than ideal, since the whole point of the reflow on zoom concept is for the user to specify what the ideal zoom level is for her, then have the text wrap according to this width. Many elements are already almost as wide as the viewport, so enhancing them just a bit isn't really a useful technique - we're not actually increasing readability.

The other gesture, pinching to indicate the level of zoom, is more promising, but comes with its own set of difficulties. The biggest difficulty is that when the user zooms in to a particular rectangle, we want to maintain the position of the text she zoomed in to in relation to the viewport. When the reflow event happens after changing the line box width, the text moves a bit to the left, since the width of the element changes, causing it to no longer be centered within the viewport. This can be rectified easily using similar code in the double-tap gesture approach, but only if we can identify the element into which the user wanted to zoom. This is further complicated by the fact that pinching doesn't have a single point to zoom in on like double-tapping does. Instead, it has a beginning point, several points as the user widens their fingers, and then a final point. These points appear to track the center of the line between the user's two fingers. So, do we take the average of these points? The first point where the user's fingers are close together? The last point, where the user's fingers are furthest apart? As an additional problem, we might not be able to identify a specific element correctly - a DOM element might be too large of an area for us to use - perhaps we want something more like a piece of text to target.

All of these problems are solvable, but the prototype is still in the early stages. It'll probably be many more iterations of this prototype before it's finally ready for the prime time.

  1. Bug 780258: Add support for max line box width API ↩︎ ↩︎ ↩︎