css animation-fill-mode foward changes element opacity - css

Having an issue with an image when upon the image finishes its animation and is filled in forwards, it's opacity is lower than if i just load the image normally (with the animations taken out)
.header-container .col-2 {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
z-index: -1;
}
.header-container .col-2 img {
opacity: 0; //
animation: 0.5 header ease 1.25s; // these three lines seem to be the problem
animation-fill-mode: forwards; //
}
#keyframes header {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
I have looked at the styles on my browser (chrome) and can't work out why this is happening
In the image is what the difference looks like + chrome styles
img on right has slightly lower opacity
Thanks for any suggestions / help

animation: 0.5 header ease 1.25s;
the 0.5 without the time unit is interpreted as the animation-iteration-count which, if set to 0.5 means: "Run my animation halfways."
What you want is: name, duration, easing, delay, fill-mode use:
animation: header 0.5s ease 1.25s forwards;
and use the s or ms unit for the duration value.
Here's a reminder for the Animation shorthand order:
name, duration, easing, delay, iteration-count, direction, fill-mode
.header-container .col-2 {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
z-index: -1;
background: url("https://placehold.it/100x100/00f");
}
.header-container .col-2 img {
opacity: 0;
animation: header 0.5s ease 1.25s forwards;
}
#keyframes header {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div class="header-container">
<div class="col-2">
<img src="https://placehold.it/200x200/f00" alt="Test">
</div>
</div>

Related

Multiple Linear Animations On Same Line - Issue where second animation is not starting at the beginning

I'm working on a project where I want to have two animation with one following the other after a delay. I've gotten the two animation on the same line with one following after a delay, but I can't seem to get it work perfectly. The issue that I am having is that the first animation is starting after 0%/0vw, so it's show the animation start instead of it coming from off the page. I would really appreciate any help or advice on how to get this to work. Thank you!
.announcement {
justify-content: right;
align-items: center;
display: flex;
}
.announce {
font-size: 1.3rem;
position: relative;
/* animation: mymove 20s infinite;*/
/* animation-timing-function: linear;*/
animation: linear 15s mymove infinite;
}
.announce2 {
font-size: 1.3rem;
position: relative;
/* animation: mymove 20s infinite;*/
/* animation-timing-function: linear;*/
animation: linear 15s mymove2 infinite;
animation-delay: 5s;
}
#keyframes mymove {
from {right: 0vw;}
50% {right: 50vw !important;} /* ignored */
to {right: 100vw;}
}
#keyframes mymove2 {
from {right: 0vw;}
50% {right: 50vw !important;} /* ignored */
to {right: 100vw;}
}
<div class="announcement">
<div class="announce">
Hello
</div>
<div class="announce2">
Hello
</div>
</div>
To get the announcement off the screen to the right it needs to not only be positioned right: 0 but also to move further to the right by its own width. This can be achieved with a translation of 100%.
As an example, this snippet gives both announcements the same animation and other settings - apart from giving announement2 the animation delay.
The parent element has overflow hidden, and the body is given margin 0 to ensure that the announcements go fully from the right to the left.
body {
margin: 0;
}
.announcement {
justify-content: right;
align-items: center;
display: flex;
overflow: hidden;
}
.announce,
.announce2 {
font-size: 1.3rem;
position: relative;
animation: linear 15s mymove infinite;
right: 0;
transform: translateX(100%);
}
.announce2 {
animation-delay: 5s;
}
#keyframes mymove {
to {
right: 100vw;
transform: translateX(0%);
}
}
<div class="announcement">
<div class="announce">
Hello
</div>
<div class="announce2">
Hello
</div>
</div>
Note: if what you are wanting is an evenly spaced continuous flow then you might like to search for 'marquee' on StackOverflow - not the HTML tag which is deprecated but continuous rotating banner.

Is it possible to play an animation in both directions with a single #keyframes rule?

I would like to use a single #keyframes rule to animate an element from one state to another and then to get back to the original state when I do an action (with the same animation). I saw that using animation-direction: reverse; is a way to play the animation in reverse. However, when I try to use it, the transitions on my element disappear. If I set a new #keyframes with the reversed state it works fine.
What is the point of animation-direction in this case? I am misunderstanding something?
Is there a way to play an animation in both directions with a single #keyframes rule without loosing the transitions? I can't use transition, I need animation.
Here is a example to play with (hover the squares):
div {
width: 100px;
height: 100px;
animation: fade 0.6s ease-in-out forwards;
margin: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
#box-1:hover {
animation: fade 0.6s ease-in-out forwards;
animation-direction: reverse;
}
#box-2:hover {
animation: fadeReverse 0.6s ease-in-out forwards;
}
#keyframes fade {
0% { background: red; }
100% { background: blue; }
}
#keyframes fadeReverse {
0% { background: blue; }
100% { background: red; }
}
<div id="box-1">:(</div>
<div id="box-2">:)</div>
It's because you apply the same animation to the element on hover as the animation that is on the default state of the element.
So the element already had that animation with the default direction but then you apply it again with the reverse. But it won't work. I don't really know why this happens. But applying the same animation on an element twice, won't work. So you need 2 different keyframes.
You can use a reverse animation or duplicate the existing one and use it with direction: reverse
Read more here
restart animation
more info here
another article here
If you REALLY want to use just 1 animation this can be solved with javascript by removing and adding an 'animate-me' class . But it still wouldn't be ideal
div {
width: 100px;
height: 100px;
animation: fade 0.6s ease-in-out forwards;
margin: 15px;
display: inline-flex;
align-items: center;
justify-content: center;
color: white;
}
#box-1:hover {
animation: fade2 0.6s ease-in-out forwards;
animation-direction: reverse;
}
#box-2:hover {
animation: fadeReverse 0.6s ease-in-out forwards;
}
#keyframes fade {
0% { background: red; }
100% { background: blue; }
}
#keyframes fade2 {
0% { background: red; }
100% { background: blue; }
}
#keyframes fadeReverse {
0% { background: blue; }
100% { background: red; }
}
<div id="box-1">:(</div>
<div id="box-2">:)</div>

How to get FlexBox elements to overlap an SVG element?

I need to overlap an SVG element's top and bottom with FlexBox items so that the space between them is gone.
What I've tried:
Added a z-index of 1 to the FlexBox items but that didn't do anything.
Added a z-index of -1 to the SVG element but that only hid the element entirely, which is not what I wanted.
Here's my code:
// Lottie returns an SVG with class wrapper.
const defaultOptions = {
loop: false,
autoplay: true,
animationData: balanceData.default,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
className: 'wrapper'
}
};
// home.js
<div className="message">
<div className="txt-1">Find
</div>
<Lottie options={defaultOptions}
height={510}
width={310}
/>
<div className="txt-2">with your</div>
<div className="txt-3">body & mind.</div>
// home.css
.message {
font-family: 'Roboto', sans-serif;
font-size: 6em;
align-items: center;
display: flex;
padding-left: 60px;
padding-top: 60px;
flex-direction: column;
}
.txt-1 {
opacity: 0;
animation-name: txt-1;
animation-duration: 2s;
animation-delay: .5s;
animation-fill-mode: forwards;
display: flex;
align-items: center;
}
.wrapper {
z-index: 1;
}
#keyframes txt-1 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.txt-2 {
opacity: 0;
animation-name: txt-2;
animation-duration: 1.5s;
animation-delay: 1s;
animation-fill-mode: forwards;
}
#keyframes txt-2 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.txt-3 {
opacity: 0;
animation-name: txt-3;
animation-duration: 2s;
animation-delay: 1.5s;
animation-fill-mode: forwards;
}
#keyframes txt-3 {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Again, all I want is for space between the FlexBox items and SVG element to be hidden:
Figured it out! Just had to remove align-items: center; from .message and add the following to .wrapper:
.wrapper {
padding-left: 5%;
width: 90% !important;
display: flex !important;
}
to make my UI look like:
Note: I'm well aware it's highly suggested to only use !important in either utility cases or user stylesheets. But the library I'm using to render my SVG doesn't allow me to change their stylesheet, so I feel this is a justified use-case of it.

Smoothly transition from midway through CSS animation to start (or end)

I have a box that spins on click:
.box{
width: 200px;
height: 200px;
background:red;
transition: all 1s;
}
.box.spin{
animation: spin 5s infinite linear;
}
When you click it a second time, I'd like it to either unspin, or complete its spin to come to a halt. It seems that instead it snaps immediately back to its starting position:
https://codepen.io/EightArmsHQ/pen/OaoPKm?editors=0100
Is there a way of achieving this without replacing the animation with a transition?
What about use animation-play-state property ?
.box{
animation: spin 5s infinite linear; // add this here
animation-play-state: paused; // pause animation by default
}
.box.spin{
animation-play-state: running; // play animation
}
https://codepen.io/frantisekvrab/pen/YROXaZ
If you like to complete the spin, I assume you have to use some more JS or CSS transition.
By "unspin" do you mean to have it spin in the other direction? If so, you can do something like this:
window.onload = ()=>{
let box = document.querySelector('.box');
box.addEventListener('click', function(){
this.classList.toggle('spin')
this.classList.toggle('spin-reverse')
});
}
#keyframes spin{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
html, body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.box{
cursor: pointer;
width: 200px;
height: 200px;
background:red;
transition: all 1s;
box-sizing: border-box;
color: #fff;
display: flex;
padding: 30px;
text-align: center;
align-items: center;
justify-content: center;
user-select: none;
}
.box.spin{
animation: spin 5s infinite linear;
}
.box.spin-reverse {
animation: spin 5s infinite linear reverse;
}
<div class="box spin" id="box">
Click to toggle animation
</div>
Also, here's a working example :)

Different elements in one animation

Their is bit complications but I think it isn't possible to do what I want with just CSS3 alone.
I have three images in header, I want images to show up with fade-in fade-out effect by using opacity in CSS animation.
I was thinking what if I could select nested elements in animation and animate them. Creating chain animation is bit difficult.
Try using transition-delay property to delay the animation.
Simply apply animation rules to your images. Using animation-delay a chain effect can be produced.
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
}
body {
display: flex;
background-color: #000;
}
img {
margin: auto;
width: 33.333%;
opacity: 0;
animation-name: fade;
animation-duration: 4s;
animation-iteration-count: infinite;
}
#keyframes fade {
50% {
opacity: 1;
}
}
img:nth-child( 2 ) {
animation-delay: 0.5s;
}
img:nth-child( 3 ) {
animation-delay: 1s;
}
<img src="http://i.imgur.com/iyzGnF9.jpg">
<img src="http://i.imgur.com/iyzGnF9.jpg">
<img src="http://i.imgur.com/iyzGnF9.jpg">

Resources