Reputation: 126
Alright, this one is really stumping me. I'm looking for a way to reliably position a position: fixed
element relative to a statically positioned element when after the user pinches to zoom.
More details: this is a problem I am running into with my jQuery plugin, Bigfoot. Essentially, it turns footnotes into clickable buttons that generate popovers with tooltips pointing at the button. The tooltips must be position: fixed
; the popover is placed directly after the paragraph containing the footnote link so that the same paragraph/ image/ other styling applies to the footnote contents by default. This means that position: absolute
, which is easier to work with on mobile, is basically out. The script also needs to be able to reliably calculate the space between the footnote button and the top/ bottom of the visible page (so that the popover can be positioned on top or bottom, depending on which has enough space) and to the right/ left of the visible page (so that the tooltip can be positioned to actually point at the popover).
The thing that works for when the viewport is not zoomed is something along the lines of (with jQuery):
var $target = $(".target");
$(".popover").css({
top: $target.offset().top - $(window).scrollTop(),
left: $target.offset().left
});
However, this method fails to line up the elements when the viewport is scrolled. I can see what the zoom factor is by comparing the inner width (window.innerWidth
) with the total width of the page (document.documentElement.clientWidth
). I can also find the horizontal/vertical offsets with window.pageXOffset/pageYOffset
(these numbers don't appear to be the actual amount of pixels the screen is scrolled horizontally when the viewport is zoomed, but I'm not really sure). However, I have not found any way to combine these pieces of information together to find the actual left
/top
offset values that will properly align the button with its tooltip.
To get an idea of what the script is actually supposed to be doing (and the weird misalignments that happen as a result of zooms on mobile) you can check out the buttons on the project page (http://www.bigfootjs.com). Something that correctly aligns the <div class='aimer'>
(that is position: fixed
) directly over the static <div class='target'>
when the viewport is zoomed on mobile with the following example markup is what I'm looking for (at a minimum, needs to support current mobile Safari):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="aimer"></div>
<div class="target"></div>
</body>
</html>
body {
background-color: lightgray;
}
.target,
.aimer {
width: 1em;
height: 1em;
background-color: red;
border-radius: 1em;
}
.target { margin: 10em 0 40em 6em; }
.aimer {
position: absolute;
background-color: white;
}
Thank you so much in advance for your help, and let me know if there is any other information I can provide!
Upvotes: 5
Views: 2780
Reputation: 9441
This is working for my needs. It relies on position: absolute
, though. position: fixed
behaves differently on chrome vs safari, in respect to viewport zoom level.
document.addEventListener('scroll', function(){
TweenMax.set(element, {
left: window.pageXOffset,
top: window.pageYOffset,
scale: 1 / ($document.width() / innerWidth),
})
})
Upvotes: 1