css won't transition after jquery fade out - javascript

Using css media query and opacity transition, I have a div that fades in when viewport is less than 640px, and it fades out when viewport is wider.
Using jquery, I also have a button that when clicked will fade out the div.
The problem i have is that after the click/jquery fade out, the div will no longer fade back in when the viewport is changed.
I'd like the div to be able to transition back and forth 100%-0% opacity via viewport change even after the user has clicked the button to fade it out.
css:
#myDiv {
position: absolute; left: 0; top: 0; width: 100vw;
opacity: 0;
transition: opacity 1.5s;
}
#media screen and (max-width: 640px) {
#myDiv {
position: absolute; left: 0; top: 0; width: 100vw;
opacity: 1;
}
}
html:
<div id="myDiv">
<div id="closeBtn" onclick="xOut();">
</div>
</div>
script
xOut = function() {
$("#myDiv").fadeOut(2000);
});
}
It seems to me that the jquery is breaking the css. I can't figure out how to fix this.

This is happening because the fadeOut function adds display:none; to the element after it faded out, which will cause issues with css transitions.
Basically what you want to do is to use a class that hides it without using display: none; You can also use styles like height: 0; pointer-events:none; to further remove it from view.
The below snippet shows how using a css class to fade it out compares to the fade out function. I am not sure if this is the functionality you are looking for, but it should help you understand what is going on.
xOut = function() {
$("#myDiv").fadeOut(2000);
}
xOutCss = function() {
$("#myDiv").addClass('faded');
}
#myDiv {
transition: opacity 2s ease;
}
.faded {
opacity: 0;
}
#media screen and (max-width: 640px) {
#myDiv {
position: absolute;
left: 0;
top: 0;
width: 100vw;
opacity: 1;
}
#myDiv.faded {
opacity: 1;
}
#fade_out_btn {
display: none;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="myDiv">
<button onClick="xOut();">Fade Out</button>
<button id="fade_out_btn" onClick="xOutCss();">Fade Out Css</button>
</div>

Related

Better solution for animating width

I have a block over a text and i want to reveal the text and make the width of the block zero
I'm using gsap but as far as i know it is bad for performance to animate width,
and since i'm gonna use this animation quite a lot i'm worried to animate width
so is there is a better solution for my little problem ?
gsap.to('.block', {
duration: 1, width: 0, ease: Power4.easeIn}, 0.2);
h1 {
position: relative;
display: inline-block
}
.block {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
background: black;
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<h1>
hello world
<span class="block"></span>
</h1>
You can consider an animation using transform and have better performance
gsap.to('.block', {
duration: 1, transform: 'translateX(-100%)', ease: Power4.easeIn}, 0.2);
h1 {
position: relative;
display: inline-block;
overflow:hidden;
}
.block {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
background: black;
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<h1>
hello world
<span class="block"></span>
</h1>
The only thing I can think of to increase the performance while still using Gsap is to lower the duration of the width transition of the block, as well as lower the fps of the animation by adding gsap.ticker.fps('framerate') to the javascript.
the default framerate is 60 fps, so try changing it to anything lower than that. Though I'm not entirely sure if that would make a huge improvement.
gsap.ticker.fps(24);
//caps framerate at 24
gsap.to('.block', {duration: 0.5, width: 0, ease: Power4.easeIn}, 0.2);
h1 {
position: relative;
display: inline-block;
}
.block {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
background: black;
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js">
</script>
<h1>
hello world
<span class="block"></span>
</h1>
</body>
</html>
There definitely is a solution in animation properties of CSS. Using CSS instead of
JavaScript (JS) will delegate computing the animated values to the browser's layout engine instead of re-implementing them in your code.
At a high level your animation will be a from, to state where the from is full
width and to is 0 width. You express this with a #keyframe rule where you can animate ANY CSS property. This way you can combine #keyframes on different properties.
These are some good introductory notes about animations in CSS css-animation-101, using CSS animations
For you particular use case something like this should do
#keyframes unveil {
from {
width: 100%;
}
to {
width: 0%;
}
}
.block {
animation-name: unveil;
animation-duration: 1s;
animation-timing-function: ease-in;
}
Then you can either add the block class to the span directly in the HTML or use some JavaScript to toggle/add the class in response to an event.
You can use css animations:
function toggleAnimation() {
$('.block').toggleClass("animated");
}
h1 {
position: relative;
display: inline-block
}
.block {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
background: black;
width: 100%;
height: 100%;
}
#keyframes custom-animation {
from {
width: 100%;
}
to {
width: 0%;
}
}
.block.animated {
animation: custom-animation 1s ease-in 0.5s 1 normal forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>
hello world
<span class="block"></span>
</h1>
<button onclick="toggleAnimation();">Toggle animation</button>
In my sample, the block needs the animated class to actually animates. For the demo, I used a button to add this class.

css transition works in an element but not in a second element

I'm trying to build a simple image slider with css and javascript, I have an UL with some LI inside. the images are LI's backgrounds so I just have to move two LI, the active one and the next one, to make the slider work.
When the "next" button is pressed I add classes to the two LI and what happen is that the already visible li perform his transition disappearing on the left but the second LI snaps in position without sliding in from the right. I can't understand where i go wrong and why the second LI doesn't trigger the transition.
Here is a pen with some code:
https://codepen.io/luzzuc/pen/xONywP
HTML
<ul>
<li class="active" style="background-image: url(http://static.giantbomb.com/uploads/original/0/26/9780-itsahim.JPG)"></li>
<li style="background-image: url(http://vignette3.wikia.nocookie.net/fantendo/images/5/5b/NSMBDIY_Mario_Jump.png/revision/latest?cb=20100405031309)"></li>
</ul>
<br><br>
<button id="next">Next</button>
CSS
ul {
list-style-type: none;
margin: 0;
padding: 0;
width: 20%;
padding-top: 12%;
position: relative;
background: #000;
overflow: hidden;
}
li {
position: absolute;
visibility: hidden;
width: 100%;
padding-top: 60%;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
top: 0;
left: 0;
}
.active {
visibility: visible;
transition: left 2s;
}
.active-slide {
left: -100%;
}
.next {
left: 100%;
visibility: visible;
transition: left 2s;
}
.next-slide {
left: 0;
}
Javascript
var b = document.getElementById('next');
b.addEventListener('click', animate);
function animate() {
var a = document.querySelector('.active');
var b = document.getElementsByTagName('li')[1];
b.classList.add('next');
a.classList.add('active-slide');
b.classList.add('next-slide');
}
Kindly try this version: https://jsfiddle.net/urhn8b6k/
First of all, the initial status of the 2nd li is left: 0; and the css indicated that from left: 0; to left: 100%; with transition: left 2s; in .next, so you have to move transition: left 2s; to .next-slide
While doing b.addClass... a.addClass... b.addClass... that's simply doing b.addClass("next next-slide"), try put the second addClass into a setTimeout with delay 1ms should solve the problem
obviously once posted the question I found the solution. It turns out that to trigger the second transition a browser redraw is necessary. in order to make the browser to redraw the page a simple operation in an element is enough so I simply ask for offsetHeight of the element ad so the code that was:
b.classList.add('next');
a.classList.add('active-slide');
b.classList.add('next-slide');
became:
b.classList.add('next');
a.classList.add('active-slide');
var f = b.offsetHeight;
b.classList.add('next-slide');
and everything works fine

Moving the whole page to left and then right

i am looking for this kind of template . Moving the page to left and then page to right. Can anyone tell me how can i make this or is there any javascript example similar to this.
Create two <div>s, put them next to each other, make them take up the whole window, and change them as needed.
HTML:
<div class="left">left</div>
<div class="right">right</div>
CSS:
body {
margin: 0;
}
.left {
background-color: green;
bottom: 0;
left: 0;
position: fixed;
top: 0;
transition: width 1s;
width: 0;
}
.left.active {
width: 200px;
}
.right {
background-color: red;
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
transition: left 1s;
}
.right.active {
left: 200px;
}
JS (width jQuery):
$('.right').on('click', function() {
$('.left').toggleClass('active');
$('.right').toggleClass('active');
});
And here's a fiddle.
Using .toggle(effect,options,duration) method to moving the page to left to right.
// Set the effect type
var effect = 'slide';
// Set the options for the effect type chosen
var options = { direction: 'right' };
// Set the duration (default: 400 milliseconds)
var duration = 700;
$('#Id').toggle(effect, options, duration);
Taken via this link
If you want it to animate smooth on all devices you should use css transitions and transforms. Hiding and showing would be as basic as toggling a class then.
The example in jsfiddle
<style media="screen">
.wrapper {
width: 100%;
overflow: hidden;
}
.menu {
height: 100vh;
width: 100px;
background: #ABC;
color: white;
position: absolute;
left:0;
transition: transform 0.3s;
transform: translateX(-100px);
}
.content {
transition: transform 0.3s;
}
.active .menu {
transform: translateX(0);
}
.active .content {
transform: translateX(100px);
}
</style>
<button class="toggle">Toggle</button>
<div class="wrapper">
<div class="menu">
My menu
</div>
<div class="content">
My content
</div>
</div>
<script type="text/javascript">
document.querySelector('.toggle').addEventListener('click', function(event) {
event.preventDefault();
document.querySelector('.wrapper').classList.toggle("active");
});
</script>
NB! Supported from IE10. IE 9 will support without the animation and you probably should add the needed -ms-, -webkit-, -moz-, etc prefixes to support the older browsers if needed for transition and transform properties.
Also I advise not animating body or html with this method and put the content of page in the wrapper (in .content in the examples case). Moving body and html directly may lead to unpleasant surprises later.

fadeIn not working on nth-child(2)

Could someone have a look at my code. what it's suppose to do is animate the img tags using fadeIn and fadeOut but it only fades out the first img and doesn't fade in the second img. I think my css could be wrong and that's why the second image isn't showing Im not getting any errors
its an image on top of another image
jQuery
$(document).ready(function() {
$('.social-media a').on('mouseenter', function(e) {
$(this).find("img:nth-child(2)").fadeIn();
$(this).find("img:nth-child(1)").fadeOut()
});
})
HTML
<div class="social-media">
<a title="Share On Twitter" href="#">
<img alt="" src="images/icon_twitter.png" />
<img class="test" alt="" src="images/icon_twitter_active.png" />
</a>
</div>
CSS
.social-media {
padding-top: 20px;
width: 166px;
margin: 0 auto 10px auto;
}
.social-media a {
position: relative;
width: 55px;
height: 51px;
}
.social-media a img:nth-child(1) {
opacity: 1;
}
.social-media a img:nth-child(2) {
position: absolute;
left: 0; top: -33px;
opacity: 0;
z-index: 2;
}
Instead of hiding the second <img> element with zero opacity, you should use display: none instead:
.social-media a img:nth-child(2) {
position: absolute;
left: 0; top: -33px;
display: none;
z-index: 2;
}
http://jsfiddle.net/8vH4E/
However, I would strongly recommend using a simple CSS image sprite to achieve this effect, which doesn't require JS.
Update: Since OP asked if it is possible to do with CSS, I have modified the Fiddle to exclude the use of JS and simply rely on the use of CSS and pseudo-elements: http://jsfiddle.net/8vH4E/2/
.social-media a {
display: block;
position: relative;
width: 100px;
height: 100px;
background-image: url(http://placehold.it/200x200);
background-size: cover;
}
.social-media a::before {
background-image: url(http://placehold.it/200x200/4a7298/eeeeee);
background-size: cover;
content: '';
display: block;
opacity: 0;
pointer-events: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
-webkit-transition: all .25s ease-in-out;
transition: all .25s ease-in-out;
}
.social-media a:hover::before {
opacity: 1;
}
My strategy is rather simple:
Use background images instead. For sizing, I have used cover but you are free to use any sizing (absolute pixel/point sizes, relative percentage sizes or dynamically-computed sizes like cover, contain)
For the hover state, use an absolutely-positioned pseudo element that covers the entire <a> (by positioning it absolutely and with zero offset from all four directions). We don't need pointer events on the pseudo element, so we set it to pointer-events: none
When the <a> element is hovered on (targeted with the :hover selector), we toggle the opacity of the pseudo-element from 0 to 1. We declare the transition property on the pseudo-element to allow for smooth, browser-computed and JS-agnostic transition.
the sprite is good but does not give smooth fading animation (think that was the main reason, KDM, wasn't it?).
So let's fix existing code:
as the fadeOut() turns the element to the display: none; state, as the fadeIn() starts working when the element is display: none;. So let's turn the 2nd image in display: none; first;
We can omit the opacity at all for both images (relying on 1.0 as default); $.fadeIn/Out() use the opacity from the CSS as the start/end point of the animation. Of course you can set the opacity explicitly for each image if it's designed in such way;
display: inlibe-block; for the <a> is a good point because it contains inline elements which possibly can disappear (display: none;); that causes the the whole <a> disappearing and the mouseleave event firing with unexpected UI bugs.
Enjoy http://jsfiddle.net/8vH4E/1/ and thanks to Terry for the fiddle :)

Fullscreen black bg with opacity fadeIn/fadeOut

I´m trying to make a full screen black bg with opacity, it appears smoothly when the mouse enters to the body and fade out smoothly when the user leaves the body of the page (which is the whole nav content screen).
I´m trying doing it with this script:
$("body").bind('mouseover', function() {
$("#bg_black").fadeIn("slow", 0.33);
});
$("body").bind('mouseleave', function() {
$("#bg_black").fadeOut();
});
with this css:
#bg_black{
position: absolute;
z-index: 1;
background: black;
opacity: 0.5;
width: 100%;
height: 100%;
display: none;
}
But the fadeout doesn´t works and also the fadeIn is very quickly and heavy.
Any ideas to achieve it, to make it also IE compatible? (not using css3)
I got this working by adding a div to body.
<div id="bg"></div>
styled it with css
#bg {
// so if user scrolls it doesn't matter
position: fixed;
background-color: black;
// expand to height & width
height: 100%;
width: 100%;
margin: 0;
padding:0;
// hidden initially
opacity: 0;
}
body {
background-color: white;
}
javascript to fadeIn and fadeOut
$("#bg").hover(function() {
// should user hover in and out quickly stop animations
$(this).stop().animate({ opacity: 1 }, 1000);
}, function( ) {
// should user hover in and out quickly stop animations
$(this).stop().animate({ opacity: 0 }, 1000);
});
Demo here
Try with this one:
$(function(){
$("body").hover(function() {
$("#bg_black").fadeIn("slow");
},function(){
$("#bg_black").fadeOut("slow");
});
});

Categories