How to get #keyframes opacity to change opacity every time on FireFox? - css

My goal is to create a dropdown that fades in every time its parent element is moused over.
And, I want to use the CSS #keyframe property to control the opacity.
See the below example. It works in IE and Chrome as expected (fade-in happens on every mouse over). But, in FireFox, the fade-in happens only on the first mouse over. How can I get the fade-in to happen every time in FireFox?
CodePen showing example:
http://codepen.io/anon/pen/IEBgb
(notice the green "Baz" text fades in)
HTML:
<div class="foo">Foo
<div class="bar">
<div class="baz">
Baz
</div>
</div>
</div>
CSS:
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#-moz-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.foo {
cursor: pointer;
background: #333;
color: #ededed;
height: 50px;
line-height: 50px;
position: relative;
text-align: center;
width: 200px;
font-size: 30px;
}
.bar {
width: 200px;
position: absolute;
top: 52px;
background: gray;
display: none;
padding: 20px 0;
}
.foo:hover .bar {
display: block;
}
.baz {
font-size: 50px;
color: green;
visibility: visible;
opacity: 1;
-webkit-animation: fadeIn 2s;
-moz-animation: fadeIn 2s;
-o-animation: fadeIn 2s;
animation: fadeIn 2s;
}

It can be done, but you will have to adjust a few things:
Working Example
#-webkit-keyframes fadeIn {
0% {
color: rgba(0, 128, 0, 0); /* transparent text color */
opacity: 0;
}
50% {
color: rgba(0, 128, 0, 0); /* transparent text color */
opacity:1;
}
100% {
color: rgba(0, 128, 0, 1); /* fade in text color */
opacity: 1;
}
}
#keyframes fadeIn {
0% {
color: rgba(0, 128, 0, 0);
opacity: 0;
}
50% {
color: rgba(0, 128, 0, 0);
opacity:1;
}
100% {
color: rgba(0, 128, 0, 1);
opacity: 1;
}
}
.foo {
cursor: pointer;
background: #333;
color: #ededed;
height: 50px;
line-height: 50px;
position: relative;
text-align: center;
width: 200px;
font-size: 30px;
}
.bar {
display:none;
width: 200px;
position: absolute;
top: 50px;
background: gray;
padding: 20px 0;
}
.baz {
font-size: 50px;
}
.foo:hover .bar {
display: block;
-webkit-animation: fadeIn 2s both; /* attach the animation to bar rather than baz */
animation: fadeIn 2s both;
}
Or if you're looking to fade in and fade out you could try something like this:
Working Example 2
Note that the second method uses pointer-events:none/auto so it may have compatibility issues in older browsers. Also seeing the fadeOut animation when the page first loads may be a problem.

Related

Continuous Box Rotate - CSS animation

So am fairly new in CSS animation and I wanted to ask a question I created this box and it as a small box inside that rotates from top to bottom, right to left and alternate but am wondering how can I make that it rotates fully around continuously, from the point of origin.
I tried setting the transform translateX to -232% once it reach back at the point of origin but end up not going back to its origin as intent.
<div class="parent">
<div class="child"></div>
</div>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 62.5%;
font-family: Arial, Helvetica, sans-serif;
}
body {
font-size: 1.22rem;
line-height: 1.2;
}
.parent {
background: #aed4ff;
height: 300px;
width: 300px;
}
.child {
background-color: rgb(143, 36, 36);
width: 90px;
height: 90px;
display: block;
}
.parent:hover .child {
animation: left-to-right 2s ease-in-out forwards;
animation-play-state: paused;
cursor: pointer;
}
#keyframes left-to-right {
0% {
transform: translateX(0);
color: red;
}
33% {
transform: translateY(232%);
}
50% {
background-color: blue;
}
66% {
transform: translateX(232%) translateY(232%);
}
100% {
transform: translateX(232%);
background-color: black;
}
}
</style>
You need to add another keyframe with translateX(0) at 100% to move the element back to the original position, and for the other "transform-keyframes" use 25%, 50% and 75% instead of 33%, 67% and 100%.
And of course animation-iteration-count: infinite; to keep it going round.
So that would be
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 62.5%;
font-family: Arial, Helvetica, sans-serif;
}
body {
font-size: 1.22rem;
line-height: 1.2;
}
.parent {
background: #aed4ff;
height: 300px;
width: 300px;
}
.child {
background-color: rgb(143, 36, 36);
width: 90px;
height: 90px;
display: block;
}
.parent:hover .child {
animation: left-to-right 3s ease-in-out forwards;
animation-iteration-count: infinite;
cursor: pointer;
}
#keyframes left-to-right {
0% {
transform: translateX(0);
color: red;
}
25% {
transform: translateY(232%);
}
50% {
transform: translateX(232%) translateY(232%);
background-color: blue;
}
75% {
transform: translateX(232%);
}
100% {
transform: translateX(0);
background-color: black;
}
}
<div class="parent">
<div class="child"></div>
</div>
You can set your animation to run continuously by adding this to your css
animation-iteration-count: infinite;

CSS, multiple animations on one element

I want to applay a flicker animation to one button when the page is loaded (after a small delay) AND the same animation when the button is hovered. However, only one of the animations works. When both animations are not commented out, the animation when the page is loaded works. When I comment out this animation, the hover animation works. I don't understand, why it's like that.
HTML Code:
<div class="container">
Hello
</div>
CSS Code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
background-image: linear-gradient(
to right bottom,
rgba(72, 80, 92, 0.444),
rgba(43, 43, 46, 0.757)
);
}
.btn:link,
.btn:visited {
text-decoration: none;
background-color: #fff;
color: rgb(70, 70, 70);
padding: 15px 40px;
display: inline-block;
border-radius: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn::after {
content: "";
display: inline-block;
height: 100%;
width: 100%;
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-color: #fff;
animation: flickerButton 0.4s 1s;
}
.btn:hover::after {
animation: flickerButton 0.4s;
}
#keyframes flickerButton {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
Thank you very much for your support.
The problem is that the same animation keyframes are set on the actual pseudo element and when the element is hovered.
CSS reckons that once it's run the animation it doesn't need to do it again.
Assuming a CSS-only solution is required, this snippet has two copies of the keyframes, one for the non hovered condition, which runs the once, and one for when it is hovered when it runs once but then when unhovered the pseudo element doesn't have the animation set any more etc.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
background-image: linear-gradient( to right bottom, rgba(72, 80, 92, 0.444), rgba(43, 43, 46, 0.757));
}
.btn:link,
.btn:visited {
text-decoration: none;
background-color: #fff;
color: rgb(70, 70, 70);
padding: 15px 40px;
display: inline-block;
border-radius: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn::after {
content: "";
display: inline-block;
height: 100%;
width: 100%;
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-color: #fff;
animation: flickerButton 0.4s 1s;
}
.btn:hover::after {
animation: flickerButton1 0.4s;
}
#keyframes flickerButton {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
#keyframes flickerButton1 {
0% {
transform: scaleX(1) scaleY(1);
opacity: 1;
}
100% {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
}
<div class="container">
Hello
</div>
You need to define the animation-iteration-count on the pseudo element. It's inheriting the default of running once (which happens on page load).
You can share the key-frames of flickerButton, but need to define infinite on the pseudo element so that it will loop forever on hover. You can do it shorthand on the single animation property, as follows:
.btn:hover::after {
animation: flickerButton 0.4s infinite;
}

Elements of my spinner also dim when I dim the entire page for a loading element

I have implemented a loading spinning icon which is overlaid on the page.
It looks fine but when I try to darken the entire page by using
background-color: rgba(0, 0, 0, 0.4);
in the .spinner-container element, the bands of the loading element dim also...
See these pictures...
I would like to keep these bright vibrant colors on top of the dimmed gray background.
Any ideas what I can implement to change this?
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
mix-blend-mode: overlay;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>
</body>
</html>
You are using mix-blend-mode: overlay; (documentation) on your .spinner-sector elements, which is blending the vibrant colours with the darkened page below.
Removing that gives you:
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>
Alternatively, to keep the blending effect, you could switch to an option that doesn't darken the loading animation, e.g. hard-light
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
mix-blend-mode: hard-light;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>

Animated icon moves left during keyframe

I created an animated arrow set in one icon. So far so good. However, it suddenly shifts to the left for a moment during the sequence which makes the whole animation shaky.
Here is the pen to see the animation in action:
https://codepen.io/erwinvanlun/pen/VxWQQy?editors=1100
Below the code. Any clue what is going on?
HTML:
<div style="font-size: 150px; line-height: 100%;
color: darkgrey;">
<i class="icon-fold"></i></div>
CSS:
i.icon-fold {
position: relative;
display: inline-block;
font-style: normal;
box-sizing: border-box;
}
i.icon-fold {
vertical-align: bottom;
margin: .1em .2em 0 .2em;
border: .3em solid transparent;
border-bottom-color: currentColor;
border-width: 0;
animation: scale 5s linear infinite;
animation-play-state: paused;
}
i.icon-fold:before, i.icon-fold:after {
content: "";
position: absolute;
box-sizing: border-box;
left: -.3em;
border: .3em solid transparent;
border-bottom-color: currentColor;
}
i.icon-fold:before {
top: -.9em;
transition: opacity 5s linear;
animation: fade 5s linear infinite;
animation-play-state: paused;
}
i.icon-fold:after {
top: -.6em;
}
i.icon-fold:hover, {
animation-play-state: running;
&:after, &:before {
// transform:translateY(-.1em);
animation-play-state: running;
}
}
#keyframes fade {
0% {
opacity: 1;
}
99% {
opacity: 0;
}
}
#keyframes scale {
0% {
left: .3em;
border-width: 0;
}
99% {
left: 0em;
border-width: .3em;
}
}
In keyframes please use 100% instead of 99%
#keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes scale {
0% {
left: .3em;
border-width: 0;
}
100% {
left: 0em;
border-width: .3em;
}
}

CSS - Animation triggers back when mouse hover

I'm working on a CSS slider animation.
Everything is pretty much done apart from one last thing:
The wanted behaviour is that if I hover over the slider thumb, the slider grows in height and the value moves in the centre of the slider. This works as expected, however when the slider thumb goes underneath the newly positioned value, it goes back to the previous size (basically reverting the animation).
I think that I need some sort of "pass-through", so that basically even if I'm not technically hovering on the slider, the value doesn't interfere at all with my animation.
I know, it is not clear at all, that's why I'm including a codepen to help you better understand what I mean. Change the slider and stop it at 29. Then try sliding again and you will see the wrong effect and what I mean.
https://codepen.io/NickHG/pen/NYOoXR?editors=0110
I'm also posting the code here for future reference: (note: is done using LESScss):
#temp0-14: #185fb6;
#temp15-19: #00bcd4;
#temp20-23: #ffc107;
#temp24-31: #ef6b52;
#gaps: 8, 4, 4, 15;
#temps: #temp24-31, #temp20-23,#temp15-19, #temp0-14;
#darkText: #000;
#lightText: #fff;
#percentage: 20%;
#desaturate-percentage: 40%;
.gaps-loop(#i, #prevgap) when (#i > 0) {
#gap: extract(#gaps, #i);
#temp: extract(#temps, #i);
.span-gen-loop(#j) when (#j < #gap) {
#k: #j + #prevgap;
.temp-#{k} {
display: block;
background: #temp;
color: contrast(#temp, #darkText, #lightText, #percentage);
&:hover {
//background: darken(#temp, 8%);
}
}
.temp-color-#{k} {
color: contrast(#temp, #darkText, #lightText, #percentage);
}
.span-gen-loop(#j + 1);
}
.span-gen-loop(0);
.gaps-loop(#i - 1, #prevgap + #gap);
}
.gaps-loop(length(#gaps), 0);
.animate-color-change {
transition: background 0.8s ease;
}
/* Slider custom style */
#entryHeight: 60px;
#sliderTrackHeight: 25px;
#sliderThumbHeight: #sliderTrackHeight;
#sliderThumbWidth: 25px;
.entry-external-container {
font-family: "Roboto", sans-serif;
height: #entryHeight;
min-height: #entryHeight;
width: 100%;
max-width: 400px;
display: block;
border: 1px solid black;
display: flex;
align-items: flex-end;
padding: 0;
margin: 0;
position: relative;
.dataName {
display: block;
width: 100%;
position: absolute;
top: 0;
transform: translateY(50%);
padding-left: 10px;
z-index: 2;
animation-timing-function: ease-out;
animation: dataNameIn 0.4s forwards;
}
.dataValue {
display: block;
width: 25px;
position: absolute;
top: 0;
text-align: right;
right: 10px;
transform: translateY(50%);
padding-right: 10px;
z-index: 2;
animation-timing-function: ease-in-out;
animation: dataValueZoomOut 0.1s forwards;
}
.slidecontainer {
width: 100%;
box-sizing: content-box;
.custom-slider {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: #sliderTrackHeight;
outline: none;
opacity: 0.7;
margin: 0;
animation: sliderAnimationBackgroundOut 0.3s;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: #sliderThumbWidth;
height: #sliderThumbHeight;
background: white;
cursor: pointer;
transition: height 0.25s, box-shadow 0.4s;
border: 1px solid rgba(0, 0, 0, 0.6);
box-sizing: border-box;
border-radius: 3px;
}
&:hover,
&:active {
&~.dataName {
animation: dataNameOut 0.4s forwards;
}
&~.dataValue {
animation: dataValueZoomIn 0.4s forwards;
&:hover{pointer-events:none;}
}
animation: sliderAnimationBackgroundIn 0.3s forwards;
&::-webkit-slider-thumb {
border-radius: 0px 3px 3px 0;
height: #entryHeight;
box-sizing: border-box;
border-right: 1px solid rgba(0, 0, 0, 0.5);
border-top: 1px solid rgba(0, 0, 0, 0.5);
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
border-left: none;
-webkit-box-shadow: -7px 0px 7px -2px rgba(0, 0, 0, 0.2);
-moz-box-shadow: -7px 0px 7px -2px rgba(0, 0, 0, 0.2);
box-shadow: -7px 0px 7px -2px rgba(0, 0, 0, 0.2);
background: -webkit-gradient(
linear,
-20 0,
100% 0,
from(transparent),
to(white),
color-stop(80%, white)
);
}
}
}
}
}
#keyframes sliderAnimationBackgroundIn {
0% {
opacity: 0.7;
height: #sliderTrackHeight;
}
100% {
opacity: 1;
height: #entryHeight;
}
}
#keyframes sliderAnimationBackgroundOut {
0% {
opacity: 1;
height: #entryHeight;
}
100% {
opacity: 0.7;
height: #sliderTrackHeight;
}
}
#keyframes dataNameOut {
0% {opacity: 1;top: 0}
20% {opacity: 0;top: -15px}
100% {top: -40px;opacity: 0}
}
#keyframes dataNameIn {
0% {top: -40px;opacity: 0}
20% {opacity: 0;top: -15px}
100% {opacity: 1;top: 0}
}
#keyframes dataValueZoomIn {
0% { transform: scale(1); top: 5px; right: 7.5px;}
25% { transform: scale(1.2); top: 10px; right: 10px;}
50% { transform: scale(1.3); top: 15px;right: 11px;}
75% { transform: scale(1.4); top: 20px;right: 13px;}
100% { transform: scale(1.5);top: 20px;right: 13.7px;}
}
#keyframes dataValueZoomOut {
100% { transform: scale(1); top: 5px; right: 7.5px;}
75% { transform: scale(1.2); top: 10px; right: 10px;}
50% { transform: scale(1.3); top: 15px;right: 11px;}
25% { transform: scale(1.4); top: 20px;right: 13px;}
0% { transform: scale(1.5);top: 20px;right: 13.7px;}
}
use pointer-events to prevent an element from being hovered :
The pointer-events CSS property specifies under what circumstances (if
any) a particular graphic element can become the target of mouse
events.
.dataValue {
pointer-events: none;
}
PEN
You could achieve the same effect setting the hover state to the parent.
PEN
.slidecontainer {
width: 100%;
box-sizing: content-box;
&:hover {
.custom-slider {
...
}
}
}
Note: Is not a good practice to nest more than 3 levels deep,

Resources