Firefox heavy lag when using transform: translateX() in a transition - css

What I have is an offcanvas nav that moves the entire page once opened.
It looks like this:
.offcanvas {
position: fixed;
padding-left: calc($unit * 8);
z-index: 3;
height: 100%;
width: 420px;
top: 0;
right: 0;
background: $color-secondary;
overflow-x: hidden;
transform: translateX(420px);
will-change: transform;
transition: transform .2s ease-in-out;
}
When a button is clicked it gets a class modifier through jquery which moves it inside the window:
&--opened {
will-change: transform;
transform: translateX(0);
}
Content is wrapped in main which also gets moved once the nav is opened:
.main {
will-change: transform;
transition: transform .2s ease-in-out;
&__moved {
will-change: transform;
transform: translateX(-420px);
}
}
It works just fine in every major browser except Firefox (54.0.1), tested on Windows and OSX. The transition is extremely laggy both when opening and closing the menu. I tried adding will-change: transform; but the issue is still there. I've tried using translate3d and left/right, but those didn't help.
Has anyone experienced these issues and what have you done to solve them?
Thanks!

Related

Mobile Menu is being stretched by Firefox and Safari

I have a mobile menu that is supposed to disappear when users scroll. I did work out all fine, but now I have a problem that boggles my mind. I am using headroom.js to make the menu disappear and reappear. For the headroom element, I have defined some css classes. The whole thing is embedded in a Joomla Template.
Now, on Firefox Mobile as well as Safari (iPhone Browser), I get this weird behavior that header classes are stretched to 1500px width, a value that is never defined anywhere in my css files. When I let Chrome do a simulation of Mobile Viewport, everything works out the way it should.
My html:
…
<header class="headroom" id="main-header-navi-headroom">
<nav id="nav-main" class="navbar navbar-default" style=" background-color: #fff;">
<div class="navbar-header">
<!-- a button to toggle navbar-collapse goes here -->
</div>
<div class="collapse navbar-collapse" id="collapsible-menu">
<!-- all my menu points are being summoned here -->
</div>
</nav>
</header>
…
My template.css
.headroom {
position: sticky;
top: 50px;
left: 0;
right: 0;
transition: all .6s ease-in-out !important;
z-index: 900;
}
.headroom--unpinned {top: -150px;}
.headroom--pinned {top: 50px;}
My template_responsive.css:
#media (max-width: 1179px) {
.headroom {
position: fixed;
top: 50px;
left: 0;
right: 0;
margin-top: 0;
max-height: calc(var(--vh, 1vh) * 100);
overflow-y: auto;
-webkit-transition: -webkit-transform 300ms ease-out;
transition: -webkit-transform 300ms ease-out;
-o-transition: -o-transform 300ms ease-out;
transition: transform 300ms ease-out;
transition: transform 300ms ease-out, -webkit-transform 300ms ease-out, -o-transform 300ms ease-out;
will-change: transform;
z-index: 9998;
}
.headroom--pinned {
top: 50px;
position: sticky;
}
.headroom--frozen {
top: 0 !important;
}
a.reduced-z {
z-index: 9997 !important;
}
.headroom--unpinned {
-webkit-transform: translateY(-100%);
-o-transform: translateY(-100%);
transform: translateY(-100%);
top: 0;
}
}
What I've tried: I tried to add a max-width: 100%; property to the headroom class, to no avail. Also, in my template there is another <nav> element that has max-width set to 100%, but it gets still rendered to a width of 1500 pixels.
What confuses me are two things:
There is no class or identifier in my whole css that has their width set to 1500px. I first thought that maybe that prop somehow oozed to my menu element. But since there is none, I do not understand how Firefox comes up with that width.
If I just scale a regular Firefox window on my Desktop Computer, everything works fine. Just the mobile preview or an actual mobile device produce the hiccups described.
Any ideas on why that problem occurs and how to fix it?

Can't use scrollbar with particles.js set at fixed position

We have particles.js loaded and cannot use the scrollbar on wordpress website. We need this to work with full height and full width. Please see html code below in link.
Our html code" : website link: http://www.tcnarch.co.za/about
We have tried disabling plugins and checked dev tools for errors and there are none. Have also tried overflow-x: auto and also removed the height: 100% atribute from css but to no avail. Please help we have tried everything to our knowledge. Thank you
#particles-js {
position:fixed;
overflow-y:scroll;
overflow-x:hidden;
top: 0;
left: 0;
right: 0;
width: 100%;
}
#particles-js canvas {
display: block;
vertical-align: bottom;
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
opacity: 1;
-webkit-transition: opacity .8s ease, -webkit-transform 1.4s ease;
transition: opacity .8s ease, transform 1.4s ease
}
Problem has been resolved. Fixed this by adding right: 10px suppose it's not the ideal solution but the scrollbar now works also what might help others in future is setting pointer events to all.

css animation doesn't display properly in edge

So I'm having some trouble with a css animation "underline from center" to be precise.
It displays properly in every browser except edge.
I'm getting small dots underneath the links where the animation displays itself (see picture)
dots underneath links in navbar
enter code here`
.hvr-underline-from-center {
display: inline-block;
vertical-align: middle;
-webkit-transform: perspective(1px) translateZ(0);
transform: perspective(1px) translateZ(0);
box-shadow: 0 0 1px transparent;
position: relative;
overflow: hidden;
}
.hvr-underline-from-center:before {
content: "";
position: absolute;
z-index: -1;
left: 50%;
right: 50%;
bottom: 0;
background: #b80c0c;
height: 4px;
-webkit-transition-property: left, right;
transition-property: left, right;
-webkit-transition-duration: 0.1s;
transition-duration: 0.1s;
-webkit-transition-timing-function: ease-out;
transition-timing-function: ease-out;
}
.hvr-underline-from-center:hover:before, .hvr-underline-from-center:focus:before, .hvr-underline-from-center:active:before {
left: 0;
right: 0;
}
enter code here`
Thanks for the help
This is not an Edge issue. It works on Edge, depending on the text (and maybe also the density of your screen). This type of thing also happens sometime on Firefox and even Chrome.
It's a rounding error : that's why on your picture you've got dot below some menu items but not all.
Try adding a visibility hidden, it'll do the trick.
Also for this type of thing animating transform: scaleX if better performance wise than animating an item width, (and an item with a scaleX(0) will always have a length of 0 no rounding error can happen here)

Transform scale working on Chrome but not on Firefox

Once I start animating, on Chrome I get a ripple effect. My circle transform scales up. On Firefox, that exact same animation is ignored for some reason.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
.ripple {
animation: ripple 1s 0.5s;
transform: scale(20) !important;
/*Duration - delay */
transition: transform 0s 1s !important;
}
.animate {
transform: rotate(90deg) !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
CodePen Demo
Before I start explaining the problem with your code, here is a word of caution - Do not use transitions and animations together. They generally end up causing problems like the one faced here.
When an animation is specified on an element, it will take complete control over the properties that are being animated unless there is a rule with !important setting. If !important setting is used then that rule takes precedence over the animation. (but unfortunately Chrome and Firefox seem to be handling this case differently).
As per W3C Spec:
CSS Animations affect computed property values. During the execution of an animation, the computed value for a property is controlled by the animation. This overrides the value specified in the normal styling system. Animations override all normal rules, but are overriden by !important rules.
emphasis is mine
In your code, there were two problems and they are as follows:
Within .ripple selector, you were specifying the transition-duration as 0s, which means, there is no transition at all and that the change of transform is an instant one. As explained in the W3C Spec, Firefox seems to be (correctly) giving the control to the rule with !important setting (that is, the transform and transition within .ripple selector) and so it transitions the state change immediately after the specified 1s delay+. Chrome lets animation take control and thus produces the effect you are looking for.
Firefox seems to animate the element quicker than Chrome does and so while a duration of 1s is enough for the animation in Chrome, FF needs it to be 2s to be slower and show the effect.
+ - You can further verify this by removing the !important settings on the rules. Once !important is removed, the animation would take control.
$("#animate").click(function() {
$("#square").toggleClass("animate");
$("#fab").toggleClass("ripple");
});
#keyframes ripple {
from {
transform: scale(0)
}
to {
transform: scale(20)
}
}
#square {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
border: 1px solid red;
transition: background 0.1s linear 0.6s, transform 1s;
transform: rotate(0deg);
}
#fab {
position: absolute;
width: 56px;
height: 56px;
border-radius: 50%;
background: #4FB5AB;
top: 122px;
right: 0;
transform: scale(1);
transition: transform 1s;
}
#fab.ripple {
animation: ripple 2s 1s;
transform: scale(20);
/*Duration - delay */
transition: transform 1s 1s;
}
#square.animate {
transform: rotate(90deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="square">
<div id="fab"></div>
</div>
<br />
<button id="animate">animate</button>
Finally, please do not use !important unless it is mandatory. Instead just make the selector more specific. In the snippet, I have made it more specific by using the #id.class format.

Keyframe CSS animation overwrites hover transition

I am afraid there are similar questions to this but I didn’t found a concrete solution, so I created a fiddle:
http://jsfiddle.net/Garavani/yrnjaf69/2/
<div class= "category_item">
<div class= "cat_button">
<span class="title_cat">TEXT</span>
</div>
</div>
CSS:
.category_item {
position: absolute;
background-color: #999;
top: 100px;
left: 50px;
width: 200px;
height: 200px;
/* seems to be overwriten by animation keyframes */
-webkit-transition: -webkit-transform 0.215s ease-in-out;
transition: transform 0.215s ease-in-out;
cursor: pointer;
}
.category_item:hover {
-webkit-animation-name: easeBack;
animation-name: easeBack;
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
#-webkit-keyframes easeBack {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
50% {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
}
100% {
-webkit-transform: translateY(-30px);
transform: translateY(-30px);
}
}
.cat_button {
position: absolute;
width: 200px;
height: 55px;
bottom: 0;
border: 2px solid #fff;
color: #fff;
-webkit-transition: background 0.215s ease-in-out, border 0.215s ease-in-out, color 0.215s ease-in-out;
transition: background 0.215s ease-in-out, border 0.215s ease-in-out, color 0.215s ease-in-out;
}
.category_item:hover .cat_button {
background: #fff;
border-color: #fff;
color: #511c5b;
}
In this (simplified) animation everything works fine except for when the mouse leaves the entire box. The animation starts from it original state, but abruptly.
The basic transition time (and ease) is ignored because it seems the keyframes have higher importance and overwrite it.
What I need is the keyframe animation triggering AND when the mouse leaves it should turn back to the original state smoothly.
Is there a solution for this
1) in pure CSS
2) maybe with some little javascript only?
Thanks in advance for help and ideas!
EDIT:
After implementing the solution offered kindly by Toni this is the correct fiddle:
http://jsfiddle.net/yrnjaf69/40/
Thanks again Toni!
EDIT 2:
Sadly, yet, there is one question left. The part with the keyframes is not executed on Firefox even though I added all the -moz- vendors, too, in this fiddle:
http://jsfiddle.net/dr6Ld0wL/1/
Why?
PS: As far as I tested for now it works even in Opera (Beta). Only browser resisting is Firefox
EDIT 3:
The correct (working) code is now in this fiddle:
http://jsfiddle.net/dr6Ld0wL/16/
The keyframes also need to be explicitly divided in vendor prefixes. Jesus Christ. Those prefixes…
Here is a jsfiddle that achieves this.
.demo-hover {
position: relative;
margin: 100px;
animation: complexProcessReversed 2s ease-in forwards;
width: 160px;
height: 160px;
background-color: #88d;
}
.demo-hover:hover {
animation: complexProcess 2s ease-in forwards;
width: 100px;
height: 100px;
background-color: #732;
}
#keyframes complexProcess {
/* keyframes */
}
#keyframes complexProcessReversed {
/* keyframes (opposite) */
}
The animation out is assigned in the css in the main class, then the hover state kicks in on hover and css re-applies the original class properties on unhover.
The animation does trigger backwards on page load, so you might like to think of tweaking your animation to take this into account, like this example, pinched from this answer. Alternatively, use javascript (or jquery), like this example where the animations are triggered by adding and removing classes to the target using jquery:
JavaScript
$('.demo-hover').hover(
function() {
// mouse in
$(this).removeClass('forwards--reversed').addClass('forwards');
},
function() {
// mouse out
$(this).removeClass('forwards').addClass('forwards--reversed');
}
);
CSS
.forwards {
animation: complexProcess 2s ease-in forwards;
width: 100px;
height: 100px;
background-color: #732;
}
.forwards--reversed {
animation: complexProcessReversed 2s ease-in forwards;
width: 160px;
height: 160px;
background-color: #88d;
}
Also, I'd use #keyframe or transition. Use transition if you just need a simple even change from n to m but when things are more complex, such as one thing changing evenly over 100% but another thing not starting until 50% off the animation has played, then use a #keyframe
Using both will cause confusion, especially if you're trying to animate the same properties.
Finally css vendor prefixes are required

Resources