问题
I'm currently developing a web app using html5 and jQuery for iPad Safari. I'm running into a problem wherein large scroll areas cause the elements that are offscreen to appear after a delay when I scroll down to them.
What I mean by that is, if I have a row of images (or even a div with a gradient) that is offscreen, when I scroll down (or up) to it, the expected behavior is for the element to appear on screen as I am scrolling to it.
However, what I'm seeing is that the element does not appear until I lift my finger off the screen and the scroller finishes all its animations.
This is causing a super noticeable problem for me, making the whole thing look choppy, although it is not. I'm guessing the iPad Safari is trying to do something to save memory. Is there any way in which I can prevent this choppy-ness from happening. Additionally, I would also appreciate if anyone can shed light on what the iPad Safari is actually trying to do.
回答1:
You need to trick the browser to use hardware acceleration more effectively. You can do this with an empty 3d transform:
-webkit-transform: translate3d(0,0,0)
Particularly, you'll need this on child elements that have a position:relative;
declaration (or, just go all out and do it to all child elements).
Not a guaranteed fix, but fairly successful most of the time.
Hat tip: https://web.archive.org/web/20131005175118/http://cantina.co/2012/03/06/ios-5-native-scrolling-grins-and-gothcas/
回答2:
This is the complete answer to my question. I had originally marked @Colin Williams' answer as the correct answer, as it helped me get to the complete solution. A community member, @Slipp D. Thompson edited my question, after about 2.5 years of me having asked it, and told me I was abusing SO's Q & A format. He also told me to separately post this as the answer. So here's the complete answer that solved my problem:
@Colin Williams, thank you! Your answer and the article you linked out to gave me a lead to try something with CSS.
So, I was using translate3d before. It produced unwanted results. Basically, it would chop off and NOT RENDER elements that were offscreen, until I interacted with them. So, basically, in landscape orientation, half of my site that was offscreen was not being shown. This is a iPad web app, owing to which I was in a fix.
Applying translate3d to relatively positioned elements solved the problem for those elements, but other elements stopped rendering, once offscreen. The elements that I couldn't interact with (artwork) would never render again, unless I reloaded the page.
The complete solution:
*:not(html) {
-webkit-transform: translate3d(0, 0, 0);
}
Now, although this might not be the most "efficient" solution, it was the only one that works. Mobile Safari does not render the elements that are offscreen, or sometimes renders erratically, when using -webkit-overflow-scrolling: touch
. Unless a translate3d is applied to all other elements that might go offscreen owing to that scroll, those elements will be chopped off after scrolling.
So, thanks again, and hope this helps some other lost soul. This surely helped me big time!
回答3:
Targeting all elements but html : *:not(html)
caused problems on other elements in my case. It modified the stacking context, causing some z-index to break.
We should better try to target the right element and apply -webkit-transform: translate3d(0,0,0)
to it only.
Edit : sometimes the translate3D(0,0,0)
doesn't work, we can use the following method, targeting the right element :
@keyframes redraw{
0% {opacity: 1;}
100% {opacity: .99;}
}
// ios redraw fix
animation: redraw 1s linear infinite;
回答4:
When the translate3d doesn't work, try to add perspective. It always works for me
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
perspective: 1000;
-webkit-perspective: 1000;
http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css
回答5:
Adding -webkit-transform: translate3d(0,0,0)
to an element statically doesn't work for me.
I apply this property dynamically. For example, when a page is scrolled, I set -webkit-transform: translate3d(0,0,0)
on a element. Then after a short delay, I reset this property, that is, -webkit-transform: none
This approach seems to work.
Thank you, @Colin Williams for pointing me in the right direction.
回答6:
I had the same issue with iscroll 4.2.5 on ios7. The whole scroll element just disappear.
I've tried to add translate3d(0,0,0)
as was suggested here, it have solved the problem, but it disabled the iscroll "snap" effect.
The solution came with giving "position:relative; z-index:1000;display:block"
css properties to the whole container that holds the scroll element and there is no need to give translate3d to child elements.
回答7:
I'm pretty darn sure I just solved this with:
overflow-y: auto;
(Presumably just overflow: auto;
would work too depending on your needs.)
回答8:
There are cases where a rotation is applied and/or a Z index is used.
Rotation: An existing declaration of -webkit-transform
to rotate an element might not be enough to tackle the appearance problem as well (like -webkit-transform: rotate(-45deg)
). In this case you can use -webkit-transform: translateZ(0px) rotateZ(-45deg)
as a trick (mind the rotateZ).
Z index: Together with the rotation you might define a positive z-index
property, like z-index: 42
. The above steps described under "Rotation" were in my case enough to resolve the issue, even with the empty translateZ(0px)
. I suspect though that the Z index in this case may have caused the disappearing and reappearing in the first place. In any case the z-index: 42
property needs to be kept -- -webkit-transform: translateZ(42px)
only is not enough.
回答9:
This is a very common problem faced by developers and that is mainly due to Safari's
property of not recreating elements defined as position : fixed
.
So either change the position property or some hack needs to be applied as mentioned in other answers.
Link1
Link2
回答10:
In my case (an iOS Phonegap app), applying translate3d to relative child elements did not resolve the issue. My scrollable element didn't have a set height as it was absolutely positioned and I was defining the top and bottom positions. What fixed it for me was adding a min-height (of 100px).
回答11:
I had the same issue using an older version of Fancybox. Upgrading to v3 will solve your problem OR you can just add:
html, body {
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
回答12:
At time translate3d
may not work, in those cases perspective
can be used
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
perspective: 1000;
-webkit-perspective: 1000;
回答13:
I faced this problem in a Framework7 & Cordova project. I tried all the solutions above. They did not solve my problem.
In my case, I was using 10+ css animations on the same page with infinite rotation (transform). I had to remove the animations. It is ok now with the lack of some visual features.
If the solutions above do not help you, you may start eliminating some animations.
回答14:
the -webkit-transform: translate3d(0, 0, 0);
trick didn't work for me. In my case I had set a parent to:
// parent
height: 100vh;
Changing that to:
height: auto;
min-height: 100vh;
Solved the issue in case someone else is facing the same situation.
来源:https://stackoverflow.com/questions/9807620/ipad-safari-scrolling-causes-html-elements-to-disappear-and-reappear-with-a-dela