0.3.0 • Published 8 years ago

mobile-viewport-control v0.3.0

Weekly downloads
3
License
ISC
Repository
github
Last release
8 years ago

Mobile Viewport Control

On mobile browsers, Apple set a non-standardized precedent of controlling the viewport with one or more meta tags:

<meta name="viewport" content="name=value,name=value,...">

See Quirksmode for more context: 1, 2

The goal of this project is to see if we can use these tags to dynamically modify the viewport at runtime. Specifically, we want to freeze the viewport at some zoom level, then restore the viewport later.

Generally, a user should be able to pinch-zoom a page. But for things like popup modals, the user experience is better if the viewport is preset like a native app.

Usage

npm install mobile-viewport-control
const viewport = require('mobile-viewport-control');
// ... or use `window.mobileViewportControl` if not used with package manager


// Freeze the viewport at a desired scale.
viewport.freeze(1.0, () => console.log('notified when frozen!'));

// Restore the viewport to what it was before freezing.
viewport.thaw(() => console.log('notified when thawed!'));

Additionally, to freeze the scroll area to a given element, you can pass an element ID as the second argument. We do this by temporarily hiding everything else on the page. Just make sure your element is a direct child of document.body.

viewport.freeze(1.0, 'myElementID');

Compatibility Testing

NOTE: We do not test with Simulators, as iOS Simulator has been shown to produce different results than the real environment.

Compatibility is measured with a combination of automatic/manual testing:

  1. Measure Test - verify that we can measure the current viewport scale.
  2. Freeze Test - verify that we can set and freeze the viewport scale.
  3. Manual step - pinch-zoom before starting the test
  4. Manual step - verify that you cannot pinch-zoom after the test
  5. Thaw Test - verify that we can restore the viewport scale and bounds.
  6. Manual step - pinch-zoom before starting the test
  7. Manual step - verify that you can still pinch-zoom after the test
  8. Injection Method - verify it works for any webpage by running a bookmarklet test to inject JS into the page
Mobile BrowserMeasure Test*Freeze TestThaw TestInjection Method
iOS SafariYYYdevtools
iOS UIWebViewYFails**Y if freeze works.xcode+devtools
iOS WKWebViewYYYxcode+devtools
iOS SFSafariViewControllerYYY
iOS ChromeYYYbookmarklet
iOS FirefoxYYY
iOS Opera MiniYFails**Y if freeze works.
Android Browser (Stock)???
Android ChromeYYYdevtools or bookmarklet
Android WebViewYYYdevtools
Android Chrome Custom TabsYYYdevtools
Android FirefoxYFailsFailsdevtools or bookmarklet
Android Opera MiniFailsFailsFails

* This test fails in the iOS Simulator because initial-scale is ignored there for wide pages for some reason.

** Fails if user pinch-zooms before freezing. Pinch-zooming causes the page's scale to change from its specified initial-scale. This custom zoom level is maintained across refreshes. When opening in a new tab, the initial-scale is resumed.

Injecting into Existing Pages

To allow us to quickly gauge compatibility for externally owned webpages across several browsers, we must be able to inject our library code into their running pages.

With Bookmarklet

Bookmarklets are URLs of the form javascript:(function(){ ... }()) which some browsers allow for evaluating JS in the context of the current page. The mobile browsers compatible are listed in the above table under the Injection Method column.

The following bookmarklet will freeze the viewport scale, show a custom isolated element, and allow you to press a button to restore the view.

javascript:(function(){document.body.appendChild(document.createElement('script')).src='https://rawgit.com/shaunstripe/mobile-viewport-control/master/bookmarklet/index.js?'+Math.random();}())
With DevTools

Some mobile browsers allow you to connect to a Desktop DevTools environment with a JS console for evaluating JS in the context of its page. iOS Safari supports connecting to Desktop Safari DevTools in this way. Android Chrome/webview can connect to Desktop Chrome DevTools. Inside DevTools, we can simply paste the body of the bookmarklet inside the JS console:

document.body.appendChild(document.createElement('script')).src='https://rawgit.com/shaunstripe/mobile-viewport-control/master/bookmarklet/index.js?'+Math.random();

iOS webviews require an extra step: you must run an webview app from a live XCode project on your mac. Only then will Desktop Safari DevTools to connect to its webview.

Variables

We currently do not test all variables, but the test outcomes depend on the following:

  • browser/platform
  • page width (modify in test.css)
  • screen orientation (portrait or landscape)
  • refresh delay (for viewport changes to take effect)
  • initial zoom, influenced by either of:
    • default zoom specified in initial-scale
    • manual zoom remembered before page refresh
    • manual zoom after page load and before test run
  • initial zoom bounds (controlled by page's original viewport meta tags)

Quirks when Dynamically Modifying Viewport

  • iOS UIWebView does not allow scale adjustments after the user has manually adjusted it.
  • Android does not register a new viewport meta tag if it is immediately removed after creation.
  • Android will modify the scroll some time after a new viewport tag is registered.
  • Android (at least in Chrome) will not freeze scale at 1.0, but will at 1.0±ε for some ε>0.

License

ISC License

0.3.0

8 years ago

0.2.0

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago