Trouble using css transitions nested in elements that have css animations - css

I can get everything work if I use solely transitions, or solely animations, but I can't seem to work out how to make things work with the mixture.
Basically I have one outer element which I want to fade in, then an inner element I want to slide in after the fade is complete.
My real example is complex so I created a fiddle which illustrates what I'm going after.
How can I get the bottom bar here to behave similarly to the top one? (obv differences of scaleX aside). The issue is that the bottom inner blue bar shows up as full straight away, instead of animating open like the top one.
https://jsfiddle.net/joshuaohana/sqsLc5sd/
For this example just hover over either colored box
<div class="outer">
<div class="inner">
</div>
</div>
<p></p>
<div class="outer2">
<div class="inner2">
</div>
</div>
.outer {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer .inner {
height: 100px;
width: 0;
background-color: blue;
}
.outer:hover {
opacity: 1;
transition: opacity 1s;
}
.outer:hover .inner {
width: 100px;
transition: width 1s 0.5s;
}
.outer2 {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer2 .inner2 {
height: 100px;
width: 0;
background-color: blue;
}
.outer2:hover {
opacity: 1;
transition: opacity 1s;
}
.outer2:hover .inner2 {
width: 100px;
animate: widen 1s 0.5s forwards;
}
#keyframes widen {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}

You're using animate instead of animation. I would also use translateX instead of scaleX() but it probably doesn't matter. I would also set the initial state for the animation in the rule for .inner2, then simplify the animation and only specify the to or 100% step.
.outer {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
}
.outer .inner {
height: 100px;
width: 0;
background-color: blue;
}
.outer:hover {
opacity: 1;
transition: opacity 1s;
}
.outer:hover .inner {
width: 100px;
transition: width 1s 0.5s;
}
.outer2 {
width: 300px;
height: 100px;
background-color: red;
opacity: 0.1;
transition: opacity 1s;
overflow: hidden;
}
.inner2 {
height: 100px;
transform: translateX(-100%);
background-color: blue;
transform-origin: 0;
}
.outer2:hover {
opacity: 1;
}
.outer2:hover .inner2 {
width: 100px;
animation: widen 1s forwards;
animation-delay: .5s;
}
#keyframes widen {
to {
transform: translateX(0);
}
}
<div class="outer">
<div class="inner">
</div>
</div>
<p></p>
<div class="outer2">
<div class="inner2">
</div>
</div>

Related

How to reverse an animation on mouse out hover on a absolute position element

I'm hiding an element which holds text with position absolute since some screen readers won't read it if the opacity is zero. I want to use a fade in animation like the first box, so I used a simple animation function, but I can't get the fade out animation to work. Do you guys know why?
Thanks in advance!
p {
color: red;
}
.card {
position: relative;
width: 100px;
height: 100px;
text-align: center;
border: 2px solid red;
}
.card.using-opacity .text-container {
opacity: 0;
-webkit-transition: opacity 1s ease-in-out;
transition: opacity 1s ease-in-out;
}
.card.using-opacity:hover .text-container {
opacity: 1;
}
.card.using-position-absolute .text-container {
position: absolute;
top: -9999px;
left: -9999px;
width: 100%;
-webkit-animation: fadeOut 1s;
animation: fadeOut 1s;
}
.card.using-position-absolute:hover .text-container {
top: 0px;
left: 0px;
-webkit-animation: fadeIn 1s;
animation: fadeIn 1s;
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<p>This is how it's supposed to work in terms of animation/transition but it's not accessible</p>
<div class="card using-opacity">
<div class="text-container">
<p>Some text</p>
</div>
</div>
<p>This is accessible, but I can't get the mouse out animated</p>
<div class="card using-position-absolute">
<div class="text-container">
<p>Some text</p>
</div>
</div>

The bar looks right. Why won't the animation work?

I'm new to animation. I pick some code up that had a demo that worked in the 5 browsers I'm testing in. I'm on Windows 10 and have the latest versions of the 5 browsers I test in (Chrome, FF, edge IE, and Opera. The CSS follows.
.progress-bar {
margin-bottom: 1rem;
background-color: tomato;
border-radius: 1.25em;
width: 300px;
height: 16px;
display: inline-block;
}
.progress-value {
background-color: MEDIUMBLUE;
transition: 0.3s all linear;
border-radius: 1.25em;
height: 16px;
display: inline-block;
animation: progress 3s ease-in-out forwards;
-webkit-animation: progress 3s ease-in-out forwards;
}
.progress-value.green {
background-color: MEDIUMSEAGREEN;
animation: progress-3 3s ease-in-out forwards;
-webkit-animation: progress-3 3s ease-in-out forwards;
}
.progress-value.red {
background-color: TOMATO;
animation: progress-2 3s ease-in-out forwards;
-webkit-animation: progress-2 3s ease-in-out forwards;
}
/* animation */
#keyframes progress {
from {
width: 0;
}
to {
width: 55%;
}
}
#-webkit-keyframes progress {
from {
width: 0;
}
to {
width: 55%;
}
}
#keyframes progress-2 {
from {
width: 0;
}
to {
width: 70%;
}
}
#-webkit-keyframes progress-2 {
from {
width: 0;
}
to {
width: 70%;
}
}
#keyframes progress-3 {
from {
width: 0;
}
to {
width: 90%;
}
}
#-webkit-keyframes progress-3 {
from {
width: 0;
}
to {
width: 90%;
}
}
<DIV ID='dvLoading' STYLE='POSITION:relative;TOP:-300px;LEFT:30%;'>
<DIV class='progress-bar'>
<DIV class='progress-value' style='WIDTH:70%;'></DIV>
</DIV>
</DIV>
The bar looks like I hoped. But there is no animation in any of the 5 browsers.
Here's working and better code for you. Instead of creating animation for each progress value, change width of child and show indicator inside the child and animate it once (from width: 0% to width: 100% width). I created a simple animating progress bar with 4 color variants.
.progress {
width: 500px;
height: 30px;
border-radius: 15px;
overflow: hidden;
background: #eee;
position: relative;
}
.progress>.progress-value {
position: relative;
height: 100%;
left: 0;
top: 0;
}
.progress>.progress-value::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
animation: progress-value 3s ease-in-out forwards;
-webkit-animation: progress-value 3s ease-in-out forwards;
background: #666;
}
.progress>.progress-value.red::before {
background: #f44;
}
.progress>.progress-value.green::before {
background: #3f4;
}
.progress>.progress-value.blue::before {
background: #54f;
}
#keyframes progress-value {
from {
width: 0%;
}
to {
width: 100%;
}
}
#-webkit-keyframes progress-value {
from {
width: 0%;
}
to {
width: 100%;
}
}
<div class="progress">
<div class="progress-value" style="width: 65%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value red" style="width: 95%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value green" style="width: 41%"></div>
</div>
<div style="height: 15px"></div>
<div class="progress">
<div class="progress-value blue" style="width: 14%"></div>
</div>
What I did that works as I hoped is that I load the indicator as an HTML file into an object in the CGI process and position that object at the V/H center of the iframe. I put a 1 second lag in the JavaScript that's executed when the IFRAME content is loaded (ONLOAD) to turn the indicator off, to ensure that at least a little of the indicator is seen on a real fast load. Thanks all. ct

The same CSS animations does not have the same durations (with animated background color)

I try to animate two blocks with css animation. Its have the same transform animation but one of it has background-color animation also. This animations splitted to two #keyframes.
See code (https://codepen.io/mctep/pen/Rgyaep):
<style>
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
</style>
<div class="a"></div>
<div class="b"></div>
Animation of colored block is lag from gray block In Google Chrome. In Safary and FF it works perfectly.
I can to make one #keyframes for background and other for transform and it solves problem. But I want to use single value of animation property for single element. If there are no any ways to fix it I'll separate moving and coloring animations.
Why this happens? Is it Google Chrome bug?
Couldn't give you a concrete reason why this happens, but we can un-confuse Chrome by simply specifying a background-color in animation B as well.
#keyframes b {
0% {
background-color: gray; /* add this */
transform: translateX(0);
}
}
.a {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: red;
animation: a 1s infinite;
}
.b {
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100px;
background-color: gray;
animation: b 1s infinite;
}
#keyframes a {
0% {
background-color: red;
transform: translateX(0);
}
50% {
background-color: green;
transform: translateX(100px);
}
100% {
background: red;
}
}
#keyframes b {
0% {
background-color: gray;
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
}
<div class="a"></div>
<div class="b"></div>

CSS Transition on a css transform property causing the parent to flicker only in Google Chrome

I have a pretty specific rendering issue I came across. When doing a css transition on a transform property, the direct parent is dimming during the transition, even though the opacity is not being changed. This only happens in Chrome, not Safari or Firefox, and I'm on a mac.
Has anyone seen this issue or have any thoughts?
$('#toggle').click(function(e){
$('#bar').toggleClass('on');
});
body {
background: #222;
}
#bar {
background: #999;
opacity: .5;
height: 4px;
border-radius: 2px;
width: 300px;
margin: 30px 5px;
}
#inner {
background: #ee2f51;
height: 4px;
border-radius: 2px;
width: 1px;
transition: all 1s;
transform-origin: left;
transform: scaleX(100);
}
.on #inner{
transform: scaleX(300);
}
/*
//option pulse animation
#bar.on {
animation: pulse 1s ease-in-out;
}
#keyframes pulse {
0% {
opacity: .5;
}
50% {
opacity: 1;
}
100% {
opacity: .5;
}
} */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="bar">
<div id="inner"></div>
</div>
</div>
<button id="toggle">
toggle bar
</button>
If you remove opacity: 0.5 from #bar the problem goes away, but your colors are different. This version works fine on all browsers, but you'll have to tweak the rgba to your liking.
$('#toggle').click(function(e){
$('#bar').toggleClass('on');
});
body {
background: #222;
}
#bar {
background: rgba(153, 153, 153,0.65);
height: 4px;
border-radius: 2px;
width: 300px;
margin: 30px 5px;
}
#inner {
background: rgba(193, 16, 47, 0.65);
height: 4px;
border-radius: 2px;
width: 1px;
transition: all 1s;
transform-origin: left;
transform: scaleX(100);
}
.on #inner {
transform: scaleX(300);
}
/*
//option pulse animation
#bar.on {
animation: pulse 1s ease-in-out;
}
#keyframes pulse {
0% {
opacity: .5;
}
50% {
opacity: 1;
}
100% {
opacity: .5;
}
} */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="bar">
<div id="inner"></div>
</div>
</div>
<button id="toggle">
toggle bar
</button>

CSS Transition Not Returning To Original Shape & Can't Click Multiple Times

Here's the CodePen.
The square changes to a circle as expected when it slides to the right, but when it returns back to the left, it stays a circle instead of changing to a square.
Also, I can only click the <a> once. If I try to click multiple times, it doesn't work.
Trying to do this with only CSS (if possible).
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.shape:target {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The closest you can get with just CSS is this, as far as I know:
body {
margin-top: 30px;
background: gainsboro;
}
.container {
margin: auto;
width: 100%;
}
.path {
position: relative;
overflow: hidden;
width: 100%;
height: 80px;
x-background: white;
}
#keyframes ani {
0% {
left: 0;
}
50% {
left: 95%;
}
100% {
left: 0;
}
}
.path a:focus .shape {
border-radius: 50%;
transition: all .7s ease-in-out;
animation-name: ani;
animation-duration: 2s;
animation-direction: alternate;
animation-fill-mode: none;
}
.shape {
position: absolute;
left: 0;
background-color: slateblue;
width: 80px;
height: 80px;
display: block;
border-radius: none;
transition: border-radius .4s ease-out;
}
<div class="container">
<div class="path">
<span id="elem" class="shape"></span>
</div>
</div>
The problem before was triggering the state with :target:. This is tough to debug with sites like Codepen or other embedded editors, since you can't see the hash change. Basically, clicking the link would append #elem to the URL, apply the :target styles to .shape, and stay like that until the hash changes.
This solution uses :focus, which gets you closer to your goal, but not all the way. To repeat the animation, you need to defocus/blur the circle, then click it again.
I'm usually all for CSS-only effects, but I'm pretty sure you'll need Javascript for this. Something as simple as applying a class on click, waiting 2 seconds, then removing the class would accomplish the same effect more reliably.

Resources