Modify div location on Zoom Mobile Safari

I'm having a very hard time preserving a div's location relative to the entire screen when a user zooms in. Basically, what I am trying to do is relocate a div to the properly calculated location making it appear as though it never moved even though the user may have zoomed. This is quickly becoming very tricky as I basically want to undo any visual changes that have been made by the zooming event.

For example if the top of the div is currently at the center of the screen at zoom level 1, (say scale of 1.00), when the user goes to zoom level 2, (via a pinch zoom gesture, say scale of 1.235), I would like to re-position the top of the div back to the center of the screen.

Currently, I am binding the parent container of the div to a function that catches gesture events.

see link for source.

Any guidance on this matter would be appreciated. Thanks.

Update: Here is a link to a sample application. You can find all of my current handlers and functionality. My main concern is the reset of the element 'palmGuard' to the same location relative to the screen, after a zoom. Let me know if you have any questions.


This example only works on mobile safari



Well i'll be honest and tell you that i haven't yet worked on mobile apps/webstes. So i may not be right on all the syntax if they differ from traditional jquery used for websites. But you can try the below algorithm(which basically positions the div at the center of page from top). I have used traditional jquery since I'm familiar with it.

/* ---- Excute the below lines on $(window).resize(function(){}); or a function that is triggered on zoom [which ever is correct] ---- */

var modalH = parseInt($('[THE DIV/ELEMENT THAT YOU WANT TO CENTER]').css('height'));
var windowH = $(window).height();
var modalPosY = (windowH - modalH) / 2;

and ofcourse the CSS property of the div/element has to be absolute[if it isn't already set]. And the same can be done to center along the x-axis(replacing height with width)


You could use percentage values for the position of the div/element(which i presume works better). The following article will help you on that - .(check out the test case)


Ok I believe this does what you want.

Instead of using a zoom factor you need to calculate the position of the div proportionally to the iOS screen. You will need to keep track of this throughout. Whenever the div is moved (not zoomed) and at the start you need to get this value:

//When div moved and start
var height = window.innerHeight; //Adjust if needed
screenPos = (currentDivTop - window.pageYOffset)/height;

Then when zooming happens you need to set the top of the div on gestureEnd to the top point of the page on screen (i.e. window.pageYOffset) plus the current number pixels on screen (window.innerHeight) times by the relative position on the iOS screen we calculated earlier (screenPos). This gives you new position on screen required (not the difference from last time).

//GestureEnd of zoom
var height = window.innerHeight; //Adjust if needed
var newDivTop = window.pageYOffset + (screenPos*height);

Remember you will need to keep track of this proportion value.

Also I think your logic for zoom "banding" is overly simple, that is if that's for handling when zooming bounces back to within it's range? I don't think it takes into account different iOS Screen sizes.

As well as the "banding" effecting the innerHeight it also seems to effect the value of posYOffset, which makes sense really. This will cause the div to be placed lower down the page. One potential way around this would be to detect when zooming has gone too far (banding as you refer to it) and using a polling function detect when the innerHeight has dropped back to it's minimum, then get the posYOffset. If there exists an event after banding polling would obviously not be required.

You might be able to calculate the correct top of the screen (posYOffset) from the innerHeight value banding, but I think it may be dependant on where on the zoom the fingers are place when zooming.

Similarly the value of posYOffset and innerHeight does seem to change after the gestureEnd event, so even without banding occurring you will need some mechanism to pick up the settled value of pageYOffset and innerHeight. You can test this effect by adding the following to gestureEnd:

//In gestureEnd
alert ('gestureEnd pageY:'+window.pageYOffset+' height:'+height);
setTimeout(function () {
              alert ('later pageY:'+window.pageYOffset+' height:'+window.innerHeight);


Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.