JavaScript animation hide element using jquery - javascript

In the website that I am building, I have a div inside another div. When a header is clicked, the inner div should dissapear/reappear. But it's quite ugly to just change the opacity and height, so I want to add some animation so that the inner div does not just suddenly appear but "creates" the needed space in the outer div (with animation) and at the same time is reappearing (with animation). How can I achive that?
$("#d1H").click(function() {
var element = document.getElementById("d2");
if(element.style.opacity == "0") {
element.style.opacity = "1";
element.style.height = "auto";
}
else{
element.style.opacity = "0";
element.style.height = "0";
}
});
#d1{
border: 2px solid #333;
}
#d2{
border: 2px solid #000;
margin: 1rem;
}
#placeholder{
height: 100px;
}
<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="d1">
<h1 id="d1H">This is the outer div.</h1>
<div id="d2">
<h1">This is the inner div.</h1>
<div id="placeholder"></div>
</div>
</div>

If you are using jQuery, you can use .fadeIn()/.fadeOut() or .fadeToggle().
$("#d1H").click(function() {
$("#d2").fadeToggle();
});

You can use the CSS property transition, which determines the amount of time it takes to change a CSS property. Just as a simple example to make everything transition, add this to your CSS:
* {
transition: 1s;
}
You can also do this with specific properties. Some examples are given here

Related

Why is my animation "replayed" when an element is added via innerHTML?

I have a little script that adds a div named "doge" using innerHTML when clicking on a button on my page, and on this page there's a div with a CSS keyframes animation.
However, when I click on the button to add the div named "doge" on my page, the CSS animation is "replayed". Why? How can I fix that?
function addHtml() {
document.getElementById("wow").innerHTML += '<div class="doge">such wow</div>';
}
#keyframes color {
10% {
background: #4CAF50;
}
50% {
background: #3F51B5;
}
100% {
background: #009688;
}
}
.myDiv {
background: #000;
color: #fff;
animation: color 1s;
}
.doge {
background: #F57F17;
}
<div id="wow">
<div class="myDiv">Hi!</div>
<br>
<button onclick="addHtml()">Add HTML!</button>
</div>
JSFiddle
It's because you're modifying all of the element's HTML when you modify the .innerHTML property.
According to MDN:
.innerHTML - Removes all of element's children, parses the content string and assigns the resulting nodes as children of the element.
In doing so, the DOM assumes that the .myDiv element has just been added which means that the animation is going to be replayed. To work around that, use the .appendChild() method instead:
Updated Example
var div = document.createElement('div');
div.textContent = 'such wow';
div.className += 'doge';
document.getElementById("wow").appendChild(div);
Alternatively, as Teemu points out, you can also use the .insertAdjacentHTML() method:
Updated Example
document.getElementById("wow").insertAdjacentHTML('afterend', '<div class="doge">such wow</div>');

Animating height property :: HTML + CSS + JavaScript

I have noticed this 'issue' lately when trying some stuff.
Say I want to create a drop-down menu or an accordion.
This is my HTML:
<div class="wrapper" onclick="toggle()">
I want to be animated!
<div class="content">
Was I revealed in a timely fashion?
</div>
</div>
Stylesheets:
.wrapper {
background: red;
color: white;
height: auto;
padding: 12px;
transition: 2s height;
}
.content {
display: none;
}
.content.visible {
display: block;
}
JavaScript:
function toggle () {
var content = document.getElementsByClassName('content')[0];
var test = content.classList.contains('visible');
test ? content.classList.remove('visible') :
content.classList.add('visible');
}
I am trying to achieve a nice, smooth animation when we toggle the state of the content. Obviously this does not work. Anyone can explain to me why it does not work and how to fix it? Many thanks.
Link to the JSFiddle.
First things first, some CSS properties CANNOT be transitioned, display is one of them, additionally only discrete values can be transitioned, so height: auto cannot as well.
In your case the problem is with height: auto, while there are a few hacks for doing this, if you are just showing and hiding stuff, why not add, and use jQuery's toggle instead?
$(".content").toggle("slow");
jsFiddle
--EDIT (without jQuery)--
Because it's the auto that is giving us problems, we can use javascript to replace auto with a value in pixels and then use the css transition normally, if your content doesn't have a scroll, we can easily take that value from the scrollHeight property:
function toggle () {
var content = document.getElementsByClassName('content')[0];
var test = content.classList.contains('visible');
console.log(test);
if (test) {
content.classList.remove('visible')
content.style.height = "0px";
} else {
content.classList.add('visible');
content.style.height = content.scrollHeight + "px";
}
}
Css
.wrapper {
background: red;
color: white;
height: auto;
padding: 12px;
transition: 2s height;
}
.content {
height: 0px;
display: block;
transition: 2s height;
overflow: hidden;
} /* totally removed .content.visible */
jsFiddle

Toggling Between a CSS class with pure javascript on 'n' elements

Working on creating functionality where when the user clicks on one of the products (each of the elements have the same assigned ID card-reveal) it adds a CSS class to the container specifically clicked (active state) to show information for that specific item and then finally, when the user clicks the cancel button the CSS class is removed (activate state gone).
Unfortunately I have run to a few hiccups where when I click on the 1st element it adds the class to that element but the other elements I click do not add the class, as well the close button does not function at all. I would like to finish the solution in Pure Javascript. Also if you see a few classie() methods, I am using Classie.js to help with CSS class toggling.
Any help will be appreciated! Thank You!
Html
<a id="card-reveal" class="card-view" href="javascript:void(0)"><h3 class='hover-title'>View More</h3></a>
<div class="card-cover">
<span class="card-exit"></span>
<a class="card-follow" href="javascript:void(0)">Follow {{object.product_website_name}}.com</a>
<a class="card-buy" target="_blank" href="{{object.product_slug_url}}">Buy {{object.product_name }}</a>
<a id="card-close" class="card-info" href="javascript:void(0)"><span class="icon-indie_web-03"></span></a>
<ul class="card-social">
<label>Share</label>
<li><span class="icon-indie_web-04"></span></li>
<li><span class="icon-indie_web-05"></span></li>
</ul>
</div>
CSS
.card-cover {
width:100%;
height: 100%;
background: none repeat scroll 0% 0% rgba(255, 91, 36, 0.9);
color: #FFF;
display: block;
position: absolute;
opacity: 0;
z-index:200;
overflow: hidden;
-webkit-transform:translate3d(0, 400px, 0);
transform:translate3d(0, 400px, 0);
-webkit-backface-visibility:hidden;
backface-visibility: hidden;
-webkit-transition-property:opacity, transform;
transition-property:opacity, transform;
-webkit-transition-duration:0.2s;
transition-duration:0.2s;
-webkit-transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.card-cover.card--active {
opacity: 1;
-webkit-transform:translate3d(0, 0, 0);
transform:translate3d(0, 0px, 0);
}
JS below:
var cardContainer = document.querySelector('.card-cover'),
cardTargets = Array.prototype.slice.call( document.querySelectorAll( '#card-reveal' ) ),
eventType = mobilecheck() ? 'touchstart' : 'click',
cardClose = document.getElementById('card-close'),
resetMenu = function() {
classie.remove( cardContainer, 'card--active' );
},
resetMenuClick = function( ) {
cardCloseaddEventListener(globalMenuEventType, function() {
resetMenu();
document.removeEventListener(eventType, resetMenuClick);
}, false);
};
cardTargets.forEach(function (element, index) {
if( element.target ) {
element.addEventListener(eventType, function( event ) {
event.preventDefault();
event.stopPropagation();
classie.add(cardContainer, 'card--active');
document.addEventListener(eventType, resetMenuClick);
} ,false);
}
});
There are two simple ways I can think of doing something like this.
First, if you can't designate ID's for each card (which it sounds like you can't), you're going to have to go by class names. Like it was mentioned in the comments, you really don't want to use the same ID for multiple elements.
Part of the reason for this is, as you can see from my examples below, that the .getElementById() method is only meant to return one element, where the other methods like .getElementsByClassName() will return an array of elements.
The problem we're trying to solve is that the sub-content you want to display/hide has to be attached to the element you click somehow. Since we're not using ID's and you can't really rely on class names to be unique between elements, I'm putting the div with the information inside a container with the element that toggles it.
Inside a container div, are two divs for content. One is the main content that's always visible, the other is the sub-content that only becomes visible if the main content is clicked (and becomes invisible when clicked again).
The benefit of this method is that since there are no ID's to worry about, you can copy/paste the cards and they'll each show the same behaviour.
var maincontent = document.getElementsByClassName("main-content");
// Note: getElemenstByClassName will return an array of elements (even if there's only one).
for (var i = 0; i < maincontent.length; i++) {
//For each element in the maincontent array, add an onclick event.
maincontent[i].onclick = function(event) {
//What this does is gets the first item, from an array of elements that have the class 'sub-content', from the parent node of the element that was clicked:
var info = event.target.parentNode.getElementsByClassName("sub-content")[0];
if (info.className.indexOf("show") > -1) { // If the 'sub-content' also contains the class 'show', remove the class.
info.className = info.className.replace(/(?:^|\s)show(?!\S)/g, '');
} else { // Otherwise add the class.
info.className = info.className + " show";
}
}
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
.show {
/* The class to toggle */
display: block;
background: #ccc;
}
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
The second method, would be to use one div for the content that you want to show/hide, and clicking on an element will toggle both its visibility and it's content.
I'll use the previous example as a base, but ideally you would have some kind of MVVM framework like react, knockout, or angular to help you with filling in the content. For the sake of this example, I'm just going to use the text from the div of sub-content.
var info = document.getElementById("Info");
var maincontent = document.getElementsByClassName("main-content");
for (var i = 0; i < maincontent.length; i++) { //getElemenstByClassName will return an array of elements (even if there's only one).
maincontent[i].onclick = function(event) { //For each element in the maincontent array, add an onclick event.
//This does the same as before, but I'm getting the text to insert into the info card.
var text = event.target.parentNode.getElementsByClassName("sub-content")[0].innerHTML;
info.innerHTML = text; // Set the text of the info card.
info.style.display = "block"; //Make the info card visible.
}
}
info.onclick = function(event) {
info.style.display = "none"; // If the info card is ever clicked, hide it.
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
padding: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
#Info {
cursor: pointer;
display: none;
}
<div id="Info" class="container">Here is some test information.</div>
<div class="container">
<div class="main-content">Link 1.</div>
<div class="sub-content">You clicked link 1.</div>
</div>
<div class="container">
<div class="main-content">Link 2.</div>
<div class="sub-content">You clicked link 2.</div>
</div>
<div class="container">
<div class="main-content">Link 3.</div>
<div class="sub-content">You clicked link 3.</div>
</div>

How to open div smoothly

Pls help me how to open div smoothly.I have add script and html code, its working perfectly but div open suddenly with jerk. I want to open my div "#mapsec" smoothly.
function showhide() {
var div = document.getElementById("mapsec");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
}
HTML CODE
<h3>Visit us (<i><a onclick="showhide()" id="scrollmap" class="mapimg" style="cursor: pointer;">Map</a></i>)</h3>
<div id="mapsec" style="display: none; clear: both;">
<img
src="http://www.websitesnmore.com.au/wp-content/uploads/2013/06/map-img.jpg"
alt="map-img" width="1245" height="350"
class="alignnone size-full wp-image-4586" />
</div>
You have several ways to do it with jQuery. For example:
function showhide() {
$('#mapsec').slideToggle(200);
}
This will slide the div open or closed. 200 is the speed of the animation in miliseconds.
Check these out:
$('#mapsec').toggle(200); — jQuery.toggle()
$('#mapsec').slideToggle(200); — jQuery.slideToggle()
$('#mapsec').fadeToggle(200); — jQuery.fadeToggle()
Using display does exactly what it says it does: displayor hide elements. You could use jQuerys hide and show functions, but since you are trying to use standard javascript, I'll hand you another solution:
<div id="mapsec">
<!-- Your Contents -->
</div>
Now your CSS:
#mapsec {
max-height: 0;
overflow: hidden;
/* You should prefix the following: */
transition: max-height 500ms;
}
#mapsec.active {
/* Depending on this value, your animatiom will seem faster or shorter */
max-height: 1000px;
}
Now the javascript:
function showhide(){
var div = document.getElementById("mapsec");
if (div.className === "") {
div.className = "active";
} else {
div.className = "";
}
}
What we are using is CSS3's built-in animations to trigger something that looks smoother. We hide the overflow of the box you want to animate - as you want it to be invisible. Then we also set it max-height to 0, so it will appear to have no height whatsoever (I would like to add that any paddings and margins don't get included here and might need to be reset as well).
Now we simple add the active class to the div to animate it.
Heres an improved, more universal, and reusable version of the CSS and javascript:
<div id="mapsec" class="hidden">
<!-- Your Contents -->
</div>
.hidden {
max-height: 0;
overflow: hidden;
transition: max-height 500ms;
}
.hidden.active {
max-height: 1000px;
}
function showhide(id){
var div = document.getElementById(id);
if (div.className === "hidden") {
div.className = "hidden active";
} else {
div.className = "hidden";
}
}
Now you can add hidden to any box and unhide it by doing Unhide(replacing 'id' with the id of the element you want to show).
If you want to use jQuery, we can make it even better and easier (and robuster) by using something jQuery has built-in:
Unhide
Now the toggleClass will add the active class and remove it by itself! This is better, as when you use multiple classes, jQuery will leave them intact (notice we don't actually have to use hidden in this code anymore? As long as it already has hidden, we can leave it alone.)
function showhide(id){
var div = document.getElementById(id);
if (div.className === "hidden") {
div.className = "hidden active";
} else {
div.className = "hidden";
}
}
.hidden {
max-height: 0;
overflow: hidden;
/* You should prefix the following: */
transition: max-height 500ms;
}
.hidden.active {
max-height: 1000px;
}
<div id="mapsec" class="hidden">
<img src="" width="200" height="200" />
</div>
ShowHide
Use jQuery.toggle():
function showhide() {
$('#mapsec').toggle();
}
$( "#mapsec" ).show( "slow" );
This should ease the div in nicely instead of:
div.style.display = "block";
I would mainly agree with somethinghere, but since you animate a div with an image inside, than I would animate height of div and set the image height to 100%. Think that looks better/smoother Fiddle. JS changing class is from the answer, but CSS is:
#mapsec {
height: 0;
overflow: hidden;
-webkit-transition: height 500ms;
transition: height 500ms;
}
#mapsec.active {
height: 200px;
}
#mapsec img {
height: 100%;
width: 100%;
}

change height of div by clicking it

I want to change the height of the div by clicking it.
Why it doesn't work at the first clicking but the second?
I don't know why, but the height of the div is "" (in the second clicking is 20px because of the else condition)
If I define the height of the div in the html element (style="height: 20px"), it works.
<html>
<head>
<script>
function divOpen() {
var divHeight= document.getElementById("divBottom").style.height;
if (divHeight=="20px") {
document.getElementById("divBottom").style.height="200px";
}
else {
document.getElementById("divBottom").style.height="20px";
}
}
</script>
<style>
div{
border:solid 1px gray;
width:200px;
height:20px;
}
.divBottom {
position: fixed;
bottom: 0;
right: 20px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="divBottom" id="divBottom" onclick="divOpen()"></div>
</body>
</html>
so I know how to fix it, but I don't know why the height is empty in the first clicking.
Please let me know..
any help appreciated!
In the initial click the height style property of your div is '' because you haven't set it.
There is a difference between setting height through the style property and by using a class. Try to refactor your code and make it use offsetHeight instead of style.height.
JavaScript
function divOpen() {
var divHeight= document.getElementById("divBottom").offsetHeight;
console.log(divHeight);
//22 because of the border
if (divHeight == 22) {
document.getElementById("divBottom").style.height="200px";
}
else {
document.getElementById("divBottom").style.height="20px";
}
}
DEMO

Categories