CSS only - Make an animation happen in 3 steps - css

Code sandbox link: https://codesandbox.io/s/thirsty-moon-853e2k?file=/src/App.js:0-278
I want the pink circle to move in steps but it keeps moving in continuous fashion:
I tried using steps(3) steps(3,end) but none of that is working:
.Spinner {
height: 100vh;
width: 100vw;
background-color: gray;
display: flex;
align-items: center;
justify-content: center;
}
.DotLoader {
display: flex;
flex-direction: row;
column-gap: 0.5rem;
position: relative;
}
.DotLoader section {
height: 1rem;
aspect-ratio: 1;
border-radius: 50%;
background-color: #e5e4e5;
}
.DotLoader div {
position: absolute;
height: 1rem;
aspect-ratio: 1;
border-radius: 50%;
background-color: pink;
left: 3rem;
animation: moveSpinner 1s steps(3, end) infinite;
}
#keyframes moveSpinner {
0% {
left: 0;
}
50% {
left: 1.5rem;
}
100% {
left: 3rem;
}
}
<div class="Spinner">
<div class="DotLoader">
<div></div>
<section></section>
<section></section>
<section></section>
</div>
</div>
Can someone help me understand this and fix it?

.DotLoader div {
animation: moveSpinner 1s steps(3) infinite;
}
#keyframes moveSpinner {
0% {
left: 0;
}
100% {
left: 112%;
}
}

From what I understand... If you want to make the pink circle "move and stop" on each gray circles, you can simply delete steps(3, end). There is no need for it it just smoothly slides from one dot to another.
But if the request is making pink one just jump instead of slide, then you do not need another <div> for that, just create animations for your <section> elements individually. Light them up as pink and make them gray again.

Related

How to make an element disappear and stay gone after hovering over it?

So here is my code...
I understand how to make the text disappear by making it transparent but i want it to stay gone after hovering over it so it doesnt come back - how do I accomplish this?
.disappear {
margin-top: 60px;
text-align: center;
transition: all 5s ease .3s;
font-family: Bungee Spice;
}
.disappear:hover {
color: transparent;
}
you need to use onmouseover and remove() like this
function bye() {
const dis = document.getElementById("dis");
dis.remove();
}
* {
padding: 0;
margin: 0;
/* border: 1px solid red; */
overflow-x: hidden;
}
div {
height: 50vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
font-size: xx-large;
overflow: auto;
background: lightblue;
}
<div class="div">
<h2 onmouseover="bye()" id="dis">will go on hover</h2>
</div>
I don't think it's possible to make it run smoothly with pure CSS, so far, this is what I think is close to what you want to accomplish. So before hover, the animation to make it gone is already set, but the animation is not running yet, the animation will run only if the element is hovered. The problem here is that when it's hovered then it's unhovered before it's gone, the element will be half gone as the animation is paused.
.container {
width: 100%;
height: 800px;
background: #dddddd;
}
.disappear {
margin-top: 60px;
text-align: center;
font-family: Bungee Spice;
background: yellow;
animation: example 5s linear forwards;
animation-play-state: paused;
}
.disappear:hover {
animation-play-state: running;
}
#keyframes example {
from {opacity: 1}
to {opacity: 0}
}
<div class="container">
not disappear
<div class="disappear">
DISAPPEAR
</div>
</div>
The better way would be to use javascript and use onmouseover to add the animation instead of using :hover, the difference is that when you onmouseout, the function is still executed (the animation persists). This is with JS:
function fade(elm) {
elm.style.animation = "example 5s linear forwards";
}
.container {
width: 100%;
height: 800px;
background: #dddddd;
}
.disappear {
margin-top: 60px;
text-align: center;
font-family: Bungee Spice;
background: yellow;
}
#keyframes example {
from {
opacity: 1
}
to {
opacity: 0
}
}
<div class="container">
not disappear
<div class="disappear" onmouseover="fade(this)">
DISAPPEAR
</div>
</div>

Make alert box overlap content

I try to make the alert boxes overlap on my content but every time it always shows and pushes down my content.
I do not have a z-index anywhere else also change position everything absolute, relative, and fixed but nothing working One time it was working then when I saved it's gone.
here is my code.
return (
<Alert
dismissible
show={this.state.show}
variant={variant}
onClose={this.handleClose}>
<div className='container'>
<Alert.Heading>{heading}</Alert.Heading>
<p className='alert-body'>{message}</p>
</div>
</Alert>
)
}
}
.alert {
align-items: center;
animation: .5s ease-in-out 0s 1 light-bounce-in;
bottom: 1rem;
display: flex;
// left: 0;
margin: auto;
max-width: 30rem;
position: absolute;
top: 30px;
left: 20px;
right: 20px;
// right: 0;
z-index: 1;
.alert-body {
margin: auto 0;
}
}
.close {
&:active,
&:focus {
outline: none;
}
}
#keyframes light-bounce-in {
0% {
opacity: 0;
transform: translateY(20%);
}
50% {
transform: translateY(-5%);
}
100% {
opacity: 1;
transform: translateY(0%);
}
}
z-index: 1 seems to be a low value. Try something like z-index: 100 or z-index: 1000 or more. I'd check names of classes also.

Multiple rotation directions using CSS rotateX()

I've got a simple display that flips over on click. I want to add a little bounce to the movement by rotating a few degrees in the opposite direction before rotating the full 180 degrees to reveal the opposite side.
RotateX() will accept more than one instance inline, but it calculates the end result and does not show both directions. ie:
transform: rotateX(-10deg) rotateX(190deg)
this results in the object rotating 180deg.
I've tried comma separating them, as well as just putting two sets of degress in the parens, with similar results.
I've tried putting both steps into #keyframes, but animation doesn't seem to work with my on-click event in javascript.
I've also tried having each direction of rotation in a separate class that are both activated via classlist.toggle, but still do not see both directions of rotation.
here's a codepen with the above mocked up:
https://codepen.io/Boreetos22/pen/WNrJEvR
I'd appreciate any insight. Thanks!
Transitions probably won't get what you want since you can't fake the bounce with multiple steps. #keyframes will work but you can't simply toggle the class. You need to add one and then add another to reset it.
Also, you'll need multiple animations (forward and back) that you change on over/out and click.
let sides = document.querySelector('.sides');
sides.addEventListener( 'click', function(e) {
if(sides.classList.contains('flip-forward')){
sides.classList.remove('flip-forward');
sides.classList.add('flip-backward');
}else{
sides.classList.add('flip-forward');
sides.classList.remove('flip-backward');
}
});
* {
padding: 0;
margin: 0;
}
h2 {
margin-top: 12px;
font-size: 30px;
}
body {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
.container {
display: flex;
justify-content: center;
height: 60px;
width: 400px;
perspective: 1000px;
}
#keyframes myAnimationFwrd {
/* has bounce */
24% {
transform: rotateX( -40deg)
}
36% {
transform: rotateX( 0)
}
100% {
transform: rotateX( 190deg)
}
}
#keyframes myAnimationBkwrd {
/* no bounce add more steps to enable */
0% {
transform: rotateX( 190deg)
}
100% {
transform: rotateX( 0deg)
}
}
.flip-forward {
animation: myAnimationFwrd 1s forwards;
}
.flip-backward {
animation: myAnimationBkwrd 1s forwards;
}
.sides {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
position: relative;
transform-style: preserve-3d;
cursor: pointer;
}
.red, .black {
text-align: center;
color: white;
height: 100%;
width: 100%;
border-radius: 30px;
box-shadow: 2px 2px 4px black;
position: absolute;
backface-visibility: hidden;
}
.red {
background-color: darkred;
z-index: 2;
}
.black {
background-color: black;
z-index: 1;
transform: rotateX(180deg);
}
<div class="container">
<div class="sides">
<div class="red">
<h2>PLAYER ONE'S TURN</h2>
</div>
<div class="black">
<h2>PLAYER TWO'S TURN</h2>
</div>
</div>
</div>

Bug in html <marquee> style CSS animation

Here is a short codepen of a simple css animation that I'm struggling to work with. Code also below:
.navscroll {
width: 100%;
height: 100px;
padding: 5px;
overflow: hidden;
position: relative;
background-color: red;
}
.navscroll div {
position: relative;
width: 200px;
height: 100%;
line-height: 50px;
text-align: center;
background-color: blue;
opacity: 1;
border-radius: 5px;
transform: translateX(100%);
animation: navscroll 15s linear infinite;
}
#keyframes navscroll {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
}
<div class="navscroll">
<div>Why arent these</div>
<div>Side by side</div>
<div>or sliding across the WHOLE navbar</div>
</div>
Its supposed to be a scrolling navbar of divs, but I'm having two issues:
The inner divs are stacking vertically, not horizontally...
The inner divs are scrolling across only a small percentage of the nav bar / outer div...
Ideally, if there were many divs in the navscroll div, only 5-6 of them would display anytime on the screen, although the navbar would always be scrolling and those other divs would make their way onto the screen eventually. (similar to stock tickers ticking across the top of the TV screen). Any help with this is appreciated, thanks!!
div is a block level element (means it has display: block; by default). These create a line break before and after themselves. Use display: inline-block; and make sure they align properly using vertical-align: middle;.
2nd problem: translateX(100%) here the percentage does not refer to the parent element, but to the div being animated.
.navscroll {
width: 100%;
height: 100px;
padding: 5px;
overflow: hidden;
position: relative;
background-color: red;
white-space: nowrap;
}
.navscroll div {
position: relative;
width: 200px;
height: 100%;
line-height: 50px;
text-align: center;
background-color: blue;
opacity: 1;
border-radius: 5px;
transform: translateX(100%);
animation: navscroll 15s linear infinite;
/* this does the magic: */
display: inline-block;
vertical-align: middle;
}
#keyframes navscroll {
0% {
left: 100%;
}
100% {
left: -100%;
}
}
<div class="navscroll">
<div>Why arent these</div>
<div>Side by side</div>
<div>or sliding across the WHOLE navbar</div>
</div>
As per your question about how to create a snippet here:
The inner divs are stacking vertically because the default styling for a div is display: block. Adding the styles display: inline-block; vertical-align: top; to your .navscroll div rules will set them side by side, aligned to their top edges.
The animation is starting in the middle, and not all the way to the right like you intend because of how transform: translate() works. transform refers to the object being transformed, not its parent. So, translating something 100% of it refers to the width of the object. Try animating the position, something like this instead:
#keyframes navscroll {
0% {
left: 100%;
}
100% {
left: -600px;
}
}
EDIT: Also, remove the initial transform: translateX(100%); and you can simply animate the left position to -600px (3x the width of the each block).

CSS Animations using just Opacity and Transform

I read an interesting article the other day and I've been trying to apply it in my workflow.
https://blog.gyrosco.pe/smooth-css-animations-7d8ffc2c1d29#.5a2q978fv
One of the concepts that are mentioned is the idea of only animating elements with opacity and transform. I've been implementing this idea over the last few days and find it pretty awesome.
One issue I've come across is if an element is at opacity 0 the containing parent will still apply the space of the child element. I tried to remove the space with scaling the child element to almost nothing but the space is still persistent.
I was curious if anyone has worked in this manner and has advice on how to animate a parent element to grow with the child element?
function showHiddenBox() {
let hiddenBox = document.querySelector('.hiddenbox')
hiddenBox.setAttribute('data-state', hiddenBox.getAttribute('data-state') === 'hidden' ? 'visible' : 'hidden');
}
.parentbox {
width: 200px;
background-color: #564d49;
}
.showingbox {
display: flex;
align-content: flex-start;
align-items: center;
justify-content: center;
width: 100%;
height: 100px;
background-color: #63cdff;
}
.hiddenbox {
width: 100%;
height: 100px;
transition: all 1s;
background-color: pink;
}
.hiddenbox[data-state="hidden"] {
opacity: 0;
transform: scaleY(.1) translateY(-50px);
transform-origin: top;
}
.hiddenbox[data-state="visible"] {
opacity: 1;
}
<div class="parentbox">
<div class="showingbox">
<button onclick="showHiddenBox()">Click Me</button>
</div>
<div class="hiddenbox" data-state="hidden"></div>
</div>
To further explain myself I've created this snippet. I want to create an animation with just opacity and transform where the brown of the parent element doesn't show but the parent will expand when the child is created.
function showHiddenBox() {
let hiddenBox = document.querySelector('.hiddenbox')
hiddenBox.setAttribute('data-state', hiddenBox.getAttribute('data-state') === 'hidden' ? 'visible' : 'hidden');
}
.parentbox {
width: 200px;
background-color: #564d49;
}
.showingbox {
display: flex;
align-content: flex-start;
align-items: center;
justify-content: center;
width: 100%;
height: 100px;
background-color: #63cdff;
}
.hiddenbox {
width: 100%;
height: 100px;
transition: all 1s;
background-color: pink;
}
.hiddenbox[data-state="hidden"] {
max-height: 0;
transform: scaleY(.1) translateY(-50px);
transform-origin: top;
}
.hiddenbox[data-state="visible"] {
max-height: 300px;
}
<div class="parentbox">
<div class="showingbox">
<button onclick="showHiddenBox()">Click Me</button>
</div>
<div class="hiddenbox" data-state="hidden"></div>
</div>
Use max-height instead of opacity. Over exaggerate the max-height. Depends on how it will work for you. Is this what you want?

Resources