CSS transition not working when adding class via jquery - javascript

I am adding a class to show an image when the mouse is over a div, but the transition isnt working at all.
I am using opacity, I know that the visibily: hidden is not animable.
The code is in the snippet:
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
animation: opacity 2s;
}
.visible {
visibility: visible;
opacity: 1;
animation: opacity 2s;
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">

There's a bit of confusion as animation is being used, but animation will look for an #keyframes sequence to tell it what animation to run. In fact it looks as though we don't need a full CSS animation in this case, just a CSS transition.
I've added transition: all 2s in case you want to transition anything else in future, like the scale, but if you just want to stick with transitioning opacity you could do transition: opacity 2s instead.
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
/* animation: opacity 2s; */
transition: all 2s;
}
.visible {
visibility: visible;
opacity: 1;
/* animation: opacity 2s; */
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">

if you want to use animations check the docs. You need to use #keyframes
$(document).ready(function() {
$("#trigger").on("mouseenter", function () {
$("#imgPuffo").addClass("visible");
$("#trigger").on("mouseout", function () {
$("#imgPuffo").removeClass("visible");
});
});
});
#trigger {
height: 100px;
width: 100px;
background: red;
}
img {
opacity: 0;
animation: opacity 2s;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 2s ease-in-out;
}
.imgPuffo {
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">

How about a solution for css using a :hover, without jquery?
#trigger {
height: 100px;
width: 100px;
background: red;
}
#trigger:hover + .imgPuffo {
opacity: 1;
}
.imgPuffo {
opacity: 0;
height: 200px;
transition: opacity 2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="trigger"></div>
<img id="imgPuffo" class="imgPuffo" src="https://www.pinclipart.com/picdir/big/449-4499911_how-to-draw-papa-smurf-from-the-smurfs.png" alt="">

Related

Toggle animation on click of button using js

I'm trying to get a square to 'fold out' on click of a button -- kind of like a drop-down.
Right now I have this, but it doesn't seem to do anything...
function toggle() {
let classList = document.getElementById('box').classList;
if (classList.contains('expand')) {
classList.remove('expand');
classList.add('retract');
} else if (classList.contains('retract')) {
classList.remove('retract');
classList.add('expand');
}
}
#keyframes anim {
0%: {
visibility: hidden;
}
1%: {
visibility: visible;
max-height: 0px;
}
100%: {
visibility: visible;
max-height: 100px; /* or something bigger than we'll 'ever need' */
}
}
.expand .retract {
animation-name: anim;
animation-duration: 500ms;
animation-iteration-count: 1;
}
.expand {
animation-fill-mode: forwards;
}
.retract {
animation-direction: reverse;
animation-fill-mode: backwards;
}
#box {
background-color: red;
height: 0px;
visibility: hidden;
width: 50px;
}
<button onclick="toggle()">toggle</button>
<div id="box"></div>
Note, that I need to have visibility: hidden here!
How can I achieve this?
OK, your problem is solved. This tryit from W3Schools helped me a lot. I didn't need two class names. Also, as #tao said, there is no point in animating visibility (look at the comments below). Here is the CodePen pen with this code. I guess this is what you want, am I right?
const toggle = () => box?.classList.toggle('expand')
#box.expand {
height: 100px;
}
#box {
width: 50px;
height: 0;
overflow: hidden;
background: red;
transition: height 1s;
}
<button onclick="toggle()">toggle</button>
<div id="box"></div>

CSS transition fade in only the background not the child divs

I have this situation:
setTimeout(function() {
// Set BG image
var bg_content = document.querySelector('.content_top');
bg_content.style.background = "linear-gradient(0deg,#000 0,rgba(0,0,0,.7) 35%,rgba(0,0,0,.4) 50%,rgba(0,0,0,0) 100%),url(https://upload.wikimedia.org/wikipedia/commons/8/8f/Example_image.svg) no-repeat";
bg_content.style.backgroundSize = "cover";
bg_content.style.backgroundPosition = "center";
bg_content.classList.add("fade-in");
}, 1500);
.fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.5s;
}
#keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.main_header {
color: blue;
text-align: center;
font-size: 30px;
}
.content_top {
height: 300px;
}
<div class="content_top">
<div class="main_header"><span class="vertical_line"></span>
<p data-transkey="main_header_notrans"><span class="tino">Some header</span> <br> some text</p>
</div>
</div>
.content_top has a background-image, which I want to fade in when the page loads, but I do not want the .main_header to be affected aswell. Currently this leads to a flicker effect of the text in .main_header and looks bad.
Here is a working example: JsFiddle
Move the background to a new div inside of the .content_top element. This will create a new layer which we can animate without affecting the content.
Give .content_top and .main_header a position: relative value. This will make the .content_top a relative container, and give .main_header the possibility to use the z-index.
In the snippet below I've added a new element: .main_bg. This element will get the background image and the animation.
Give the .main_bg element a position: absolute;. This will allow you to overlay elements on top of each other, in this case .main_bg and .main_header.
setTimeout(function() {
// Set BG image
var bg_content = document.querySelector('.main_bg');
bg_content.style.background = "linear-gradient(0deg,#000 0,rgba(0,0,0,.7) 35%,rgba(0,0,0,.4) 50%,rgba(0,0,0,0) 100%),url(https://upload.wikimedia.org/wikipedia/commons/8/8f/Example_image.svg) no-repeat";
bg_content.style.backgroundSize = "cover";
bg_content.style.backgroundPosition = "center";
bg_content.classList.add("fade-in");
}, 1500);
.fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 0.5s;
}
#keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.main_bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.main_header {
position: relative;
color: blue;
text-align: center;
font-size: 30px;
z-index: 1;
}
.content_top {
height: 300px;
position: relative;
}
<div class="content_top">
<div class="main_bg"></div>
<div class="main_header"><span class="vertical_line"></span>
<p data-transkey="main_header_notrans"><span class="tino">Some header</span> <br> some text</p>
</div>
</div>

Play new css animation seamlessly

I created a simple HTML game, which disappears under the screen when I click on a moving box.
However, the animation that disappears starts at the original location, not where it was clicked.
I think 0% of the remove #keyframes should have the location of the click, but I couldn't find a way
How shall I do it?
(function () {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.remove(`f${target.dataset.id}`);
target.classList.add('f0');
target.classList.add('remove');
setTimeout(() => { stage.removeChild(target) }, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
0% {
transform: translateX(0);
}
100% {
transform: translateX(30vw);
}
}
#keyframes remove {
0% {
transform: translate(0);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
animation: moving infinite alternate;
}
.remove {
animation: remove 0.2s cubic-bezier(.68,-0.55,.27,1.55) forwards;
}
.f0 {
background-color: black;
animation-duration: 2s;
}
.f1 {
left: 5%;
bottom: 5%;
animation-duration: 2s;
background-color: red;
}
<div class="stage">
<div class="character f1" data-id="1"></div>
</div>
Change the first animation to consider left instead of translate then append both of them to the element initially and you simply toggle the animation-play-state when adding the remove class
(function() {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.add('remove');
setTimeout(() => {
stage.removeChild(target)
}, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
100% {
left:calc(95% - 50px);
}
}
#keyframes remove {
50% {
transform: translateY(-30vh);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background:red;
left: 5%;
bottom: 5%;
animation:
moving 2s infinite alternate,
remove 1s cubic-bezier(.68, -0.55, .27, 1.55) forwards paused;
}
.remove {
animation-play-state:paused,running;
background: black;
}
<div class="stage">
<div class="character f1" data-id="1"></div>
</div>
If your use case is to deal with a lot of such boxes and complexity, it's better to go with handling everything with pure JS but I tried to make this work with minimal changes in JS and CSS.
I have added comments to the new JS lines.
Also taken the liberty to have a separate class with name moving for animation moving so that we can remove it on click.
(function () {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.remove(`f${target.dataset.id}`);
target.classList.add('f0');
// remove the moving animation
target.classList.remove('moving');
// Get offsetWidth which is the half of width to substract later while calculating left for the target i.e our box.
const offsetWidth = parseInt(getComputedStyle(target).width)/2;
// e.clientX gives us the x coordinate of the mouse pointer
// target.getBoundingClientRect().left gives us left position of the bounding rectangle and acts as a good offset to get the accurate left for our box.
target.style.left = `${e.clientX -target.getBoundingClientRect().left - offsetWidth}px`;
target.classList.add('remove');
setTimeout(() => { stage.removeChild(target) }, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
0% {
transform: translateX(0);
}
100% {
transform: translateX(30vw);
}
}
#keyframes remove {
0% {
transform: translate(0vh);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
}
.moving{
animation: moving infinite alternate;
}
.remove {
animation: remove 0.2s cubic-bezier(.68,-0.55,.27,1.55) forwards;
}
.f0 {
background-color: black;
animation-duration: 2s;
}
.f1 {
left: 5%;
bottom: 5%;
animation-duration: 2s;
background-color: red;
}
<div class="stage">
<div class="character moving f1" data-id="1"></div>
</div>

CSS transition does not work on mobile

Please have a look at the animation below. While you may see that it works on PC, there must be something wrong since it does not work on mobile. For example on Android, the image is zoomed and with opacity 1 from the very beginning. I assume that the transition has been made but the duration was 0s. Thank you for your help.
$(document).ready(function(){
$(".photo").css(" -moz-transform", "scale(1.2)");
$(".photo").css("-webkit-transform", "scale(1.2)");
$(".photo").css("-o-transform", "scale(1.2)");
$(".photo").css("opacity", "1");
$(".photo").css("transform", "scale(1.2)");
});
.photo {
display: inline-block;
vertical-align:top;
max-width:100%;
opacity: 0.1;
-moz-transition: transform 40s, opacity 6s;
-webkit-transition: transform 40s, opacity 6s;
transition: transform 40s, opacity 6s;
}
.photoDiv {
display: inline-block;
background-color: #f1f1f1;
width: 100%;
position: relative;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="photoDiv">
<img class="photo" src="https://img-aws.ehowcdn.com/877x500p/s3-us-west-1.amazonaws.com/contentlab.studiod/getty/f24b4a7bf9f24d1ba5f899339e6949f3">
</div>
I think it's cleaner to remove the CSS from JS. Also jQuery is redundant and way too big for what you are trying to do here. Also make sure to add the JS at the end of the body. This way you are sure the content is loaded before JS will even be loaded.
window.addEventListener('load', function() {
var photos = document.getElementsByClassName('photo');
if( photos )
{
for( var i = 0; i < photos.length; i++ )
{
var photo = photos[i];
photo.classList.add('active');
}
}
});
.photo {
display: inline-block;
vertical-align:top;
max-width:100%;
opacity: 0.1;
/*ease-in-out is the animation, 2s is the delay/ pause*/
transition: transform 40s ease-in-out 2s, opacity 6s ease-in-out 2s;
transform: scale(1);
}
.active {
opacity: 1;
transform: scale(1.2);
}
.photoDiv {
display: inline-block;
background-color: #f1f1f1;
width: 100%;
position: relative;
overflow: hidden;
}
<div class="photoDiv">
<img class="photo" src="https://img-aws.ehowcdn.com/877x500p/s3-us-west-1.amazonaws.com/contentlab.studiod/getty/f24b4a7bf9f24d1ba5f899339e6949f3">
</div>

Inherit css value from body (parent) not working

I'm want to disable all css transitions using JavaScript. I added transition: none to the body (via JavaScript), but the elements in the body still have a transition.
Of course I can loop through all elements, and add transition = 'none';, but I'm sure there's a better way of temporary disabling the css transition of all elements. Here's a sample code:
JSFiddle
var sample = document.getElementById('sample');
sample.addEventListener('click', function() {
if (document.body.style.transition === 'none') {
document.body.style.transition = '';
} else {
document.body.style.transition = 'none';
}
})
#sample {
width: 200px;
height: 100px;
background: lawngreen;
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
<div id="sample">Hover over me to move
<br />Click to disable transition</div>
Add a new class name to the body or parent tag. Set transitions with the new parent selector .animated #sample:
<body class="animated">
<div id="sample"></div>
</body>
... and the styles:
#sample {
width: 200px;
height: 100px;
background: lawngreen;
}
.animated #sample {
transition: transform 500ms ease;
}
.animated #sample:hover {
transform: translateX(50px);
}
To disable animations of all children just remove the .animated class from the body or parent tag.
Modified fiddle: https://jsfiddle.net/xjxauu0h/1/
you'll want to use a class on body so you can turn it on and off.
var sample = document.getElementById('sample');
document.body.classList.add('transitioner');
sample.addEventListener('click', function() {
if (document.body.classList && document.body.classList.length) {
document.body.classList.remove('transitioner');
} else {
document.body.classList.add('transitioner');
}
console.log(document.body.classList);
})
#sample {
width: 200px;
height: 100px;
background: lawngreen;
}
.transitioner *{
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
<div id="sample">Hover over me to move
<br />Click to disable transition</div>
var sample = $('#sample');
var body = $('body');
sample.click(function() {
body.toggleClass('notransition notransform');
});
#sample {
width: 200px;
height: 100px;
background: lawngreen;
transition: transform 500ms ease;
}
#sample:hover {
transform: translateX(50px);
}
.notransition.notransform #sample {
background: HotPink;
}
.notransition * {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
.notransform * {
-webkit-transform: none !important;
-moz-transform: none !important;
-o-transform: none !important;
-ms-transform: none !important;
transform: none !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sample">Hover over me to move
<br />Click to disable transition</div>

Categories