CSS3 background-position animation lags on mobile devices - android

I'm trying to create a scrolling effect for a background using CSS3 animations, such as:
body {
background: url("bg.jpg") repeat-y 0 0;
animation: animatedBackground 50s linear infinite;
}
#keyframes animatedBackground {
from { background-position: 0 0; }
to { background-position: 0 100%; }
}
(JSFiddle)
This works great, except that it's very laggy on mobile devices (e.g. Android Chrome 43.0)). I've tried various hacks that are suppose to force the browser to use the GPU, which sadly didn't help.
One solution is to use translateY and duplicate the image, like shown here. That doesn't feel very good however, since the image is pretty big to start with. It does run smooth, though.
I'm looking for alternate solutions on how to make this run smooth.

The reason that transform runs smoothly while background-position does not is that transform can utilize the phone's hardware acceleration while background-position must rely on the browser software's re-rendering of the element. Even if it's a large image, using hardware acceleration is always better for mobile.
If it's the same image, any browser worth it's salt isn't going to incur any extra impact by using it twice, as it's cached after the first pull.
So use the transform solution, and feel confident it's the right one.

Inspired by the link in the OP, I found a way to achieve this without having multiple references to the same image. It does, however, require you to know the image's height.
The general idea is to have a relative wrapper which hides all overflow, and force the image to be 200% its height, and make it repeat and finally animate the y-axis -100%. Example:
#parallax-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#parallax-background {
position: relative;
width: 100%;
height: #parallax-image-height * 2;
background: url("/bundles/sunnerbergsimilarseries/images/tv-show-wall.jpg") repeat 0 0;
animation: animatedBackground 50s linear infinite;
transform: translate3d(0, 0, 0);
}
#keyframes animatedBackground {
0% { transform: translateY(0) }
100% { transform: translateY(-#parallax-image-height) }
}
(JSFiddle)
The above runs as smooth on a 2015 Android-phone as on a computer with a dedicated graphics card.

Related

Opera Mobile ignores overflow: hidden | Strange white offset beyond the page content

It's some kind of magic, really. I didn't see anything similar before. So only on Opera Mobile (the latest ver) on the Android device (any), I get a strange white offset while some of the nodes cross the body content width (i.e. became beyond the visible layout). Of course, I don't need any such content, as well as such a white offset.
So I tried to set overflow: hidden as a solution on the parent node(body). Unfortunately, it exactly doesn't work with Opera Mobile (again, the white offset around the page became visible and scrollable).
Exampe of the real code:
#parent_body {
overflow-x: hidden;
overflow-y: scroll;
position: relative;
}
#child_tooltip {
z-index: 99999;
display: table;
}
#tooltip_content {
position: absolute;
z-index: 50;
left: 430px;
top: 175px;
}
Does anyone face such an issue previously? I'll appreciate a lot any help!
Thanks in advance.
Example of such "white offset" around the page:

fixed positioning bug on Android chrome

So I have a simple flash message on our site, which should have fixed positioning in the bottom left. On mobile, I've also added a width of 100% to make it look a little nicer, with a small amount of padding to offset it from the edges.
The container for these flash messages is in the root of the body:
#FlashMessages-Container {
position: fixed;
bottom: 0;
left: 0;
max-width: 550px;
padding: 32px;
z-index: 11;
#include media-down(large) {
max-width: 57%;
}
#include media-down(medium) {
max-width: 100%;
padding: 16px;
}
}
This works great on desktop on all browsers, and also works great on mobile Android/Firefox, iOS/Safari and even iOS/Chrome. However, it doesn't work on Android Chrome, which doesn't calculate the width correctly. You can see from this DevTools screenshot, it's making the flash messages 376px wide when the screen "width" is only 360px (device pixels, that is), so there is no gap on the right side.
If I make the position absolute, the width is correct but then it's not fixed.
Here is the offending Android/Chrome view:
The related dev tools styles:
And here is Android/Firefox which looks fine:
Here's iOS/Firefox too:
And finally, even iOS/Chrome which strangely works fine unlike its Android cousin.

Display a loading spinner while DOM is being painted

I am working on a cordova android application, and would like to display some sort of loading message/spinner while the user's notifications are being loaded as there is a bit of a wait while the DOM is being painted with all the notifications.
We currently use the cg-busy directive in a few places to display spinners during wait times while ajax calls are being completed. However in this case, cg-busy doesn't accomplish what we want as the ajax call is very quick and it is the painting that is taking a long time.
So my question is this: is there some way to get cg-busy to display its spinner while the DOM is being painted or if not, is there something similar we could use to display a spinner during the paint?
What I did is showing a simple CSS animation until angular is done initializing. There are lots of plain CSS loading animations out there, you can just google some. I'll use one of those for this example.
So how does this work? I'm adding following div to my html:
<div class="loadingAnimation" ng-show="::false"></div>
And also following CSS:
.loadingAnimation {
width: 40px;
height: 40px;
margin: 100px auto;
background-color: #3b454b;
border-radius: 100%;
-webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
animation: sk-scaleout 1.0s infinite ease-in-out;
}
#-webkit-keyframes sk-scaleout {
0% {
-webkit-transform: scale(0);
}
100% {
-webkit-transform: scale(1.0);
opacity: 0;
}
}
#keyframes sk-scaleout {
0% {
-webkit-transform: scale(0);
transform: scale(0);
}
100% {
-webkit-transform: scale(1.0);
transform: scale(1.0);
opacity: 0;
}
}
Once angular is done initializing it will evaluate the ng-show and hide the loading animation. The :: are just a performance improvement.
I'm not 100% sure if that's the behaviour you want, so you might want to tweak on the condition for ng-show. But I hope you got the idea.

CSS Hardware Acceleration in Phonegap App

I'm trying to use hardware acceleration in a phonegap application. I have read that I have to put a css 3dtransform for this pourpose. So, I have used a webkit-transform3d in the main class of my html element, but I continue to see some lag during the animation.
I want to open and close a box, settings is height from 0 to somevalue and viceversa.
I have write an example here: http://jsfiddle.net/VG7V5/6/
As you can see, I have defined the class container in this way:
#container {
box-shadow: 0.1em 0.1em 0.2em 0em #777777;
width: 100%;
max-height: 15em;
overflow-y: auto;
transform: translate3d(0em,0em,0em);
-webkit-transform:translate3d(0em,0em,0em);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
If I open the example with my Nexus 5 with Android 4.4.2 I see some lags during the animation, with or without the transform3d enabled (infact in jsfiddle it starts with the transform commented). It seems as nothing change.
Is there something wrong???
Thx
Maybe I have found the solution by myself.
As explained in this article
is possible to achieve high performance animations if they are of these types: position, scale, rotation or opacity.
Essentially the animation should not change the dimensions of the element, because it causes too much overhead for the cpu/gpu.
So, changing the height of the element, as in my example, is not a great idea. :D

How to slide up / slide down an element with Zepto on mobile devices?

A common mobile UI pattern is slide up / slide down, for example sliding up an action sheet, then sliding it back down below the screen when it's not in view.
I've tried various css 3 transitions and Zepto's animate function but have yet to find something that works smoothly and consistently on Android and iPhone.
I figure this post can serve as a definitive question and answer:
How do you make a smooth slide up / slide down work on Android and iPhone browsers (and by extension PhoneGap)?
This is a start:
#action-sheet {
background-color: #333;
height: 200px; /* note that the height changes depending
on # of action divs added to the action picker,
dynamically from Javascript */
width: 250px;
position: fixed;
bottom: -50%; /* something that will get it off the screen */
left: 50%;
margin-left: -125px;
/* maybe some css3 transition here? */
}
#action-sheet.active {
bottom: 0px;
}
iOS and Android browser uses webkit rendering engine, where 3d transforms are hardware accelerated, so that's what you want to use. You should use translate3d.
Adding active class to #action-sheet will slide it down 200px during 2 seconds
#action-sheet {
-webkit-transition: -webkit-transform 2s;
}
#action-sheet.active {
-webkit-transform: translate3d(0,200px,0);
}

Categories

Resources