During my work on a CSS image zooming feature I encountered a performance problem in mobile Chrome.
Description: If I try to scale images by adding the CSS transform property directly to the image everything works well. The zooming transition is smooth like butter with 60fps (JSFiddle).
<img src="http://placehold.it/1000x1500" style="transform:matrix(2, 0, 0, 2, 0, 0);" />
The Problem: But if I wrap the image in a div container and try to transform the container the transition is very laggy (JSFiddle). The transition starts with a big delay and isn't smooth. It seems to be a mobile Chrome only problem because it doesn't happen in other browsers like Firefox on Android, just on my mobile device (Nexus 5) and some other Android devices.
<div style="transform:matrix(2, 0, 0, 2, 0, 0);">
<img src="http://placehold.it/1000x1500" />
</div>
Does someone know whats wrong with the CSS or HTML structure?
TL;DR # Take care that your animations don't cause performance issues; ensure that you know the impact of animating a given CSS property. Animating properties that change the geometry of the page (layout) or cause painting are particularly expensive. Where you can, stick to changing transforms and opacity.
The transition-delay property specifies when the transition effect will start. The transition-delay value is defined in seconds (s) or milliseconds (ms).
Triggering transitions You can trigger CSS transitions directly with pseudo classes like :hover (activates when the mouse goes over an element), :focus (activates when a user tabs onto an element, or when a user clicks into an input element), or :active (activates when user clicks on the element).
CSS transitions provide a way to control animation speed when changing CSS properties. Instead of having property changes take effect immediately, you can cause the changes in a property to take place over a period of time.
Greensock plugin is by far the best in terms of performance I've seen. Some time ago I make a deep study and some tests, and it's been by far, one of the best plugins to animate elements.
It's lightweight, fast and easy to use.
What about performance? Take a look on your own: https://www.greensock.com/js/speed.html
Here's your example using gsap library:
var content = document.getElementById('zoom-container').children[0];
document.getElementById('zoom-in').addEventListener('click',
function zoomIn() {
TweenLite.to(content, 1.5, {scale:1});
}, false);
document.getElementById('zoom-out').addEventListener('click',
function zoomOut() {
TweenLite.to(content, 1.5, {scale:0.2});
}, false);
* {
margin: 0;
padding: 0;
}
img {
display: inline-block;
}
html,
body {
height: 100%;
width: 100%;
}
#zoom-container div {
position: relative;
/*some prefix*/-transform-origin: 0 0;
transform-origin: 0 0;
}
#zoom-toolbar {
position: absolute;
top: 0;
left: 0;
}
.zommIn {
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<div id="zoom-container" style="height:100%; width:100%;">
<div>
<img src="http://placehold.it/1000x1500" />
</div>
</div>
<div id="zoom-toolbar">
<button id="zoom-in">Zoom in</button>
<button id="zoom-out">Zoom out</button>
</div>
Use JavaScript to set classnames, but let CSS completely handle the transitions and trigger GPU acceleration.
I would suggest using the onclick
HTML event attribute, to set triggers for two functions, zoomIn
and zoomOut
.
<div id="zoom-container">
<img src="http://placehold.it/1000x1500" />
</div>
<div id="zoom-toolbar">
<button id="zoom-in" onclick="zoomIn()">Zoom in</button>
<button id="zoom-out" onclick="zoomOut()">Zoom out</button>
</div>
You now have two functions, that set desired CSS classnames.
function zoomIn() {
var element = document.getElementById("zoom-container");
element.className = 'zoomed-in';
};
function zoomOut() {
var element = document.getElementById("zoom-container");
element.className = 'zoomed-out';
};
To achieve the desired animation, the CSS can now be much simpler as well.
#zoom-toolbar {
position: absolute;
top: 0;
}
#zoom-container.zoomed-out {
transition: transform 0.3s ease-in-out;
transform: matrix(0.2, 0, 0, 0.2, 0, 0);
}
#zoom-container.zoomed-in {
transition: transform 0.3s ease-in-out;
transform: matrix(2, 0, 0, 2, 0, 0);
}
From there, you can introduce additional CSS and test whether subsequent changes are breaking.
I've created a CodePen example to demonstrate.
A good article on smooth CSS transitions is here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With