How to animate backdrop-filter? - css

I faced the issue with low fps while using backdrop-filter and transition on the same component.
.modal-background {
// some styles
backdrop-filter: blur(2px)
transition: all .15s linear
}
As simple as that. The animation is glitchy :( But if I comment out backdrop-filter line, things are getting better.

You can achieve a different but comparable effect by instead animating the backdrop-filter's opacity() like so:
.bg {
transition: backdrop-filter 0.2s;
backdrop-filter: blur(4px) opacity(0);
}
.bg.show {
backdrop-filter: blur(4px) opacity(1);
}
I have seen some minor graphical glitches when doing this in Chromium. But on the plus side, I've also found this approach to be much more performant than the alternative suggestion of animating a (non-backdrop) filter property's blur(). There's a trade-off to be made between responsiveness and graphical accuracy.

I believe, it's a very new property and can't be animated properly yet. You can always restructure something to make work this one instead: filter: blur(7px);

As Roman mentions
its a very new property. Until it got optimized, you have to look for alternatives. More specifically on "filter: blur(6px)":
<div id="root"/>
<div id="modal"/>
If you are trying to apply a backdrop on modal, don't. Go put some listeners on parent (#root) element checks if it has that child modal, apply filter on "#root" and enjoy.

Related

AngularJS Animate - Transition To Different Background Color Only Works One Way

I use the following CSS to animate the change in background color for a div:
#availability-button.red-add, #availability-button.red-remove, #availability-button.green-add, #availability-button.green-remove{
transition: background-color 2000ms linear;
}
#availability-button.red, #availability-button.red-add, #availability-button.red-add-active{
background-color: #c21807;
}
#availability-button.green, #availability-button.green-add, #availability-button.green-add-active{
background-color: #68af28;
}
The above works only one way - when you transition from green to red.
What is causing this?
Fiddle
You only need #availability-button.red and #availability-button.green. The animation life-cycle classes like red-add and red-remove are useful if you're using animations, but for transitions can be tricky since you're just transitioning the change in properties between selectors.
In this case, it seems like multiple selectors are matched in the red-* and green-* groups, which causes undefined behavior in how the transition is completed.
Updated Fiddle

MS Edge CSS transition flickering

I've noticed a strange issue with CSS transitions in MS Edge.
Basically if you have a transition, between hover states for example, but the styles defined for those hover states are over-written in the CSS cascade, Edge will switch to the over-written styling for the duration of the transition, then switch back.
The issue is described fairly well here too:
https://www.webmasterworld.com/css/4791912.htm
I have also created a pen demonstrating the problem:
http://codepen.io/powerbored/pen/OWqXRw
a {
transition: all 2s ease-in;
color: orange;
}
a div {
color: lightblue;
// displays in light blue in all browsers except during transitions in Edge
}
a:hover {
color: red;
}
I know Edge isn't exactly a great browser but I what I'd really like to see is an explanation of what is actually happening here and why it could be happening.
There's something about transition-property: all that's causing the descendant element to inherit the animated value during the transition, instead of keeping its specified value indefinitely, in Microsoft Edge. This appears to be so specific to Microsoft Edge's implementation of CSS transitions, that even Internet Explorer behaves correctly, and it only occurs when transition-property is all — if you specify only the properties that need transitioning, Microsoft Edge behaves correctly.
That's all I can tell you. Well, that, and the obvious fact that this is incorrect behavior.

CSS Blur elements selectively

I'm trying to get a smart looking modal popup by using a blur filter e.g. -webkit-filter: blur(10px);. This works great when I apply the blur to a specific element like this:
body.modal_open #main { -webkit-filter: blur(10px); }
However, if my modal popup is within #main, the filter is applied to that element too, as you'd expect.
My question is, would there be a way to tell the browser not to apply the filter to a specific element? I tried to add:
body.modal_open .modal_window { -webkit-filter: blur(0px); }
But that didn't work. Is there a way to do this based on the z-index of an element, or something similar? I can't find any CSS to select elements based on z-index, so I'm guessing that's not possible.
Is the only option to bring all the modal windows out of the #main container? Or are there any more ideas out there?
Many thanks in advance!
For anybody looking for an answer to this, I never found a way to use z-index or anything similar to apply the filter: blur to specific layers. However, by using backdrop filter:
-webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
I managed to achieve the desired effect. Note that this method is only supported in Safari and Chrome at the moment, but hopefully more browsers will support this in the coming months and years, because it looks pretty great!

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!
You could try to assign 0.01 to opacity.
.face.init {
opacity: 0.01;
}
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.
This problem was brought to my attention on Facebook. As requested, I'll post my initial thought process.
Initial Thought: Aggressive GPU-use / hardware-acceleration
Initially, I thought Chrome was seeing the 3D transforms in the keyframes-animation and hardware accelerating the animation -- which is what we expect -- but then when trying to interfere via JavaScript, was not interrupting the GPU execution.
Workaround 1:
Use a separate keyframes-animation first to animate opacity and rotation at the same time and then start your current animation, animating just the rotation to continue infinitely.
See this codepen.
Workaround 2:
I then immediately realised he wanted each face to fade in independently, in sequence. Knowing javascript wasn't interrupting the CSS animation, I tried animating the .faces using a keyframes-animation. Using an animation-delay to stagger each face.
See this codepen. But for some reason, it stops after the first face :(
Workaround 3:
At this point I was clutching at straws, and thought to toggle perspective: 500px to perspective: 501px, within a requestAnimationFrame callback, in hopes it would break hardware-acceleration, but no luck.
Workaround 3.1:
But having used a requestAnimationFrame, I decided I could just perform the first rotation and intended fade-in's using javascript and then trigger the CSS animation after.
See this codepen. This was the intended visual.
Workaround 4:
While anyone else would have been done and dusted, still using javascript bugged me to hell -- as much as I love JS, CSS is just smoother (right now).
Then it hit me! I could just animate background-color: rgba(...); rather than opacity: ...;.
And so finially, I had the intended animation using pure CSS.
See this codepen.
This was based on Workaround 2. I had to create 3 extra animations: one for each colour .face identified with classes .x, .y and .z.
I used SCSS to make it clear I was using the original colours (hence the rgba(#c82222,0);) and also to save myself the ball-ache of having to convert that to RGB values anyway.
Hope that helps anyone :)
Please try to initiate opacity from zero with bit more transition values.
CSS position relative fixes the problem:
.fullscreen {
position: relative;
http://codepen.io/anon/pen/oekyt
It reminds me the of old IE bugs then you have to set
*zoom: 1;
for element. It made element "really rendered", not just "light rendered".

Safari blurs strange bugs

I'm currently redesigning one of my sites. I using the CSS blur filter:
.blur {
blur(5px);
-webkit-filter: blur(5px);
}
and some CSS animation
.animate-blur {
transition: 0.45s all ease-out;
}
to animate the turn on and off these blur styles.
The turning is done by this script:
jQuery(function(){
jQuery("article").hover(function(){
jQuery("article").not(this).addClass("blur");
},function(){
jQuery("article").removeClass("blur");
})
jQuery(".sitename").hover(function(){
jQuery("article").addClass("blur");
jQuery("#background-top,#background-bottom").removeClass("blur");
},function(){
jQuery("article").removeClass("blur");
jQuery("#background-top,#background-bottom").addClass("blur");
})
});
That worked all well until I upgraded to Mavericks and the new Safari. Now sometimes the articles completely disappear or there is a strange shadow behind the text.
So my question is. (Can you reproduce this? And...) Does anybody know if I can fix this?
As StopLogic mentioned, the will-change CSS property fixes this bug. Use will-change: filter on the blurred element.
In addition to the solutions proposed by the author, the css property "will-change" can help you. It allows you to attract additional system resources to play the animation.
I resolved my problem, although I'm not quite sure how I did. I made some changes to the mark up (I'm not sure which of these solved the problem):
no longer using the bootstrap grid, now no position style is applied to the parent div
added overflow: hidden; to the parent div
removed a clearfix out of the affected divs
floating the sidebar (even I don't think this is relevant)
...in the hope this will probably help somebody.

Resources