Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Chrome is unable to apply opacity transition on a 3d transformed element

I have the following markup:

<div class="cube trigger cuberotate">
    <div class="face init f z"></div>
    <div class="face init l y"></div>
    <div class="face init b z"></div>
    <div class="face init r y"></div>
    <div class="face init u x"></div>
    <div class="face init d x"></div>
</div>

Which resembles a 3d cube, every face is rotated and translated onto their proper position and I let the cube rotate using an animation on the faces' parent.

Here's the related css of it:

.cube {
  position: absolute;
  cursor: pointer;

  width: 120px;
  height: 120px;

  top: 0;
  left: 0;

  transform-origin: 50% 50%;
  transform-style: preserve-3d;
}

.face {
  position: absolute;

  width: 120px;
  height: 120px;

  border: 0px solid #fff;
  background: #c82222;

  transform-origin: 50% 50%;

  opacity: 1;
  padding: 0px;

  -webkit-touch-callout: none;
  user-select: none;

  transition: all 0.5s ease-out;    
}

I wanted to make the cube appear one face at time on document ready, so I just threw in some javascript, basically an interval every 500ms which simply removes the .init class which overrides the opacity: 1 value on the .face class.

(function($) {
  'use strict';

  // Some selectors and shit...
  var $face = $('.face').first(),
      speed = 500,
      timer = null;

  $(document).ready(function(){
    // Start showing faces
    timer = window.setInterval(function(){
      var $next = $face.next();

      $face.removeClass('init');

      if(!$next.hasClass('face')) {
        window.clearInterval(timer);
      }

      $face = $next;
    }, speed);

  });


})(jQuery);


// And the additional CSS below
.face.init {
  opacity: 0;
}

In an ideal world this code should work, however I am facing a problem on Google Chrome the opacity doesn't transition back to 1 after the class is removed keeping the cube completely invisible. If you right click and inspect it becomes visible again.

Curiously on Safari, which is also a webkit-based browser this does not happen at all and the faces show one at time as they are supposed to do.

I tried to use both .animate() from jquery and also tried the jquery plugin transit

  • Now, Safari and Chrome aren't supposed to behave in the same way, or are there major differences under the hood despite the rendering engine being the same?
  • Is it something I did wrong?
  • There's a workaround for this?

Here's my pen: http://codepen.io/luigimannoni/pen/FstKG/

Thanks

Update:

I have tried obviously on Chrome on my Mac and also on Windows 7 and they both behave the same way (different machines also)

Also tried Firefox which works seamlessly like Safari apart from the rotating animation which isn't happening (but I kept Firefox out of consideration as it's a different browser).

Additional update:

Chrome on mobile devices (both iOS and Android) are working and behaving like Safari on desktop.

Another Update:

After playing around around I have found probably it's a browser bug, Chrome Canary works fine as expected. I posted this on facebook where I've got a couple of good workarounds from a developer, which I found quite creative.

The first one involved in have a rgba() background-color and make the alpha change instead of having the transition on the opacity: http://codepen.io/anon/pen/IjsBL

The second one involved a bit of javascript coding, forcing the browser repaint the faces at each frame: http://codepen.io/anon/pen/Hofzb

I am starting a bounty to see what stackoverflow can do here!

like image 859
MacK Avatar asked Apr 29 '14 15:04

MacK


Video Answer


2 Answers

You could try to assign 0.01 to opacity.

.face.init {
  opacity: 0.01;
}
like image 97
emn178 Avatar answered Sep 30 '22 17:09

emn178


Looks like it is a documented regression bug

For the difference in Safari and Chrome, you should know that Chrome uses Blink(a webkit fork) as its rendering engine since version 28.

like image 38
Gabriele Petrioli Avatar answered Sep 30 '22 18:09

Gabriele Petrioli