Transform: translate Doesn't work in React / SASS [duplicate] - html

This question already has an answer here:
How to keep origin in center of image in scale animation?
(1 answer)
Closed 1 year ago.
I couldn't find a solution for this simple problem, I changed the display to flex and block, that didn't work either. It works on parent element. But I guess there is something I can't see on this code.
.planets {
display: flex;
height: 100vh;
}
.pluton-orbit {
display: inline-block;
width: 70rem;
height: 70rem;
border: 1px solid rgba(0, 0, 0, 0.219);
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% , -50%);
z-index: 4;
animation: Rotation 5s linear infinite;
}
#keyframes Rotation {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
the transform here, doesn't work. I know how to center, my question is why doesn't the transform property work. this is react with Sass by the way. Everything else works in the code, just the transform has this weird problem. here is the component.
import React from "react";
const Planets: React.FC = () => {
return (
<div className="planets">
<div className="pluton-orbit">
<div className="pluton"></div>
</div>
<div className="neptun-orbit">
<div className="neptun"></div>
</div>
</div>
);
};
export default Planets;

It's because the animation is overriding the transform property. This is one limitation of transform. a solution is to add the translate(-50%, -50%) to the animation keyframes.
#keyframes Rotation {
from {
transform: translate(-50%, -50%) rotate(0);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}

Related

Why does 'transform:rotate(Xdeg)' cause the animation to stop?

I tried to rotate an animated font arrow when the window reached a min/max size, but when the rotate takes place the animation stops, also just for testing I tried replacing transform: rotate(90deg) to transform: rotate(0deg) which maintains the same arrow's direction but it causes to stop the animation too. The issue is with transform: rotate() and it can be easily tested by inspecting the element and activating/deactivating it in the browsers developer tools.
An easy way to bypass this can be using two <p> each one with an arrow in different direction and with vertical and horizontal animation each, and using display: none; to alternate between them when the min/max size switches, but what I want is to know why this is happening and how to solve this using this approach
.text-center {
text-align: center;
}
.lnr-x3 {
font-size: 2.4rem;
}
#media (max-width: 991px) {
#catalogArrow_h {
transform: rotate(90deg) !important;
transform-origin: center !important;
}
}
.animated-h {
text-decoration: none;
outline-style: none;
-webkit-animation: movingHorizontally 1.7s ease-in-out infinite;
animation: movingHorizontally 1.7s ease-in-out infinite;
}
#keyframes movingHorizontally {
0% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
50% {
transform: translateX(-10px);
-webkit-transform: translateX(-10px);
}
100% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
}
#-webkit-keyframes movingHorizontally {
0% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
50% {
transform: translateX(-10px);
-webkit-transform: translateX(-10px);
}
100% {
transform: translateX(0px);
-webkit-transform: translateX(0px);
}
}
<!-- Font Icons -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" type="text/css">
<link rel="stylesheet" href="https://cdn.linearicons.com/free/1.0.0/icon-font.min.css">
<div class="col-12">
<p class="text-center pt-3 px-5">
<span id="catalogArrow_h" class="lnr lnr-x3 lnr-arrow-right fas animated-h"></span>
</p>
</div>
Why does this happen
The transform property is "shared" for many transform functions and css doesn't combine any property's values.
Because your animation is made with transform: translateX(..), adding transform: rotate(..) will overwrite the property's value, not combine them. I.e. the resulting style is transform: rotate(..), not transform: translateX(..) rotate(..).
It would be the same if you were animating the box-shadow and then wanted an inset box-shadow too, it would overwrite one with the other. Or more simply - if you have .box { color: red; color: blue; } css will choose the last value (blue) to apply to the color property.
If there were css properties rotate: 90deg and translate: 4px (there are but not widely supported), then your animation would work, because the translate animation would be applying to a different property than the rotation, not overwriting one that is essentially shared amongst many transform functions.
Ways around it
There are many ways around this problem.
You can set the translate or rotate on the parent element
<div class="rotate-90">
<span class="translate-animate"></span>
</div>
You can add the rotate to your translate animation properties:
#keyframes movingHorizontallyRotated {
0%, 100% { transform: translateX(0px) rotate(90deg); }
50% { transform: translateX(-10px) rotate(90deg); }
}
You can animate a different property to translate the element:
#keyframes movingHorizontally {
0%, 100% { padding: 5px 10px 5px 0px; }
50% { padding: 5px 0px 5px 10px; }
}
You can use/make an already rotated arrow if your framework/ assets provides one.

Rotate twice from two origin

I have a css div I want first to rotate at 180deg from the center origin and then rotate from -45deg from the "new" bottom left corner.
But I don't manage to apply two different rotations
https://imgur.com/a/9GSToEx -> So you can better understand
CSS
.player1{
background-color: blueviolet;
transform-origin: center;
transform: rotate(180deg);
transform-origin: bottom left;
transform: rotate(45deg);
}
HTML
<div class="player1">
<div class="questionSpace"></div>
</div>
Thank you ^^
This can be a bit tricky because of the need to move the origin and the rotations not being additive.
A fairly straightforward way of getting round the problem is to enclose the element in a parent whose sole purpose is to allow an independent 180deg rotation.
This snippet colors the player1 element with a linear-gradient so it can be seen that the 180deg rotation has taken place.
.player1container {
display: inline-block;
transform: rotate(180deg);
margin: 20vmin;
/* added just for demo */
}
.player1 {
background-color: blueviolet;
width: 20vmin;
height: 10vmin;
background-image: linear-gradient(red, blue);
transform: rotate(-45deg);
transform-origin: top right;
}
<div class="player1container">
<div class="player1">
<div class="questionSpace"></div>
</div>
</div>
Hmm. Your code is wrong, because this rules have conflict and last rule have more priority;
transform: rotate(180deg);
...
transform: rotate(45deg);
You need to use #keyframes
for example:
#rotate {
0% {
transform: rotate(0);
}
50% {
transform: rotate(180deg);
}
100% {
transform-origin: left;
transform: rotate(45deg);
}
}
and then you need to use animation: rotate;

Why does adding a rotation animation offset my image? [duplicate]

This question already has an answer here:
How to keep origin in center of image in scale animation?
(1 answer)
Closed 1 year ago.
Im trying to make a logo that spins, but once the animation is being added, it jumps a down and i can't figure out why. I'm just adding -webkit-animation: rotation 5s infinite linear; and not adjusting the position at all.
Here's a live version of it, you can click the logo after the initial animation to add the rotate class. Any ideas how to make it stay in place?
const EL_logo = document.querySelector(".permanent-logo");
EL_logo.addEventListener("click", () => {
EL_logo.classList.add("rotate-logo");
});
.permanent-logo {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
top: 70px;
width: 120px;
}
.rotate-logo {
animation: rotation 5s infinite linear;
}
#keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
<div class="initial-overlay">
<div class="logo-container">
<img class="permanent-logo" src="https://i.stack.imgur.com/g2LtV.png" alt="logo">
</div>
</div>
If your element has already a non animated transform applied transform: translate(-50%, -50%), the animation keyframes should also consider that initial transformations - because later transformations are not added on top, composited over the existing ones.
You should repeat them transform: translate(-50%, -50%) rotate(0deg);:
const EL_logo = document.querySelector(".permanent-logo");
EL_logo.addEventListener("click", () => {
EL_logo.classList.add("rotate-logo");
});
.permanent-logo {
position: relative;
left: 50%;
transform: translate(-50%, -50%);
top: 70px;
width: 120px;
}
.rotate-logo {
animation: rotation 5s infinite linear;
}
#keyframes rotation {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(359deg);
}
}
<div class="initial-overlay">
<div class="logo-container">
<img class="permanent-logo" src="https://i.stack.imgur.com/g2LtV.png" alt="logo">
</div>
</div>

css transitions: hover out transition not working if hover in is not allowed to complete

I have a div, for which css transitions are applied on hover,
on hover in, a transition is applied on the :before element, and on hover out, same transition (reversed) is applied on the :before element.
here is the html:
<section class="strips">
<article class="strips__strip">
<div class="strip__content">
<h1 class="strip__title">Title</h1>
</div>
</article>
</section>
and (important parts of) the css:
.strips .strip__content:hover:before {
transform: skew(180deg) scale(1) translate(0, 0);
opacity: 0.1;
}
.strips .strip__content:before {
content: "";
position: absolute;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
opacity: 0.05;
transform-origin: center center;
transform: skew(180deg) scaleY(0) translate(0, 0);
transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
}
Now, the transitions work smoothly if i allow tem to finish, but say, if i dont allow the hover in transition to finish , and quickly hover out, then the hover out transition does not work.
here is a fiddle:
https://jsfiddle.net/x2pavnac/
(try hovering out before the transition finishes).
I am not sure why this happens and how this issue can be addressed in css.
EDIT:
i have simplified the transition and also increased opacity, so it is more visible.
Updated fiddle: https://jsfiddle.net/x2pavnac/4/
I am not sure why this works well for others, but i found a typo in my css which was the issue in my case:
.strips .strip__content:before {
transform: skew(180deg) scaleY(0) translate(0, 0);
}
.strips .strip__content:hover:before {
transform: skew(180deg) scale(1) translate(0, 0);
opacity: 0.1;
}
should be
.strips .strip__content:before {
transform: skew(180deg) scaleY(0) translate(0, 0);
}
.strips .strip__content:hover:before {
transform: skew(180deg) scaleY(1) translate(0, 0);
opacity: 0.1;
}
notice the scaleY(1) instead of scale(1).
I am still not sure why it worked correctly for others though, even with the typo.

Cube rotation with css

I am having a bit of an issue with rotation of a cube. I want to make it cross-browser so I am transforming every side of the cube. When I am rotating from left to right the sides align perfectly on all browsers Chrome, Firefox and IE, BUT when the cube is rotated from top to bottom, the sides align only on Chrome (If I make the animation slower on Chrome the sides are broken the same way as the other browsers, so I think working properly is a bug :D). I have provided an example on jsfiddle:
http://jsfiddle.net/0n9bnxe5/
HTML:
<div class="flip-card-content">
<div class="flip-card-side-a" style="background:red">
FRONT
</div>
<div class="flip-card-side-b" style="background:green">
BACK
</div>
<div class="flip-card-side-c" style="background:aqua">
LEFT
</div>
</div>
<button id="button">Flip-top</button>
<button id="button2">Filp-right</button>
CSS:
.flip-card-content {
position: relative;
margin: 100px;
width: 200px;
height: 200px;
transform-style: preserve-3d;
perspective:1000px;
}
.flip-card-side-a,
.flip-card-side-b,
.flip-card-side-c{
width: 100%;
position: absolute;
height: 100%;
backface-visibility: hidden;
transform-origin:50% 50% 0px;
transition: all .5s ease-in-out;
}
.flip-card-side-a {
transform: rotateY(0deg) translateZ(100px);
z-index: 1;
}
.flip-card-side-b {
transform: rotateX(90deg) translateZ(100px);
}
.flip-card-side-c {
transform: rotateY(-90deg) translateZ(100px);
}
.flip .flip-card-side-a {
transform: rotateX(-90deg) translateZ(100px);
}
.flip .flip-card-side-b {
display:block;
transform: rotateY(0deg) translateZ(100px);
z-index: 1;
}
.flip-right .flip-card-side-a {
transform: rotateY(90deg) translateZ(100px);
}
.flip-
right .flip-card-side-b {
display:none;
}
.flip-right .flip-card-side-c {
transform: rotateY(0deg) translateZ(100px);
z-index:1;
}
JQUERY:
$("#button").on('click', function(){
$(".flip-card-content").removeClass("flip-right");
setTimeout(function(){
$(".flip-card-content").toggleClass("flip");
},500);
});
$("#button2").on('click', function(){
$(".flip-card-content").removeClass("flip");
setTimeout(function(){
$(".flip-card-content").toggleClass("flip-right");
},500);
});
Any advice is welcomed!
Your translateZ doesn't quite work in the way you expect. Have look at how I've positioned the faces on the cube here and compare it to your own. Ultimately, I find the easiest way to rotate items such as cubes etc. is to position all the elements and then just rotate the container.
Also for nice scaling of fonts, images etc. its preferable to leave the front face at its natural size rather than scale up (i.e. move everything backward in 3d space):
.box {
height: 100%;
position: relative;
transform: rotateX(0deg);
transform-origin: 50% 50% -100px;
transform-style: preserve-3d;
transition: all 1s;
width: 100%;
}
.box--rotate-top {
transform: rotateX(-90deg);
}
.box--rotate-left {
transform: rotateY(90deg);
}
.box__face {
backface-visibility: hidden;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.box__face--front {
background: #f90;
}
.box__face--top {
background: #369;
transform: rotateX(90deg) translateZ(200px);
transform-origin: 0 100% 0;
}
.box__face--left {
background: #867;
transform: rotateY(-90deg) translateZ(200px);
transform-origin: 100% 0 0;
}
Here is the fiddle.
Transition in 3d space are tricky, and different browsers can handle them differently.
Here you have your fiddle corrected.
Your best bet is to leave nothing to the browser imagination
so, instead of changing
transform: rotateY(0deg) translateZ(100px);
to
transform: rotateX(-90deg) translateZ(100px);
make the change happen from
transform: rotateX(0deg) rotateY(0deg) translateZ(100px);
to
transform: rotateX(-90deg) rotateY(0deg) translateZ(100px);
Notice that I didn't change the transform from a mathematical point of view; but now every property matches a similar one.
Note just in case you want to know, in the first case IE is making the followng transition: change the angle of rotation from 0 to -90deg. At the same time, change the axis of rotation from Y to X. So, at the middle of the transition, the rotation is wrong (from your point of view), but in a mathematic sense, both ways of understanding the transition make sense.