visibility hidden after playing animation - javascript

I'm trying to add effects on modal.
I want to make like this:
When modal--show class added, visibility set to visible and opacity continues to grow 0% to 100%.
When modal--show class removed, opacity continues to decrease 100% to 0%, and after then, visibility set to hidden.
Showing modal animation works well, but hiding modal animation doesn't. When hiding animation plays, visibility becomes hidden immediately when animation starts.
How to set visibility: hidden after opacity: 0% with CSS or pure JS?
JSFiddle: https://jsfiddle.net/p1gtranh/1/
document.querySelector('.open').addEventListener('click', () => {
document.querySelector('.modal').classList.add('modal--show');
});
document.querySelector('.close').addEventListener('click', () => {
document.querySelector('.modal').classList.remove('modal--show');
});
.modal {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
visibility: hidden;
opacity: 0%;
}
.modal--show {
animation: show 0.5s both;
visibility: visible;
}
#keyframes show {
0% {
visibility: hidden;
opacity: 0%;
}
1% {
visibility: visible;
}
100% {
opacity: 100%;
}
}
<button class="open">open</button>
<div class="modal">
<button class="close">close</button>
</div>

I would probably scrap the whole animation and just make a simple transition instead.
In this case, transition is specified in a shorthand. The associated properties are:
transition-timing-function: ease-in-out - how the transition should be played, this value will play an easing fading transition when both opening and closing the modal.
transition-property: all - what property is associated with the transition. Since we are transitioning both the opacity and visibility-properties, using all will select both of these.
transition-duration: 0.5s - how long the transition should last.
More on the transition-shorthand here
document.querySelector('.open').addEventListener('click', () => {
document.querySelector('.modal').classList.add('modal--show');
});
document.querySelector('.close').addEventListener('click', () => {
document.querySelector('.modal').classList.remove('modal--show');
});
.modal {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
visibility: hidden;
opacity: 0%;
transition: all 0.5s ease-in-out;
}
.modal--show {
visibility: visible;
opacity: 100%;
}
<button class="open">open</button>
<div class="modal">
<button class="close">close</button>
</div>

Related

CSS trigger animation instead of using hover

Just have a quick question about how would I trigger CSS animation which is currently set for hover to be automatically executed.
I have tried applying the keyframe and the animation however the animation is already finished and is not transitioned although the transition is set correctly.
The example below only triggers the animation on hover, how would I make it trigger onload?
The expected result is an animation to be triggered when the page loads and should trigger only when the element is scrolled into view.
CSS and HTML Code
main {
padding: 5rem 0;
display: flex;
align-items: center;
justify-content: center;
}
main .carousel {
max-height: 500px;
overflow: hidden;
}
main .carousel figure {
height: 500px;
background: url("https://res.cloudinary.com/dqjhiewf1/image/upload/v1666092821/fullPagePrint/portfolio_fullpage_kg2c1w.png");
width: 550px;
background-size: cover;
background-position: top center;
transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
transition: all 8.5s ease, transform 0.5s ease;
}
main .carousel figure:hover {
background-position: bottom center;
cursor: pointer;
overflow: auto;
transform: perspective(1000px) rotateY(0) rotateX(0) rotate(0) scale(1) translate(0) translateY(0);
transition: all 8.5s ease, transform 0.5s ease;
}
<main>
<a href="https://axie-infinity-lp.vercel.app" target="_blank">
<div class="carousel">
<figure></figure>
</div>
</a>
</main>
View Entire Code on JSFiddle
ANIMATION ON PAGE LOAD
For this you can simply add the javascript code and one id to figure.
Here in example I added image_figure id and in javascript code I add one class pageEffect to that image_figure
Javascript - CSS - HTML Code
window.onload = function() {
document.getElementById('image_figure').className = 'pageEffect';
};
main {
padding: 5rem 0;
display: flex;
align-items: center;
justify-content: center;
}
main .carousel {
max-height: 500px;
overflow: hidden;
}
main .carousel figure {
height: 500px;
background: url("https://res.cloudinary.com/dqjhiewf1/image/upload/v1666092821/fullPagePrint/portfolio_fullpage_kg2c1w.png");
width: 550px;
background-size: cover;
background-position: top center;
transform: perspective(1000px) rotateY(-13deg) rotateX(5deg) rotate(1deg) scaleY(0.9) scaleX(0.95) translate(-3%) translateY(-3%);
transition: all 8.5s ease, transform 0.5s ease;
}
.pageEffect {
background-position: bottom center !important;
cursor: pointer !important;
overflow: auto !important;
transform: perspective(1000px) rotateY(0) rotateX(0) rotate(0) scale(1) translate(0) translateY(0) !important;
transition: all 8.5s ease, transform 0.5s ease !important;
}
<main>
<a href="https://axie-infinity-lp.vercel.app" target="_blank">
<div class="carousel">
<figure id="image_figure"></figure>
</div>
</a>
</main>
View My Code on JSFiddle
You need to write some javascript code to do that. Add a class to elements when document loaded.
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
Or you can use one of these plugins below:
https://wowjs.uk/
https://michalsnik.github.io/aos/

How can I keep element at last state of CSS animation? [duplicate]

This question already has answers here:
Maintaining the final state at end of a CSS animation
(5 answers)
Closed 5 months ago.
I have a page with a lot of interactivity going on. Clicking a button here changes the text and image over there... that kind of stuff. Just about everything is controlled by click handlers adding or removing CSS classNames to show or hide the appropriate content. Almost all of the animation is achieved with CSS transitions. Pretty straight forward.
But I have one element that requires a keyframe animation. Its default state is to be hidden until it's time for it to enter the UI... at which point it needs to have this CSS keyframe animation applied and stay in the last state the animation had it in.
For the sake of this example, let's just say that when Block A becomes visible (by clicking the button), the element in question, Block A1, needs to fade in (remember in my actual use case, the animation is more complicated and can't be achieved using transitions... it requires a keyframe animation) and then remain with the properties it had in the last frame of the animation: in this case opacity: 1 after the animation runs.
Right now, the only way I'm able to do this is to use javascript to set the opacity after the animation runs. This works but I can see it getting really messy/complicated when elements now have a style attribute overriding the styles set in the CSS rulesets. You can see this start to happen when you click the button again to hide the block and then AGAIN to show it... Block A1 is still set to opacity: 1 so the animation ha no effect after the 1st time around.
Is there a better way to do this?
const $btn = document.querySelector('button');
const $block = document.querySelector('.block-a');
const $blocka1 = document.querySelector('.block-a-1');
$btn.addEventListener('click', function() {
$block.classList.toggle("is-visible")
})
$blocka1.addEventListener('animationend', function() {
console.log('done');
this.style.opacity = 1;
})
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
button {
font-size: 32px;
margin-bottom: 24px;
cursor: pointer;
}
.block-a {
width: 25vw;
height: 50vh;
background-color: red;
padding: 20px;
color: #fff;
transform: translateY(150%);
transition: all .25s linear;
}
.block-a.is-visible {
transform: translateY(0);
transition: all .1s ease-in;
}
.block-a-1 {
font-size: 32px;
font-weight: bold;
color: white;
background-color: blue;
padding: 10px;
opacity: 0;
}
.block-a.is-visible .block-a-1 {
animation: fadeIn 2s linear 2s;
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<button>Do Block 1</button>
<div class="block-a">
<span class="block-a-1">Block A-1</span>
<h1>Block A</h1>
</div>
You can maintain the last animation frame using:
animation-fill-mode:forwards;
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode
const $btn = document.querySelector('button');
const $block = document.querySelector('.block-a');
$btn.addEventListener('click', function() {
$block.classList.toggle("is-visible")
})
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
button {
font-size: 32px;
margin-bottom: 24px;
cursor: pointer;
}
.block-a {
width: 25vw;
height: 50vh;
background-color: red;
padding: 20px;
color: #fff;
transform: translateY(150%);
transition: all .25s linear;
}
.block-a.is-visible {
transform: translateY(0);
transition: all .1s ease-in;
}
.block-a-1 {
font-size: 32px;
font-weight: bold;
color: white;
background-color: blue;
padding: 10px;
opacity: 0;
}
.block-a.is-visible .block-a-1 {
animation: fadeIn 2s linear 2s;
animation-fill-mode:forwards;
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<button>Do Block 1</button>
<div class="block-a">
<span class="block-a-1">Block A-1</span>
<h1>Block A</h1>
</div>
Set the animation property animation-fill-mode to forwards or add it to animation like animation: fadeIn 2s linear 2s forwards;

Clicking trough a visibility:hidden element

I made a div with 2 elements inside: an image and an another div (about). The image is hiding the about div.
Is that possible to make elements which are in the about div clickable when the image disappear with a hover property ?
Thanks in advance !
Also, here's my code but the elements aren't clickable
#logo {
opacity: 1;
visibility: visible;
margin-top: 12.5px;
-webkit-transition: opacity 600ms, visibility 600ms;
-o-transition: opacity 600ms, visibility 600ms;
-moz-transition: opacity 600ms, visibility 600ms;
transition: opacity 600ms, visibility 600ms;
}
.blue_border:hover #logo {
opacity: 0;
visibility: hidden;
}
.blue_border {
width: 625px;
height: 625px;
background-image: url("./border.png");
background-repeat: no-repeat;
background-position: 50%;
}
#about {
z-index: -1;
position: relative;
margin-top: -605px;
width: 600px;
height: 600px;
border-radius: 100%;
background-color: #25B8EE;
}
<div class="blue_border">
<img id="logo" src="./logo.png" />
<!-- Img is "on" the about div" -->
<div id="about">
I want to be clicked :-(
</div>
<div class="la-ball-scale-multiple">
<div></div>
<div></div>
<div></div>
</div>
</div>
I don't think I understand it completely, but you cannot click under another element but you can use CSS display: none attr or you do this in a fake way. You can listen to the top element for this and check other conditions on javascript.
As mentioned in the comments, you may can use the pointer-events: none on the overlay to cause it to not receive click events, and allow them to pass through.
function whoWasClicked(e) {
console.log(`${e.target.id} was clicked!`);
};
document.querySelector('#lowerElement').addEventListener('click', whoWasClicked);
document.querySelector('#upperElement').addEventListener('click', whoWasClicked);
#lowerElement {
background-color: rgb(128, 128, 128);
min-width: 25vw;
height: 100px;
text-align: center;
position: absolute;
top: 37vh;
left: 37vw;
z-index: 1;
}
#upperElement {
min-width: 25vw;
height: 100px;
text-align: center;
line-height: 50px;
position: absolute;
top: 37vh;
left: 37vw;
z-index: 2;
pointer-events: none;
}
<div id="lowerElement">Click Me</div>
<div id="upperElement">Overlay</div>
With my current code, I think the z-index: -1; in #about is the problem: #blue_border is an image background and it's upper my "about" div... So I'm trying to find a way to replace that background.
Edit:
Okay. I figured out that the element with z-index: -1; will never be clickable the way I want to.
So I decided to reverse everything: the logo has now the property z-index: -1; and the about div (which is upper now) is hidden until the hover trigger. I also changed my background image by a border.
My code now :
/*Under #about and visible*/
#logo {
z-index: -1;
}
.blue_border {
width: 600px;
height: 600px;
border: 15px solid #71d1f4;
border-radius: 100%;
/*background-image: url("./border.png");
background-repeat: no-repeat;*/
background-position: 50%;
}
/*Hidden first*/
#about {
opacity: 0;
visibility: hidden;
position: relative;
margin-top: -605px;
width: 600px;
height: 600px;
border-radius: 100%;
background-color: #25B8EE;
-webkit-transition: opacity 600ms, visibility 600ms;
-o-transition: opacity 600ms, visibility 600ms;
-moz-transition: opacity 600ms, visibility 600ms;
transition: opacity 600ms, visibility 600ms;
}
/*Unhidden on hover*/
.blue_border:hover #about
{
opacity: 1;
visibility: visible;
}
I didn't changed my html
Thanks anyway guys. It was my very first question and I'm glad that some of you already answered me !

Slide in absolute positioned Modal

I've created a background div that hosts a modal div.
I have set the modal div to have the css:
.modal {
opacity: 0.01;
top: 20px;
transition: all ease-in 200ms;
}
Then I created another class to add to it in order to show it
.modal-open {
top: 50px;
opacity: 1;
}
However, when the open class is added to the div, chrome shows the properties being striked out (a.k.a not taking effect or overridden).
See codepen for demonstration. You can click on the background to hide the modal again.
Why isn't it transitioning properly?
Because you placed .model-open before .modal in the CSS.
.modal {
position: absolute;
z-index: 101;
transition: all 300ms ease-in-out;
top: 20px;
opacity: 0.01;
width: 500px;
background-color: white;
left: 50%;
margin-left: -250px;
}
.modal-open {
top: 50px;
opacity: 1;
}
https://codepen.io/anon/pen/KvdZMa
you can use
.modal.modal-open {
top: 50px;
opacity: 1;
}
to override .modal{}
You should add !important to the .modal-open
.modal-open {
top: 50px !important;
opacity: 1 !important;
}
or make it like this to override .modal
.modal.modal-open {
top: 50px !important;
opacity: 1 !important;
}

Jumping of animation on empty space

HTML:
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
JS:
$('.button').on('mouseenter', function () {
$('.element').addClass('active');
}).on('mouseleave', function () {
$('.element').removeClass('active');
});
$('.element').on('mouseenter', function () {
$('.element').addClass('active');
}).on('mouseleave', function () {
$('.element').removeClass('active');
});
http://jsfiddle.net/e4p98cwb/1/
When you hover on the black element the blue one enters the screen. After that if you hover for a sec on empty space the blue one starts to escape the screen, but if you hover fast on the empty space that it occupied before two things might happen:
1. The blue one returns fully shown on screen
or
2. Jumps once or twice and proceeds to leave the screen
The same happens on hover and mouseover events as well. Why is this happening and is there a way around this behavior ?
The easiest way to get around any issues with JS is to just let CSS take care of it. If you add this to the :hover state it will work:
.button:hover + .element,
.element:hover {
-webkit-transform: translateX(0);
transform: translateX(0);
}
See below for an implementation. This saves you a ton of JS as well.
.wrap {
position: relative;
width: 600px;
height: 600px;
overflow: hidden;
border: 2px solid red;
}
.button{
width: 100px;
height: 50px;
display: block;
background: #333;
}
.element {
position: absolute;
top: 0;
right: 0;
z-index: 99999;
width: 500px;
height: 630px;
background: blue;
-webkit-transform: translateX(630px);
transform: translateX(630px);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.button:hover + .element,
.element:hover {
-webkit-transform: translateX(0);
transform: translateX(0);
}
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
Update
The reason this is happening is because the element itself is still occupying the same space. This has to do with translation not actually moving the element, but transforming it. Once you move your cursor off any of the activatable elements, it will retract, but as it's animating it still occupies that same space, making it possible to hover on that space and retrigger the animation. I believe it's because this transform is only fully applied after completing the animation. Let's test this theory:
.wrap {
position: relative;
width: 600px;
height: 600px;
overflow: hidden;
border: 2px solid red;
}
.button{
width: 100px;
height: 50px;
display: block;
background: #333;
}
.element {
position: absolute;
top: 0;
right: 0;
z-index: 99999;
width: 500px;
height: 630px;
background: blue;
right: -100%;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.button:hover + .element,
.element:hover {
right: 0;
}
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
In this one we are simply using absolute positioning and the issue goes away, meaning that the tranform is actually causing the element to still occupy the same space. Until animation concludes.

Categories

Resources