Smoothing a sharp disappearing for transient div - javascript

I have created a box to toggle between appearing and disappearing via a toggle button.
The problems are:
The first time, the appearing height is sharp and not smooth.
The disappearing height is happening sharp and at the end instead of smooth.
I am not a web expert. All I have written are what I have got from different places and assembled. Please feel free to fix any other CSS/JS mistakes too. But the above issues are what I am mainly looking for.
function toggle_elem()
{
var elem = document.getElementById('elemid');
if(elem.style.display == 'none')
{
elem.style.display = 'block';
window.setTimeout(function(){
elem.style.opacity = 1;
elem.style.transform = 'scale(1)';
elem.style.height = '100px';
},0);
}
else
{
elem.style.transform = 'scale(0)';
window.setTimeout(function(){
elem.style.display = 'none';
elem.style.height = '0';
}, 300);
}
}
#elemid {
border: 1px solid black;
opacity: 0;
transform: scale(0);
transition: height 0.3s, width 0.3s, padding 0.3s, visibility 0.3s, 0.3s ease opacity, opacity 0.3s ease-out, 0.3s ease transform;
}
<div>
<button onclick="toggle_elem()">Toggle</button>
</div>
<div id="elemid" style="display:none">aaaaa</div>
<div>
<button >Next button</button>
</div>

You're almost there for the smooth transition in disappearing animation.
The only thing you need to modify is this
elem.style.transform = 'scale(0)';
//this is to support the css animation
elem.style.height = '0'; //move your height set outside of `setTimeout`
window.setTimeout(function(){
//only set `display` none after the animation completed
elem.style.display = 'none';
}, 300);
Full code
function toggle_elem() {
var elem = document.getElementById('elemid');
if (elem.style.display == 'none') {
elem.style.display = 'block';
window.setTimeout(function() {
elem.style.opacity = 1;
elem.style.transform = 'scale(1)';
elem.style.height = '100px';
}, 0);
} else {
elem.style.transform = 'scale(0)';
elem.style.height = '0';
window.setTimeout(function() {
elem.style.display = 'none';
}, 300);
}
}
#elemid {
border: 1px solid black;
opacity: 0;
transform: scale(0);
transition: height 0.3s, width 0.3s, padding 0.3s, visibility 0.3s, 0.3s ease opacity, opacity 0.3s ease-out, 0.3s ease transform;
}
<div>
<button onclick="toggle_elem()">Toggle</button>
</div>
<div id="elemid" style="display:none">aaaaa</div>
<div>
<button>Next button</button>
</div>

Related

Else statement doesn't work in "Click" event when I try to toggle

I'm a beginner at Javascript and I've been having trouble trying to toggle the size of my 3d carousel menu that I have created.
The menu starts large in the centre of the screen and I would like it to shrink and move to the top-left corner when I click on it and when I click it again it will enlarge and go back to its initial position.
Right now, the way the big menu shrinks and moves to the top-left corner is working just as I wished, however, the else statement inside my cellTransform() function is not executing so it's not returning to its original state when clicked again.
JS Fiddle:
https://jsfiddle.net/jcou6gre/3/
Below is my code:
HTML:
<html>
<head>
<title>carousel menu</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<script src="jquery-3.4.1.min.js"></script>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="menu-wrapper">
<div class="menu">
<div class="carousel" id="carousel">
<!-- cell 1 -->
<div class="carousel-cell cell1" id="carousel-cell">
<div class="cell-text-wrapper">
<div class="cell-text">
Upload image
<br>
Save
<br>
Submit
</div>
</div>
</div>
<!-- cell 2 -->
<div class="carousel-cell cell2" id="carousel-cell">
<div class="cell-text-wrapper">
<div class="cell-text">
Gallery
</div>
</div>
</div>
<!-- cell 3 -->
<div class="carousel-cell cell3" id="carousel-cell">
<div class="cell-text-wrapper">
<div class="cell-text">
TIPS
</div>
</div>
</div>
<!-- cell 4 -->
<div class="carousel-cell cell4" id="carousel-cell">
<div class="cell-text-wrapper">
<div class="cell-text">
About
</div>
</div>
</div>
</div>
</div>
</div>
<script type="module" src="app.js"></script>
</body>
CSS:
.menu-wrapper {
width: 100vw;
height: 100vh;
position: absolute;
}
.menu {
width: 500px;
height: 300px;
position: relative;
perspective: 1000px;
left:30vw;
top:30vh;
}
.carousel {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: all 0.5s linear;
transform: rotateZ(-20deg) rotateY(25deg) rotateX(-30deg) ;
}
.carousel-cell {
position: absolute;
width: 500px;
height: 300px;
}
.cell-text-wrapper{
width: 100%;
height:100%;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.cell-text{
font-size: 20px;
font-family: arial ;
}
.cell1 {
background-color: red;
opacity: 0.3;
transform: rotateY( 0deg) rotateX( 10deg) translateZ(250px);
}
.cell2 {
background-color: blue;
opacity: 0.3;
transform: rotateY( 90deg) translateZ(300px);
}
.cell3 {
background-color: green;
opacity: 0.3;
transform: rotateY( 180deg) rotateX( 10deg) translateZ(250px);
}
.cell4 {
background-color: yellow;
opacity: 0.3;
transform: rotateY(270deg) translateZ(300px);
}
JS:
// TOGGLE LARGE SMALL MENU
$(".menu").click(function() {
if ($(".carousel-cell").height() != 30) {
$(".carousel-cell").animate({
height: 30,
width: 50,
}, 1000);
$(".cell-text").animate({
fontSize: "10px"
}, 1000);
} else {
$(".carousel-cell").animate({
height: 300,
width: 500,
}, 1000);
$(".cell-text").animate({
fontSize: "20px"
}, 1000);
}
});
function cellTransform() {
var cell1 = document.querySelector(".cell1");
var cell2 = document.querySelector(".cell2");
var cell3 = document.querySelector(".cell3");
var cell4 = document.querySelector(".cell4");
if (cell1.style.transform != "translateZ(50px)") {
cell1.style.transition = "transform 1.0s linear 0s";
cell1.style.transform = "rotateY(0deg) rotateX(10deg) translateZ(50px)";
cell2.style.transition = "transform 1.0s linear 0s";
cell2.style.transform = "rotateY(90deg) translateZ(50px)";
cell3.style.transition = "transform 1.0s linear 0s";
cell3.style.transform = "rotateY(180deg) rotateX(10deg) translateZ(50px)";
cell4.style.transition = "transform 1.0s linear 0s";
cell4.style.transform = "rotateY(270deg) translateZ(50px)";
document.querySelector(".menu").style.transition = "all 1s ease-in 0s";
document.querySelector(".menu").style.left = "8vw";
document.querySelector(".menu").style.top = "10vh";
document.querySelector(".carousel").style.transition = "all 1s ease-in 0s";
document.querySelector(".carousel").style.width = "10%";
document.querySelector(".carousel").style.height = "10%";
} else if (cell2.style.transform == "translateZ(50px)") {
cell1.style.transition = "transform 2.5s ease-in 1s";
cell1.style.transform = "rotateY(0deg) rotateX(10deg) translateZ(250px)";
cell2.style.transition = "transform 2.5s ease-in 1s";
cell2.style.transform = "rotateY(90deg) translateZ(300px)";
cell3.style.transition = "transform 2.5s ease-in 1s";
cell3.style.transform = "rotateY(180deg) rotateX(10deg) translateZ(250px)";
cell4.style.transition = "transform 2.5s ease-in 1s";
cell4.style.transform = "rotateY(270deg) translateZ(300px)";
document.querySelector(".menu").style.transition = "all 1s ease-in 0s";
document.querySelector(".menu").style.left = "30vw";
document.querySelector(".menu").style.top = "30vh";
document.querySelector(".carousel").style.transition = "all 1s ease-in 0s";
document.querySelector(".carousel").style.width = "100%";
document.querySelector(".carousel").style.height = "100%";
}
}
document.querySelector(".menu").addEventListener("click", cellTransform, false);
Any helps is appreciated! Thanks in advance!
As Sergio has said, the transform value does not only contain the translateZ property but also other properties, you should use the includes() or indexOf() function. includes() works fine here easier to read, though. This code works in your JSFiddle:
if (!cell2.style.transform.includes("translateZ(50px)")) {
cell1.style.transition = "transform 1.0s linear 0s";
cell1.style.transform = "rotateY(0deg) rotateX(10deg) translateZ(50px)";
cell2.style.transition = "transform 1.0s linear 0s";
cell2.style.transform = "rotateY(90deg) translateZ(50px)";
cell3.style.transition = "transform 1.0s linear 0s";
cell3.style.transform = "rotateY(180deg) rotateX(10deg) translateZ(50px)";
cell4.style.transition = "transform 1.0s linear 0s";
cell4.style.transform = "rotateY(270deg) translateZ(50px)";
document.querySelector(".menu").style.transition = "all 1s ease-in 0s";
document.querySelector(".menu").style.left = "8vw";
document.querySelector(".menu").style.top = "10vh";
document.querySelector(".carousel").style.transition = "all 1s ease-in 0s";
document.querySelector(".carousel").style.width = "10%";
document.querySelector(".carousel").style.height = "10%";
} else if (cell2.style.transform.includes("translateZ(50px)")) {
cell1.style.transition = "transform 1s ease-in 0s";
cell1.style.transform = "rotateY(0deg) rotateX(10deg) translateZ(250px)";
cell2.style.transition = "transform 1s ease-in 0s";
cell2.style.transform = "rotateY(90deg) translateZ(300px)";
cell3.style.transition = "transform 1s ease-in 0s";
cell3.style.transform = "rotateY(180deg) rotateX(10deg) translateZ(250px)";
cell4.style.transition = "transform 1s ease-in 0s";
cell4.style.transform = "rotateY(270deg) translateZ(300px)";
document.querySelector(".menu").style.transition = "all 1s ease-in 0s";
document.querySelector(".menu").style.left = "30vw";
document.querySelector(".menu").style.top = "30vh";
document.querySelector(".carousel").style.transition = "all 1s ease-in 0s";
document.querySelector(".carousel").style.width = "100%";
document.querySelector(".carousel").style.height = "100%";
}
The changes I made are:
change the conditions to use includes function instead of equals symbols. Also for future uses, in JS you should use === and !== instead of == and !=. This is due to JS interpreting all values as truthy and falsy if == and != are used. This can lead to some confusing situations like if ("false" == true) {..} // <- code in if statement is executet. This is advanced knowledge, for further reading take a look at this.
use the same cell to check the transform value.
change the transformation duration in the else to transform 1s ease-in 0s to make it more smooth (optional). Without this you'll have a two step animation with first zooming in on the menu and then rearange them to have a squarey arrangement instead of a hashtagy arrangement.
In addition to that, I'd recommend to put all the styles in matching css classes. On button click you can then toggle a css class for an element. JQuery has a method for this.
This makes the code more readable because you don't merge style and logic code. Also it helps you to track the different styles you apply for each state.
If you log cell2.style.transform you get
""
"rotateY(90deg) translateZ(50px)"
You should test if it includes the translate property, not if it's exact match.
Actually, you are having the same issue in the first IF statement as it also is empty or it's a string with 3 properties.
You should use String.includes() method or String.indexOf() (indexOf has full support, includes doesn't).

Add animation when opening & closing Div element

I have this page with menu-link (#navBtn), and #mobileLinks div that opens and closes when clicking #navBtn.
I would like to add fade-in animation when #mobileLinks div is opened, and fade-out animation when the #mobileLinks div is closed. I would like to achieve this with pure JavaScript.
I managed to insert the fade-in animation already, but don't know how to add the fade-out animation as well.
var content = document.getElementById("mobileLinks");
var button = document.getElementById("navBtn");
button.onclick = function(){
if(content.className == "open"){
content.className = "";
content.animate([{opacity:'0.0'}, {opacity:'1.0'}],
{duration: 1500, fill:'forwards'})
} else{
content.className = "open";
}
};
#navBtn
#mobileLinks {
display: none
}
#mobileLinks.open {
display: flex;
}
You can handle the styles entirely in CSS, and only toggle a class with Js.
With CSS & Js
const menu = document.getElementById("menu")
function toggleMenu() {
menu.classList.toggle("isOpen");
}
#menu {
opacity: 0;
transition: opacity 0.2s ease-out;
}
#menu.isOpen {
opacity: 1;
}
<a onClick="toggleMenu()">menu</a>
<nav id="menu">
<a>link</a>
<a>link</a>
</nav>
Or with JS only
const menu = document.getElementById("menu")
menu.style.opacity = '0'
menu.style.transition = "opacity 0.2s ease-out"
function toggleMenu() {
// Toggle between 0 and 1
menu.style.opacity ^= 1;
}
<a onClick="toggleMenu()">menu</a>
<nav id="menu">
<a>link</a>
<a>link</a>
</nav>
You can achieve it using jquery effect
To show your element, use fadeIn() and to hide an element, you can use fadeOut()
<script>
$(document).ready(function(){
$("button").click(function(){
$("#div1").fadeIn();
$("#div2").fadeOut();
$("#div3").fadeToggle();
});
});
</script>
You can do it with JS. You can change the opacity of the element to hide it and along with css transition property to make fade effect
var container = document.getElementById("container")
function clicked() {
if (container.style.opacity == 0) {
container.style.opacity = 1
}
else {
container.style.opacity = 0
}
}
#container {
opacity: 0;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-ms-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
<div id="container">Some Text</div>
Submit

Simple css transition doesn't work

I have some problem with repeating animation in Firefox and Chrome.
I use simple js to make it repeatable.
(function step() {
setTimeout(function() {
var coin7 = document.getElementById('coin7');
coin7.style.display = 'block';
coin7.style.height = "210px";
}, 2000)
setTimeout(function(){
coin7.style.display = "none";
coin7.style.height = "0";
},6000);
setTimeout(step, 7000)
})();
Demolink http://jsfiddle.net/pe461zrn/
First iteration is ok in all browsers, but second and next doesn't apply css transition in FF39 and latest Chrome. And it's still work fine at all iteration in IE11.
How can I fix it?
try applying height with timeout 0 so you are sure it happens after display is set to block (which is something that would prevent animation)
setTimeout(function(){coin7.style.height = "210px";}, 0);
Try this..
Just remove coin7.style.display = 'none'; and thats the solution
HTML
<div id="coin7" style="">
<img src="http://us.cdn4.123rf.com/168nwm/kristijanzontar/kristijanzontar1101/kristijanzontar110100013/8612198-.jpg" />
</div>
CSS
#coin7 {
overflow: hidden; display: block; height: 0px;
-moz-transition: all 3s ease-in-out;
-webkit-transition: all 3s ease-in-out;
-o-transition: all 3s ease-in-out;
-ms-transition: all 3s ease-in-out;
transition: all 3s ease-in-out;
}
Javascript
(function step() {
setTimeout(function() {
var coin7 = document.getElementById('coin7');
coin7.style.display = 'block';
coin7.style.height = "210px";
}, 2000)
setTimeout(function(){
coin7.style.height = "0px";
},6000);
setTimeout(step, 7000)
})();
Check out this Fiddle

How to ignore an transition based on javascript

Heyy guys,
At first I want to apologize for my bad english.
I am making an site wich you can find here for the moment: http://rekenopjetoekomst.nl/test/test.html
When you scroll down the height of the foto under the menu will decrease. But the arrows that you need to navigate trough the slideshow have to disappear also. I am doing that by changing the opacity to 0 with a transition.
But my problem is that when you scroll down and then scroll fast up (a second or something) you will still see the arrows (with an opacity of 0.6 or something). Soo.. What I want is: When the arrows are out of the screen the opacity must be 0 without an transition. And if you scroll back to the foto the arrows have to appear with an transition.
Thnx for all your help!
Javascript (with only the arrows 1 and 2):
function yScroll(){
pijl1 = document.getElementById('pijl1');
pijl2 = document.getElementById('pijl2');
yPos = window.pageYOffset;
if(yPos > 100 && yPos < 370){
pijl1.style.opacity = "0.8";
pijl2.style.opacity = "0.8";
} else if(yPos > 370){
pijl1.style.opacity = "0.0";
pijl2.style.opacity = "0.0";
}
}
var animateInterval = setInterval(yScroll,10);
CSS:
#mainbox #foto #pijl1 {
transition: opacity 1s ease-in 1.3s;
}
#mainbox #foto #pijl2 {
transition: opacity 1s ease-in 1.3s;
}
I would use a tri-state setup.
the first state is the visible (normal) one. The second is the fading state, the opacity is set to 0, and there is a transition on it. The third one is the out state. in this one, we set the opacity to 0, but without delay.
To manage this, we create 3 classes, and asign each one according to the scroll level
demo with extended timings so it is easier to see
function yScroll(){
ele = document.getElementById('test');
yPos = window.pageYOffset;
if(yPos > 200){
ele.className = "out";
} else if(yPos > 100){
ele.className = "fading";
} else {
ele.className = "normal";
}
}
var animateInterval = setInterval(yScroll,10);
#test {
height: 50px;
width: 100px;
margin-top: 300px;
background-color: green;
}
.pusher {
margin: 3000px;
}
.out {
opacity: 0.1;
transition: opacity 0.1s;
}
.fading {
opacity: 0.2;
transition: opacity 20s;
}
.normal {
opacity: 1;
transition: opacity 20s;
}
<div id="test"></div>
<div class="pusher"></div>

JavaScript display none after CSS3 animation

I have div with id='mainmenu'. I'm adding CSS3 transition to it by JavaScript after button click (by adding 'transition' to #mainmenu and by creating class .fadein and .fadeout that will be added to the div element). Code:
<div id='mainmenu'></div>
<button id="btn1">Click me1</button>
<button id="btn2">Click me2</button>
#mainmenu {
width:100px;
height:100px;
background:#eee;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
}
.fadeout {
opacity:0;
}
.fadein {
opacity:1;
}
var menu = document.getElementById('mainmenu'),
btn1 = document.getElementById('btn1'),
btn2 = document.getElementById('btn2');
btn1.addEventListener('click', function() {
menu.className = 'fadeout';
}
btn2.addEventListener('click', function() {
menu.className = 'fadein';
}
The problem is that now I want to add display none and block to fadeout and fadein option. So after the fadeout animation div should get display none, and after fadein display block:
btn1.addEventListener('click', function() {
menu.className = 'fadeout';
menu.style.display = 'none';
}
btn2.addEventListener('click', function() {
menu.className = 'fadein';
menu.style.display = 'block';
}
Unfortunately, the display none and block executes with the animation, so the animation isn't working (element gets display none, without the opacity animation). I want first the animation with opacity, and after that display none/block for the element. Is there any way to do it? I can use only pure JavaScript (no jQuery etc.).
You need to use setTimeout() with menu.style.display = "none"; in order to let fade do it's job before you trigger style.display.
btn1.addEventListener('click', function() {
menu.className = 'fadeout';
setTimeout(function() {
$(menu).css('display', 'none');
}, 1000);
}
btn2.addEventListener('click', function() {
menu.className = 'fadein';
setTimeout(function() {
$(menu).css('display', 'block');
}, 1000);
}
Although this is an old post, for future visitor's sake, you can use the transitionend event. You can use:
/*For when object has fully faded*/
menu.addEventListener("transitionend", function() {
if (this.className == "fadeout") {
this.style.display = "none";
}
}.bind(menu));
/*Show before animation starts*/
menu.addEventListener("click", function() {
this.style.display = "block";
}.bind(menu));
I could be wrong here, however i believe you need to add a transition-end trigger that does the display:block / display:none change.
see: CSS3 transition events
I use height 0 instead of display none for some cases but It may or may not apply for what you need. Anyway here's the code:
1) Using transitions (looks like jQuerys fadeOut):
.fadeOut{
opacity : 0;
height : 0;
transition : opacity 800ms, height 0 800ms;
}
if you want you can add width 0 too.
.fadeOut{
opacity : 0;
width : 0;
height : 0;
transition : opacity 800ms, height 0 800ms, width 0 800ms;
}
2) Using animations (it works but transitions is better):
.fadeOut{
animation : fadeout 800ms linear forwards;
}
#keyframes fadeout{
99%{
opacity : 0;
height : initial;
}
100%{
opacity : 0;
height : 0;
}
}

Categories