CSS animation scale transform starts blurry in Firefox - css

(Note: This was asked [exactly] 1½ years ago and had [exactly] zero activity... I'm apparently having the same issue so hopefully OP #Jaffa won't mind me piggybacking in it, and slapping a bounty on it to [hopefully] generate some interest!)
The OP's original question is below, and my added issue & examples is below that.
 
[Original Question:]
I am trying to animate a zoom out effect on an SVG. I have gotten it working, but the first frame, which is scaled to 30, is blurry/pixelated in Firefox.
Firefox:
Chrome:
I do not see the same issue in Chrome or Edge. The initial frame is crisp as I would expect being an SVG.
html,
body {
margin: 0px;
padding: 0px;
}
.wrapper {
padding: 50px 50px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
margin-top: 80px;
}
.img_zoom {
width: 400px;
height: 500px;
margin: 2em auto 2em auto;
overflow: hidden;
}
.zoom {
width: 100%;
height: 100%;
background-position: center;
background-size: cover;
animation: zoom 5s ease-in-out 4s 1 normal forwards;
transform: translate(3400px, -3600px) scale(30);
}
#keyframes zoom {
to {
margin-left: 0;
transform: translate(0px, 0px) scale(0.7);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="wrapper">
<div class="img_zoom">
<div class="zoom"><img src="https://flexion.tech/images/box-con.svg"></div>
</div>
</div>
</body>
</html>
Code pen is here for review:
https://codepen.io/jaffa80/pen/KKpxgeQ
Any ideas how I can fix the blurry issue in Firefox?
Another problem i am having is if I remove margin-left:0 from the #keyframe to, things stop working. Any pointers on this would be appreciated also.
 
EDIT:
I have a rounded div container containing several elements to position text within the circle. I need the circle to "grow" when the user gets to it, so I figured I'd use transform:scale() with a transition or animation.
However, only in Firefox, the text is blurry until the transition (or animation) is complete. Oddly, the border of the circle remains perfectly sharp (I think?).
Thinking maybe it needed a moment to pre-render, I've tried delaying with setTimeout alone, as well as combining with events (open & DOMContentLoaded) and with requestAnimationFrame. I also tried using css animation instead of transition.
Nothing seems to make a difference in Firefox, yet Chrome and Edge seem fine. Is there a prefix that I don't know about, or is this maybe a rendering bug in Firefox?
My MCSE is the snippet below:
setTimeout(function(){
circ.classList.remove('shrunk');
},500);
body{ font-family:'fira code'; font-size:20px; }
#circ{ position:relative; border:3px solid blue; border-radius:50%; text-align:center; white-space: nowrap; transition:transform 1000ms; }
#circ span{ position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); }
.shrunk{ transform:scale(0.1); }
<div class='shrunk' id='circ' style='width:336px; height:336px;'>
<span>Lorem<br>Ipsum is simply<br>dummy text of the<br>printing and typesetting<br>industry. Lorem Ipsum has<br>been the industry's<br>standard dummy text ever<br>since the 1500s, when an<br>unknown printer took a<br>galley of type and<br>scrambled it to make<br>a type specimen<br>book.</span>
</div>
Any suggestions or workarounds?

I can only guess why this happens. Firefox is taking a snapshot before starting the animation / transition (by adding the class to the tag) and then when the transition ends. Maybe Firefox is taking more than two snapshots. But as you can see in the snippet below, the animation label is still blurred and waiting for when the animation is finished; the blur then disappears immediately. I think Firefox does this optimization for better performance.
The CSS property will-change also does not solve this problem if reset to initial .
setTimeout(function() {
circ.classList.add('shrunk');
}, 2000);
body {
display: flex;
flex-flow: column;
font-family: 'fira code';
gap: 2rem;
}
.circles,
.titles {
width: 100%;
display: flex;
gap: 2rem;
}
h4 {
width: 105px;
font-size: 0.8rem;
}
#circ,
#circ2,
#circ3,
#circ4 {
width: 100px;
height: 100px;
position: relative;
border: 3px solid blue;
border-radius: 50%;
text-align: center;
word-break: break-all;
}
#circ {
transition: transform 1000ms;
transform: scale(0.1);
}
#circ2 {
animation: forwardAnim 5s linear forwards;
}
#circ3 {
animation: forwardAnim 5s linear forwards;
backface-visibility: hidden;
}
#circ4 {
animation: forwardAnim 5s linear forwards;
transform-style: preserve-3d;
}
#circ span,
#circ2 span,
#circ3 span,
#circ4 span {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
#circ.shrunk {
transform: scale(1);
}
#keyframes forwardAnim {
0% {
transform: scale(0.1);
}
45% {
transform: scale(0.1);
}
50% {
transform: scale(1);
}
100% {
transform: scale(1);
}
}
<div class="circles">
<div id="circ">
<span>This is my text!</span>
</div>
<div id="circ2">
<span>This is my text!</span>
</div>
<div id="circ3">
<span>This is my text!</span>
</div>
<div id="circ4">
<span>This is my text!</span>
</div>
</div>
<div class="titles">
<h4>Add class with transition</h4>
<h4>Animation</h4>
<h4>Animation with backface-visibility: hidden</h4>
<h4>Animation with transform-style: preserve-3d</h4>
</div>
To avoid this you could use backface-visibility: hidden;as #nullptr mentions above, or transform-style: preserve-3d;* for a smoother transition.
setTimeout(function() {
circ.classList.remove('shrunk');
}, 500);
setTimeout(function() {
circ2.classList.remove('shrunk');
}, 500);
body {
display: flex;
flex-flow: column;
font-family: 'fira code';
gap: 2rem;
font-size: 0.9rem;
}
.circles,
.titles {
width: 100%;
display: flex;
gap: 2rem;
}
h4 {
width: 255px;
font-size: 0.8rem;
text-align: center;
}
#circ,
#circ2 {
width: 250px;
height: 250px;
position: relative;
border: 3px solid blue;
border-radius: 50%;
text-align: center;
white-space: nowrap;
transition: transform 1000ms;
}
#circ {
backface-visibility: hidden;
}
#circ2 {
transform-style: preserve-3d;
}
#circ span,
#circ2 span {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.shrunk {
transform: scale(0.1);
}
<div class="circles">
<div class="shrunk" id="circ">
<span>Lorem<br />Ipsum is simply<br />dummy text of the<br />printing and
typesetting<br />industry. Lorem Ipsum has<br />been the industry's<br />standard
dummy text ever<br />since the 1500s, when an<br />unknown printer
took a<br />galley of type and<br />scrambled it to make<br />a type
specimen<br />book.</span
>
</div>
<div class="shrunk" id="circ2">
<span
>Lorem<br />Ipsum is simply<br />dummy text of the<br />printing and
typesetting<br />industry. Lorem Ipsum has<br />been the industry's<br />standard
dummy text ever<br />since the 1500s, when an<br />unknown printer
took a<br />galley of type and<br />scrambled it to make<br />a type
specimen<br />book.</span
>
</div>
</div>
<div class="titles">
<h4>backface-visibility: hidden;</h4>
<h4>transform-style: preserve-3d;</h4>
</div>
Another way to avoid blurred content inside the circle is to remove position: absolute if it's not critical, and instead align content with display: flex on the parent element.
setTimeout(function() {
circ.classList.remove('shrunk');
}, 500);
body {
font-family: 'fira code';
font-size: 20px;
}
#circ {
display: flex;
justify-content: center;
align-items: center;
position: relative;
border: 3px solid blue;
border-radius: 50%;
text-align: center;
white-space: nowrap;
transition: transform 1000ms;
}
.shrunk {
transform: scale(0.1);
}
<div class="shrunk" id="circ" style="width: 336px; height: 336px">
<span>Lorem<br />Ipsum is simply<br />dummy text of the<br />printing and
typesetting<br />industry. Lorem Ipsum has<br />been the industry's<br />standard
dummy text ever<br />since the 1500s, when an<br />unknown printer took
a<br />galley of type and<br />scrambled it to make<br />a type
specimen<br />book.</span
>
</div>

I ran into this issue a few years back, although I think I had it on chrome and not Firefox. But this seems to solve the issue in Firefox too.
Add backface-visibility: hidden to your transforming component. This will make it so that only the front face of the element is animated, instead of both the front and the back faces.
setTimeout(function(){
circ.classList.remove('shrunk');
},500);
body{ font-family:'fira code'; font-size:20px; }
#circ{ position:relative; border:3px solid blue; border-radius:50%; text-align:center; white-space: nowrap; transition:transform 1000ms; backface-visibility: hidden; }
#circ span{ position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); }
.shrunk{ transform:scale(0.1); }
<div class='shrunk' id='circ' style='width:336px; height:336px;'>
<span>Lorem<br>Ipsum is simply<br>dummy text of the<br>printing and typesetting<br>industry. Lorem Ipsum has<br>been the industry's<br>standard dummy text ever<br>since the 1500s, when an<br>unknown printer took a<br>galley of type and<br>scrambled it to make<br>a type specimen<br>book.</span>
</div>
As to why it works, I really have no idea. But do try it and let me know it if works for you.

Related

How to make an element disappear and stay gone after hovering over it?

So here is my code...
I understand how to make the text disappear by making it transparent but i want it to stay gone after hovering over it so it doesnt come back - how do I accomplish this?
.disappear {
margin-top: 60px;
text-align: center;
transition: all 5s ease .3s;
font-family: Bungee Spice;
}
.disappear:hover {
color: transparent;
}
you need to use onmouseover and remove() like this
function bye() {
const dis = document.getElementById("dis");
dis.remove();
}
* {
padding: 0;
margin: 0;
/* border: 1px solid red; */
overflow-x: hidden;
}
div {
height: 50vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
font-size: xx-large;
overflow: auto;
background: lightblue;
}
<div class="div">
<h2 onmouseover="bye()" id="dis">will go on hover</h2>
</div>
I don't think it's possible to make it run smoothly with pure CSS, so far, this is what I think is close to what you want to accomplish. So before hover, the animation to make it gone is already set, but the animation is not running yet, the animation will run only if the element is hovered. The problem here is that when it's hovered then it's unhovered before it's gone, the element will be half gone as the animation is paused.
.container {
width: 100%;
height: 800px;
background: #dddddd;
}
.disappear {
margin-top: 60px;
text-align: center;
font-family: Bungee Spice;
background: yellow;
animation: example 5s linear forwards;
animation-play-state: paused;
}
.disappear:hover {
animation-play-state: running;
}
#keyframes example {
from {opacity: 1}
to {opacity: 0}
}
<div class="container">
not disappear
<div class="disappear">
DISAPPEAR
</div>
</div>
The better way would be to use javascript and use onmouseover to add the animation instead of using :hover, the difference is that when you onmouseout, the function is still executed (the animation persists). This is with JS:
function fade(elm) {
elm.style.animation = "example 5s linear forwards";
}
.container {
width: 100%;
height: 800px;
background: #dddddd;
}
.disappear {
margin-top: 60px;
text-align: center;
font-family: Bungee Spice;
background: yellow;
}
#keyframes example {
from {
opacity: 1
}
to {
opacity: 0
}
}
<div class="container">
not disappear
<div class="disappear" onmouseover="fade(this)">
DISAPPEAR
</div>
</div>

How to remove bluriness of fonts and 'lock in' effect when combining transform: scale with transition: transform?

When combining transform:scale with transition:scale, the animation has two problems, and the problems are similar in Firefox and Chrome.
1) The font/border is extremely blurry during the transition
2) About 0.3s after the transition, the browser 'locks-in' the new scale. It is hard to explain but you will clearly see from the example.
<html>
<body>
<div id="block">
<div class="text">123123</div>
<div class="text">123123</div>
<div class="text">123123</div>
</div>
</body>
</html>
<style>
#block {
margin-top: 100px;
margin-left: 100px;
width: 80%;
height: 300px;
display: flex;
flex-direction: column;
}
.text {
margin: auto;
width: 250px;
font-size: 25px;
transition: transform 0.5s;
border: 1px solid blue;
cursor: pointer;
}
.text:hover {
transform: scale(1.5);
}
</style>
I've tried adding backface-visibility: hidden but this has no effect in Firefox and makes the end of the transition permanently blurred.
Also tried using transform-origin: 100% 0, but no avail.
Take a look at the Codepen:
https://codepen.io/vibonaaci/pen/LKqrPX
Any ideas? If you use the effect on some more stylized elements, the issue really hurts the eyes.

Why does transitioning the transform scale of an element cause some children elements to jitter

I'm trying to scale a card element when a user hovers over it by using only the transform of the card.
However I'm noticing that in a lot of cases when the card is hovered, the child elements will jitter in some way, i.e. some letters jumping up in height for a split second.
Here's an example of the effect that i keep experiencing.
https://codepen.io/andrewmumblebee/pen/OrBGzm
You'll notice that the S of TEST, jumps in height during the transition.
I've managed to get a completely smooth transition working before, but this was absolutely positioned.
https://codepen.io/andrewmumblebee/pen/REevdB
After removing the absolute positioning, etc. it still is smooth, so I'm assuming it's something to do with having multiple child elements.
Here's the important code, the full code can be found on the first Codepen link.
<div class="container">
<div class="card">
<img src="https://upload.wikimedia.org/wikipedia/commons/6/6a/Godot_icon.svg" />
<div class="text">
test
</div>
</div>
</div>
body {
background: #478cbf;
}
.container {
margin: 50px auto;
width: 200px;
}
img {
width: 200px;
height: 200px;
}
.card {
width: 250px;
height: 300px;
background: linear-gradient(#444, #333);
transition: all 0.3s;
text-align: center;
padding: 30px;
will-change: transform;
transform: scale(1);
box-shadow: rgba(#000000, 0.2) 5px 5px 10px;
}
.text {
font-size: 50px;
text-transform: uppercase;
color: white;
font-family: arial;
will-change: transform;
text-align: center;
}
.card:hover {
transform: scale(1.1);
box-shadow: rgba(#000000, 0.2) 10px 10px 10px;
}

Is it possible to recreate marquee using CSS only?

I have a requirement that can be solved using a marquee
.ticker {
white-space: no-wrap;
}
.item {
display: inline-block;
cursor: pointer;
}
<marquee class="ticker" onmouseover="this.stop()" onmouseout="this.start()">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
</marquee>
How do we make this compliant with html5 since marquee is deprecated?
I have seen a few examples, but most of them rely on fixed width.
In my example, the items are received from the server so there can be a lot of them. Also, I will need that stop on hover since the items are links to something else.
Thank you very much for your help,
PS: I want to make sure we can't do this in CSS only before I start exploring javascript.
This codepen has a great example of what you're looking for.
To make it pause on hover, I added a hover state to pause the animation:
https://codepen.io/anon/pen/zzpZyg
.marquee:hover div {
-webkit-animation-play-state: paused; /* Safari 4.0 - 8.0 */
animation-play-state: paused;
}
body { margin: 20px; }
.marquee {
height: 25px;
width: 420px;
overflow: hidden;
position: relative;
}
.marquee div {
display: block;
width: 200%;
height: 30px;
position: absolute;
overflow: hidden;
animation: marquee 5s linear infinite;
}
.marquee span {
float: left;
width: 50%;
}
#keyframes marquee {
0% { left: 0; }
100% { left: -100%; }
}
.marquee:hover div {
-webkit-animation-play-state: paused; /* Safari 4.0 - 8.0 */
animation-play-state: paused;
}
<div class="marquee">
<div>
<span>You spin me right round, baby. Like a record, baby.</span>
<span>You spin me right round, baby. Like a record, baby.</span>
</div>
</div>
Sorry I know I am late. However, I have a simple solution to create a marquee with CSS.
.marquee-container{
overflow:hidden;
}
.marquee{
min-width:100%;
animation: marquee 15s linear infinite;
}
.marquee:hover{
animation-play-state: paused;
}
#keyframes marquee {
from{margin-left : 120%;}
to{margin-left: -20%;}
}
<div class="marquee-container">
<p class="marquee">
<span>Item 1</span>
<span>Item 2</span>
<span>Item 3</span>
<span>Item 4</span>
</p>
</div>
Finally I found one that works, and here is the finally product https://fiddle.sencha.com/#view/editor&fiddle/228u
Here is the original one, https://codepen.io/lewismcarey/pen/GJZVoG
<div class="wrapper">
<div class="container">
<span>Span Me 1</span>
<span>Span Me 2</span>
<span>Span Me 3</span>
<span>Span Me 4</span>
</div>
</div>
The trick was to "left-pad" the wrapper to hide the container initially. Then, "right-pad" the container so that the animation only stops/restarts once the container has gone off screen. Both padding are sized relatively. display: block; is added to the container so that the right padding uses the wrapper's size. And finally, we add an animation on the wrapper's transform attribute.
Thank you all,
I am no good at java script
but here is it using html and css
PS. that mouse over thing is not working here
.wrapper {
position: relative;
overflow: hidden;
height: 25px;
width: 100px;
border: 1px solid orange;
}
.wrapper p {
position: absolute;
margin: 0;
line-height: 25px;
white-space: nowrap;
animation: marquee 5s linear infinite;
}
#keyframes marquee {
0% { transform: translateX(100%); }
100% { transform: translateX(-100%); }
}
<div class="wrapper">
<p>Hey, how you're doing? .</p>
</div>
There are lots of information on google about it, just search: "css3 marque", like Neil Kennedy mentioned. One question is very similar to yours and the text stops scrolling after you hover over it. Check this link below: CSS3 Marquee Effect and jsfiddle: http://jsfiddle.net/MaY5A/1/
$(".toggle").on("click", function() {
$(".marquee").toggleClass("microsoft");
});
/* Make it a marquee */
.marquee {
width: 450px;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
box-sizing: border-box;
border: 1px green solid;
}
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
border: 1px red solid;
animation: marquee 15s linear infinite;
}
.marquee span:hover {
animation-play-state: paused
}
/* Make it move */
#keyframes marquee {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-100%, 0);
}
}
/* Make it pretty */
.microsoft {
padding-left: 1.5em;
position: relative;
font: 16px 'Segoe UI', Tahoma, Helvetica, Sans-Serif;
}
/* ::before was :before before ::before was ::before - kthx */
.microsoft:before,
.microsoft::before {
z-index: 2;
content: '';
position: absolute;
top: -1em;
left: -1em;
width: .5em;
height: .5em;
box-shadow: 1.0em 1.25em 0 #F65314, 1.6em 1.25em 0 #7CBB00, 1.0em 1.85em 0 #00A1F1, 1.6em 1.85em 0 #FFBB00;
}
.microsoft:after,
.microsoft::after {
z-index: 1;
content: '';
position: absolute;
top: 0;
left: 0;
width: 2em;
height: 2em;
background-image: linear-gradient(90deg, white 70%, rgba(255, 255, 255, 0));
}
/* Style the links */
.vanity {
color: #333;
text-align: center;
font: .75em 'Segoe UI', Tahoma, Helvetica, Sans-Serif;
}
.vanity a,
.microsoft a {
color: #1570A6;
transition: color .5s;
text-decoration: none;
}
.vanity a:hover,
.microsoft a:hover {
color: #F65314;
}
/* Style toggle button */
.toggle {
display: block;
margin: 2em auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Wanted to see how easily marquees could be constructed with CSS:
- This demo uses -prefix-free to avoid vendor prefixes
- It also requires manual setting of the end text-indent
- Everything below the /* Make it pretty */ comment is non-essential
- Brought to you by #jonathansampson -->
<p class="microsoft marquee"><span>Windows 8 and Windows RT are focused on your life—your friends and family, your apps, and your stuff. With new things like the Start screen, charms, and a Microsoft account, you can spend less time searching and more time doing.</span></p>
<button class="toggle">Toggle Beautification</button>
<p class="vanity">
#jonathansampson of
#appendTo
</p>

3D-transforms, z-index and Safari

I know 3d-transforms and z-indexes don't work especially well together, but I'm having this issue (only in Safari) for which I'm hoping there's still a solution.
Basically, I have 2 elements on top of each other. The one in the "back" (with the lower z-index) is being rotated in 3d space. I would still however like the top element to be on top at all times.
.button {
padding: 10px 30px;
position: relative;
display: inline-block;
color: white;
cursor: pointer;
}
.button span {
position: relative;
z-index: 2;
}
.button:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border-radius: 10px;
background: red;
transition: transform .2s;
}
.button:hover:after {
transform: rotateY(30deg);
}
<div class="button">
<span>Text</span>
</div>
This works well in Chrome and Firefox (haven't tested IE yet), but in Safari the back element "cuts through" the top element, making half of the top element invisible.
I've tried setting transform:translate3d(0,0,0) to the top element and also transform-style:preserve-3d to the parent element, with no success.
I've seen other posts about this on here, but they all seem to be outdated and the solutions don't seem to work.
You can see a fiddle here: https://jsfiddle.net/6mtgts33/
Add following:
.button span {
display: inline-block;
transform: translateZ(100px);
}
https://jsfiddle.net/6mtgts33/2/
.button { padding:10px 30px; position:relative; display:inline-block; color:white; cursor:pointer; }
.button span { position:relative; display: inline-block; transform: translateZ(100px); z-index: 2; }
.button:after { content:""; position:absolute; left:0; top:0; width:100%; height:100%; border-radius:10px; background:red; transition:transform .2s; }
.button:hover:after { transform:rotateY(30deg); }
<div class="button">
<span>Text</span>
</div>
Actually you don't need z-index: 2 for Safari, but need it for Chrome still.
Haven't checked in other browsers.
transform: rotateY(30deg);
-webkit-transform: rotateY(30deg); //chrome and safari

Resources