Absolutely positioned element moves after animation completes - html

it's been awhile. Anyway, having some trouble getting an absolutely positioned element to stay center while animating. What's more is I'm seeing the element "shift" after the animation is complete and I have no idea why. Closest issue I found was css animations moves element position but that didn't solve for this common use case.
Debugging the animation frames, we can see the following:
During animation
After animation
Yuck! Playing with positioning didn't work, but animation-fill-mode did something; however, I noticed translate has no effect on the positioned element during animation or when animation-fill-mode is set to forwards or both. Why? The side effect is when the animation completes the element's position will not be recalculated so no repaint.
Example:
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
and the CSS using animate.css to make life easy:
.alert {
min-width: 500px;
position: absolute;
top: 0;
left: 50%;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
/* animation-fill-mode: forwards; */
transform: translateX(-50%);
}
Demo: https://codepen.io/atomicpages/pen/yrymVY?editors=1100
Goals:
Center aligned
Element is at least 500px
Element doesn't move after animation frame completes
Your help is appreciated.

Use custom fadeInDown without animate.css because it is using transform: translate3d(0, -100%, 0) in fadeIndown
.alert {
width: 500px;
top: 0;
left: 50%;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
transform: translateX(-50%);
position:absolute;
}
#keyframes fadeInDown{
from{
opacity:0;
}
to{
opacity:1;
}
}
#-webkit-keyframes fadeInDown{
from{
opacity:0;
}
to{
opacity:1;
}
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>

Try removing transform: translateX, after the animation, the element stays where it is, and change it to left: 0;
.alert {
min-width: 500px;
top: 0;
left: 0;
animation-name: fadeInDown;
animation-duration: 0.75s;
animation-timing-function: ease-in-out;
}

The reason is that the built-in fadeInDown also use transform for its animation, hence resets/override your initial value, and restore it after, unless you use animation-fill-mode: forwards;, which will keep it 50% off the left edge all the time.
And do note, preset transform "values", like translateX doesn't persist when another "value" is added to the "property", all existing values gets overwritten.
Original CSS
#keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
For yours to work you need to override the built-in one, adding your translateX value to it, and it will behave.
And if you do, there is a prefixed #keyframes rule as well, which also need to be updated.
New CSS
#keyframes fadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(-50%, -100%, 0);
transform: translate3d(-50%, -100%, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(-50%, 0, 0);
transform: translate3d(-50%, 0, 0);
}
}
As a side note:
With the provided setting it will always take full width and centering it would have no effect, unless you also gave it a max-width somewhere else.

Related

page breaks do not work within section tags

I am making a project with django, html,css, and javascript and I am building a page with sections and scroll snapping. I am struggling to go down a line after my tag but before my tag within a section. when I tried using break tags nothing happens, even when I use multiple. My best guess is that the fact that I am trying to do it within a section tag
<body>
<div class = "nav">
Home
Education
Projects
Skills
Experience
</div>
<div class="scroll_container">
<section id = "1" class = "home_section">
<h1>Tyler Olson</h1>
<img class="animate__animated animate__bounce" src="/static/down_arrow.png" alt="bouncing dodwn arrow" style="width:50px;height:50px;">
</section>
...
</div>
</body>
My goal is to have the arrow repeatedly bouncing at the bottom center of the section but I am completely unable to move it down rn, I even tried modifying some css values to move the img tag but none of them did anything
May be this Answer Helpful For Your Try This
<style>
.animate__bounce {
width: 100px;
height: 100px;
animation: bounce 0.5s;
animation-direction: alternate;
animation-timing-function: cubic-bezier(.5, 0.05, 1, .5);
animation-iteration-count: infinite;
}
#keyframes bounce {
from {
transform: translate3d(0, 0, 0);
}
to {
transform: translate3d(0, 200px, 0);
}
}
/* Prefix Support */
animate__bounce {
-webkit-animation-name: bounce;
-webkit-animation-duration: 0.5s;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: cubic-bezier(
.5, 0.05, 1, .5);
-webkit-animation-iteration-count: infinite;
}
#-webkit-keyframes bounce {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
-webkit-transform: translate3d(0, 200px, 0);
transform: translate3d(0, 200px, 0);
}
}
</style>

Smooth parent transition on child "translateX"

On GIF below, there's parent div, which contain "left-menu" and "app-content". Left menu is animating, using keyframes and translate property
#LeftMenuContainer {
&.menu_hidden {
animation: slide-out 0.6s forwards;
}
&.menu_shown {
animation: slide-in 0.6s forwards;
}
}
#keyframes slide-in {
0% { transform: translateX(-100%); width: 0; }
100% { transform: translateX(0); width: auto; }
}
#keyframes slide-out {
0% { transform: translateX(0); width: auto; }
100% { transform: translateX(-100%); width: 0; }
}
DOM tree looks like this
<div id="contentContainer" class="flex">
<app-left-menu></app-left-menu>
<div>Be smooth!</div>
</div>
Is there any way, to "smooth" transition parent width, when "left-menu" is hiding? I try to add styles for parent, with
transition-property: width;
transition-duration: 0.6s;
but it doesn't work.
https://im2.ezgif.com/tmp/ezgif-2-a1f74da85c.gif
Assume It only flickers when comes to animate, so you can try to use will-change, css-will-change-property
The will-change CSS property hints to browsers how an element is expected to change. Browsers may set up optimizations before an element is actually changed
If you are using framework like React can try to use framer-motion

Preserve CSS transform property after removing the class

Is it possible to preserve a CSS property (including variables) after removing a class that modifies them ?
The problem is in the code below.
I want to preserve the transform property of the cyan box after removing the class animation-slide-to-left that slides the box to the left.
That is because when removing that animation-slide-to-left and adding the class animation-slide-to-right class, I want that new animation to start from where the old one ended.
But the problem is when removing animation-slide-to-left the transform property resets and becomes equal to Its old value before adding that class.
Note: I don't want to hard code the transform property at 0%, because there are a lot of animations, and I am searching for a way that automatically solve the problem without JAVASCRIPT.
(expand the snippet result to full page too see the example)
const box = document.querySelector (".animated");
function leftclicked (){
box.classList.remove ("animation-slide-to-right");
box.classList.add ("animation-slide-to-left");
}
function rightclicked (){
box.classList.remove ("animation-slide-to-left");
box.classList.add ("animation-slide-to-right");
}
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.animated {
animation-duration: 0.5s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
.animation-slide-to-left {
animation-name: slide-to-left;
}
.animation-slide-to-right {
animation-name: slide-to-right;
}
#keyframes slide-to-left {
100%{
transform: translate(-150%, -50%);
}
}
#keyframes slide-to-right {
100%{
transform: translate(50%, -50%);
}
}
<div class="center" style="width:300px; height: 300px; background-color: red;">
<div class="center animated" style="width: 50%; height: 50%; background-color:cyan;">
</div>
<button style="float:left;" onclick="leftclicked()">LEFT</button>
<button style="float:right;" onclick="rightclicked()">RIGHT</button>
</div>
You can set the starting position for each time you click on the buttons LEFT and RIGHT in the CSS keyframes, so that when the button is on the left side and click on the RIGHT button, it first sets the position to the left side (0%) before it animates to the right (100%) and vice-versa. This way it doesn't reset back to the center when clicking the buttons.
const box = document.querySelector (".animated");
function leftclicked (){
box.style.transform = 'translate(50%, -50%)';
box.classList.remove ("animation-slide-to-right");
box.classList.add ("animation-slide-to-left");
}
function rightclicked (){
box.style.transform = 'translate(-150%, -50%)';
box.classList.remove ("animation-slide-to-left");
box.classList.add ("animation-slide-to-right");
}
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.animated {
animation-duration: 0.5s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
.animation-slide-to-left {
animation-name: slide-to-left;
}
.animation-slide-to-right {
animation-name: slide-to-right;
}
#keyframes slide-to-left {
100%{
transform: translate(-150%, -50%);
}
}
#keyframes slide-to-right {
100%{
transform: translate(50%, -50%);
}
}
<div class="center" style="width:300px; height: 300px; background-color: red;">
<div class="center animated" style="width: 50%; height: 50%; background-color:cyan;">
</div>
<button style="float:left;" onclick="leftclicked()">LEFT</button>
<button style="float:right;" onclick="rightclicked()">RIGHT</button>
</div>
Well It turns out that it is unnecessary to create such behaviour without JavaScript.
Because if a CSS class is being replaced at runtime, we are already using JavaScript.
So the solution is to set the transform property in JavaScript after removing the old class and before adding the new class

Iron Man HUD CSS Animation

I've always been inspired by the HUD display in Iron Man. Specifically how the icons fly in at the initial loading of the suit like here:
https://www.youtube.com/watch?feature=player_embedded&v=ZwOxM0-byvc
However, I haven't found a way in CSS get the images to start at the center of the page, drop to the bottom and then slide into their respective spots. I figured that I would have to use something like this:
from {
opacity: .5;
position: absolute;
left: 50%;
transform: translate3d(0, -100px, 0);
animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
}
60% {
opacity: 1;
position: absolute;
left: 50%;
transform: translate3d(0, 0, 0);
animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
}
to{
left: 0%
}
However, when I do that it creates a weird jitter as it doesn't appear to know how to make the transition smoothly from left center (50% absolute) to then it's respective placement on the page.
Ideas?

How to scale an element when it loads using only CSS?

I'm loading an element that has the initial css values of :
.popOver {
height: 100%;
width: 100%;
position: fixed;
background-color: #d9dfe5;
transition: all 2s ease-in-out;
transform: scale(0,0);
}
I need to change to scale(1, 1) when the element loads in the page and see the transition. Anyone can help?
transition will apply the moment you load the page so that is not an ideal solution in your situation, what you will need is CSS #keyframes where you need to set scale(0,0) to the class and then scale(1,1) for 100% as keyframes will shoot after the page is completely loaded.
Demo (Refactored the code a bit and added animation-fill-mode to prevent the popup from scaling back to 0 so using rev 2)
.popOver {
height: 100%;
width: 100%;
position: fixed;
background-color: #d9dfe5;
-webkit-animation: bummer 2s;
animation: bummer 2s;
-webkit-transform: scale(0,0);
transform: scale(0,0);
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards; /* Add this so that your modal doesn't
close after the animation completes */
}
#-webkit-keyframes bummer {
100% {
-webkit-transform: scale(1,1);
}
}
#keyframes bummer {
100% {
transform: scale(1,1);
}
}
Here as I explained before, am setting the initial scale of the element to 0,0 and than am animating it to 1,1 using keyframes. The time of the animation can be controlled by tweaking the 2s which is nothing but 2 Seconds.