I'm trying to reduce the size of the icon-container (from 110px in 0% to 50px in 100%) when the animation "slide-bck-top" is on focus. I tried to pass &__icon-container {} inside #keyframes but it didnt work.
here is my scss file:
.button {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: none;
height: 150px;
width: 230px;
background-color: transparent;
outline: none;
&__icon-container {
width: 100px;
height: 100px;
border-radius: 50%;
color: color(white-0);
background-color: color(blue-150);
box-shadow: 0px 4px 4px color(black-0, 0.25);
padding: 20px;
cursor: pointer;
}
&__icon {
fill: currentColor;
width: 50px;
height: 50px;
}
&:focus {
animation: slide-bck-top 0.3s 1.5s cubic-bezier(0.47, 0, 0.745, 0.715) forwards;
}
#keyframes slide-bck-top {
0% {
transform: translateZ(0) translateY(0);
}
100% {
transform: translateZ(-400px) translateY(-200px);
}
}
}
The issue is #keyframes won't allow you to pass a selector, since it's meant for properties and SCSS won't compile it correctly nested. It would be like passing the selector in the color: attribute.
What you could do is pass the .button__icon-container into the :focus and move the #keyframes outside of the .button, since #keyframes is really a global scope item and SCSS/SASS will still render it outside of the .button anyway.
.button {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: none;
height: 150px;
width: 230px;
background-color: transparent;
outline: none;
&__icon-container {
width: 100px;
height: 100px;
border-radius: 50%;
color: color(white-0);
background-color: color(blue-150);
box-shadow: 0px 4px 4px color(black-0, 0.25);
padding: 20px;
cursor: pointer;
}
&__icon {
fill: currentColor;
width: 50px;
height: 50px;
}
&:focus {
animation: slide-bck-top 0.3s 1.5s cubic-bezier(0.47, 0, 0.745, 0.715) forwards;
.button__icon-container {
animation: make-small 0.3s 1.5s cubic-bezier(0.47, 0, 0.745, 0.715) forwards;
}
}
}
#keyframes slide-bck-top {
0% {
transform: translateZ(0) translateY(0);
}
100% {
transform: translateZ(-400px) translateY(-200px);
}
}
#keyframes make-small {
0% {
width: 110px;
height: 110px;
}
100% {
width: 50px;
height: 50px;
}
}
It compiles to this:
.button {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: none;
height: 150px;
width: 230px;
background-color: transparent;
outline: none;
}
.button__icon-container {
width: 100px;
height: 100px;
border-radius: 50%;
color: color(white-0);
background-color: color(blue-150);
box-shadow: 0px 4px 4px color(black-0, 0.25);
padding: 20px;
cursor: pointer;
}
.button__icon {
fill: currentColor;
width: 50px;
height: 50px;
}
.button:focus {
animation: slide-bck-top 0.3s 1.5s cubic-bezier(0.47, 0, 0.745, 0.715) forwards;
}
.button:focus .button__icon-container {
animation: make-small 0.3s 1.5s cubic-bezier(0.47, 0, 0.745, 0.715) forwards;
}
#keyframes slide-bck-top {
0% {
transform: translateZ(0) translateY(0);
}
100% {
transform: translateZ(-400px) translateY(-200px);
}
}
#keyframes make-small {
0% {
width: 110px;
height: 110px;
}
100% {
width: 50px;
height: 50px;
}
}
try using the max-height property.
#keyframes slide-bck-top {
0% {
transform: translateZ(0) translateY(0);
max-height:110px;
}
100% {
transform: translateZ(-400px) translateY(-200px);
max-height:50px
}
}
Related
Hi I was wondering if I could get any advice on how to do a animation such as this in react native: https://codepen.io/gayane-gasparyan/pen/jOmaBQK
It uses a mixture of keyframes, linear gradients but is a CSS based animation.
I have react-native-reanimated and native-base and can also leverage these modules if necessary.
Main CSS code:
.card {
background: #191c29;
width: var(--card-width);
height: var(--card-height);
padding: 3px;
position: relative;
border-radius: 6px;
justify-content: center;
align-items: center;
text-align: center;
display: flex;
font-size: 1.5em;
color: rgb(88 199 250 / 0%);
cursor: pointer;
font-family: cursive;
}
.card:hover {
color: rgb(88 199 250 / 100%);
transition: color 1s;
}
.card:hover:before, .card:hover:after {
animation: none;
opacity: 0;
}
.card::before {
content: "";
width: 104%;
height: 102%;
border-radius: 8px;
background-image: linear-gradient(
var(--rotate)
, #5ddcff, #3c67e3 43%, #4e00c2);
position: absolute;
z-index: -1;
top: -1%;
left: -2%;
animation: spin 2.5s linear infinite;
}
.card::after {
position: absolute;
content: "";
top: calc(var(--card-height) / 6);
left: 0;
right: 0;
z-index: -1;
height: 100%;
width: 100%;
margin: 0 auto;
transform: scale(0.8);
filter: blur(calc(var(--card-height) / 6));
background-image: linear-gradient(
var(--rotate)
, #5ddcff, #3c67e3 43%, #4e00c2);
opacity: 1;
transition: opacity .5s;
animation: spin 2.5s linear infinite;
}
#keyframes spin {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
a {
color: #212534;
text-decoration: none;
font-family: sans-serif;
font-weight: bold;
margin-top: 2rem;
}
I worked with this tutorial, and coded this:
Splitting();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: monospace;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: grey;
}
.circle {
transform-style: preserve-3d;
animation: animate 8s linear infinite;
}
.circle .char {
position: absolute;
top: 0;
left: 0;
background: blue;
color: red;
font-size: 4em;
padding: 5px 12px;
border-top: 4px solid black;
border-bottom: 4px solid black;
transform-style: preserve-3d;
transform-origin: center;
transform: rotateY(calc(var(--char-index) * 12deg)) translateZ(250px);
}
#keyframes animate {
0% {
transform: perspective(1000px) rotateY(360deg) rotateX(15deg);
}
100% {
transform: perspective(1000px) rotateY(0deg) rotateX(15deg);
}
}
<script src="https://unpkg.com/splitting/dist/splitting.min.js"></script>
<div class="circle" data-splitting>
Circle-Text-Animation-Effects-
</div>
Unfortunately, I realized that it doesn't work with Chrome and Firefox. They don't show the curvature. I tried to fix it with Autoprefixer, but it didn't help. Has anyone an idea how to solve this issue?
Here is how it should look like, and how it looks like with Safari:
There is an extra span around your letters that need to have transform-style: preserve-3d;
Splitting();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: monospace;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: grey;
}
.circle {
transform-style: preserve-3d;
animation: animate 8s linear infinite;
}
/* added this */
.circle > span {
transform-style: preserve-3d;
display: block;
}
/**/
.circle .char {
position: absolute;
top: 0;
left: 0;
background: blue;
color: red;
font-size: 4em;
padding: 5px 12px;
border-top: 4px solid black;
border-bottom: 4px solid black;
transform-style: preserve-3d;
transform-origin: center;
transform: rotateY(calc(var(--char-index) * 12deg)) translateZ(250px);
}
#keyframes animate {
0% {
transform: perspective(1000px) rotateY(360deg) rotateX(15deg);
}
100% {
transform: perspective(1000px) rotateY(0deg) rotateX(15deg);
}
}
<script src="https://unpkg.com/splitting/dist/splitting.min.js"></script>
<div class="circle" data-splitting>
Circle-Text-Animation-Effects-
</div>
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>
In the following pure CSS loading, the fore color is white so it doesn't show anything on the white screen. How to change the fore-color?
.lds-hourglass {
display: inline-block;
position: relative;
width: 120px;
height: 120px;
background-color: black;
}
.lds-hourglass:after {
content: " ";
display: block;
border-radius: 50%;
width: 0;
height: 0;
margin: 8px;
box-sizing: border-box;
border: 32px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-hourglass 1.2s infinite;
}
#keyframes lds-hourglass {
0% {
transform: rotate(0);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
50% {
transform: rotate(900deg);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
100% {
transform: rotate(1800deg);
}
}
<div class="lds-hourglass">Loading....</div>
Just need to set background-color to :before.
see Snippet:
.lds-hourglass {
display: inline-block;
position: relative;
width: 120px;
height: 120px;
}
.lds-hourglass:after {
content: " ";
background-color:black;
display: block;
border-radius: 50%;
width: 0;
height: 0;
margin: 8px;
box-sizing: border-box;
border: 32px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-hourglass 1.2s infinite;
}
#keyframes lds-hourglass {
0% {
transform: rotate(0);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
50% {
transform: rotate(900deg);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
100% {
transform: rotate(1800deg);
}
}
<div class="lds-hourglass">
Loading....
</div>
This animation uses borders to generate this shape, change these values to change color :
border: 32px solid #f00;
border-color: #f00 transparent #f00 transparent;
and to change the text loading.. color, just add this line color: #fff to your lds-hourglass style.
.lds-hourglass {
display: inline-block;
position: relative;
width: 120px;
height: 120px;
background-color: #fff;
color: #f00;
}
.lds-hourglass:after {
content: " ";
display: block;
border-radius: 50%;
width: 0;
height: 0;
margin: 8px;
box-sizing: border-box;
border: 32px solid #f00;
border-color: #f00 transparent #f00 transparent;
animation: lds-hourglass 1.2s infinite;
}
#keyframes lds-hourglass {
0% {
transform: rotate(0);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
50% {
transform: rotate(900deg);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
100% {
transform: rotate(1800deg);
}
}
<div class="lds-hourglass">Loading....</div>
Try replacing border-color: #fff transparent #fff transparent; with border-color: #fff black #fff black;
.lds-hourglass {
display: inline-block;
position: relative;
width: 120px;
height: 120px;
background-color: white;
}
.lds-hourglass:after {
content: " ";
display: block;
border-radius: 50%;
width: 0;
height: 0;
margin: 8px;
box-sizing: border-box;
border: 32px solid #fff;
border-color: #fff black #fff black;
animation: lds-hourglass 1.2s infinite;
}
#keyframes lds-hourglass {
0% {
transform: rotate(0);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
50% {
transform: rotate(900deg);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
100% {
transform: rotate(1800deg);
}
}
<div class="lds-hourglass">Loading....</div>
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,