Sliding animation when hiding/showing a div - javascript

I have two divs, top and bottom. Both divs have dynamic height, the top div will show or hide depending on a variable.
I would like to add in a sliding animation to the top div when showing or hiding, but the bottom div should stick with the top div and slide with it too.
var hide = true;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (hide) {
topdiv.classList.add('hide');
} else {
topdiv.classList.remove('hide');
}
hide = !hide;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
}
.hide {
display: none !important;
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>
I tried adding transform animations, but the effect is only applied to the top div while the bottom div remains unanimated.
#keyframes topDivAnimate {
from {
transform: translateY(-100%);
}
to {
transform:translateY(0%);
}
}
Help is much appreciated.

I would use CSS transition rather than animation. I've found it easiest to do by animating the lower div rather than the upper one, and changing its position so that it covers the top one (or, of course, not). See demonstration below, I've made as minimal changes as I could to the CSS and JS:
var cover = true;
var trigger = document.getElementById("trigger");
var bottomdiv = document.getElementsByClassName("body")[0];
trigger.addEventListener('click', function() {
if (cover) {
bottomdiv.classList.add('cover');
} else {
bottomdiv.classList.remove('cover');
}
cover = !cover;
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
background: #999;
}
.body {
background: #555;
transform: translateY(0%);
transition: transform 0.5s;
}
.cover {
transform: translateY(-100%);
}
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>

Are you looking something like this? Then please try this:
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if ($('#topdiv').css('display') == 'none') {
$(topdiv).slideDown();
} else {
$(topdiv).slideUp();
}
});
div {
position: relative;
display: block;
width: 100%;
padding: 10px;
}
.top {
display: none;
background: #999;
}
.body {
background: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="topdiv" class="top hide">
<p>Top</p>
</div>
<div class="body">
<p>Body</p>
<button id="trigger">
Trigger
</button>
</div>

Try this code and see if that's the effect you wanted. It uses the Animate.css library so you'll need to link that in your <head></head>
function animateCSS(element, animationName, callback) {
const node = document.querySelector(element)
node.classList.add('animated', animationName)
function handleAnimationEnd() {
node.classList.remove('animated', animationName)
node.removeEventListener('animationend', handleAnimationEnd)
if (typeof callback === 'function') callback()
}
node.addEventListener('animationend', handleAnimationEnd)
}
var hide = false;
var trigger = document.getElementById("trigger");
var topdiv = document.getElementById("topdiv");
trigger.addEventListener('click', function() {
if (!hide) {
topdiv.classList.remove('hide');
animateCSS('.body', 'slideInDown');
animateCSS('#topdiv', 'slideInDown');
} else {
animateCSS('#topdiv', 'slideOutUp', function() {
topdiv.classList.add('hide');
})
animateCSS('.body', 'slideOutUp');
}
hide = !hide;
});
Working Codepen demo of my solution
Here's some more explanation on how to use the Animate.css library.

Related

is there any better way to do this js code?

I am making these panels to be resized to fit screen height as I click 'this' element. I feel like I hard coded those javascript, and I believe there must be better way. But couldn't really sort it out.
when one panel is clicked, its size is going to get bigger, and rest of pannels gonna get smaller
I would very much appreciate any suggestion of it.
I've tried making this function reusable, but then couldn't really come up with better solution as I am a begginer.
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))
function getCurrentName(element) {
const panel1 = document.querySelector('.panel1');
const panel2 = document.querySelector('.panel2');
const panel3 = document.querySelector('.panel3');
const panel4 = document.querySelector('.panel4');
console.log(this);
if(this) {
this.classList.toggle('active');
if(this === panel1) {
panel2.classList.toggle('inactive');
panel3.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel2) {
panel1.classList.toggle('inactive');
panel3.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel3) {
panel1.classList.toggle('inactive');
panel2.classList.toggle('inactive');
panel4.classList.toggle('inactive');
} else if (this === panel4) {
panel1.classList.toggle('inactive');
panel2.classList.toggle('inactive');
panel3.classList.toggle('inactive');
}
}
}
.panel {
background-color: #002712;
box-shadow: inset 0 0 0 .5rem rgba(255,255,255,0.1);
min-height: 22.5vh;
color: #fff;
text-align: center;
font-size: 2rem;
background-size: cover;
background-position: center;
line-height: 8rem;
transition:
min-height .5s linear,
font-size .2s linear .5s,
line-height .2s linear .5s;
}
.panel1 { background-image: url("../images/steake.png"); }
.panel2 { background-image: url("../images/sundayRoast.png"); }
.panel3 { background-image: url("../images/image1(1).png"); }
.panel4 { background-image: url("../images/cannonbury.png"); }
.active {
min-height: 37vh;
line-height: 15rem;
font-size: 2.3rem;
}
.inactive {
min-height: 15vh;
font-size: 1.2rem;
}
<main>
<section class="intro">
<div class="intro-panels">
<section class="panel panel1">
<p>most original,</p>
</section>
<section class="panel panel2">
<p>best beer,</p>
</section>
<section class="panel panel3">
<p>grilled food</p>
</section>
<section class="panel panel4">
<p>Islington</p>
</section>
</div>
</section>
</main>
I expect simplified javascript code to achieve the same goal.
Here's how I've sorted it out by your answer. Thank you for your help guys.
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click', getCurrentName))
function getCurrentName(element) {
if(this) {
panelsArr.forEach(panel => panel.classList.toggle('inactive'));
this.classList.toggle('inactive');
this.classList.toggle('active');
}
}
You could mark them all as inactive and re-mark the current one as active.
Array.from(document.querySelectorAll('.panel')).forEach(element => {
element.classList.remove('active');
element.classList.add('inactive')
});
this.classList.remove('inactive');
this.classList.add('active');
You could also filter out this from the array, but it wouldn't change the outcome.
You can toggle inactive class on all class elements but undo it again on the target element:
const panels = document.querySelectorAll('.panel');
const panelsArr = Array.from(panels);
panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))
function getCurrentName(element) {
console.log(this);
if(this) {
// Toggle inactive on all elements
for (i = 0; i < panels.length; ++i) {
panels[i].classList.toggle('inactive');
}
//But undo for selected element again
this.classList.toggle('inactive');
this.classList.toggle('active');
}
}
Try something like this. Event delegation
document.addEventListener('click', (e) => {
if(e.target.matches('.sizable')) {
document.querySelectorAll('.sizable').forEach(div => {
div.classList.remove('active');
div.classList.add('inactive');
});
e.target.classList.add('active');
}
});
.sizable {
display: inline-block;
border: 1px solid black;
margin: 5px;
}
.inactive {
width: 50px;
height: 50px;
}
.active {
width: 150px;
height: 150px;
}
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>

how to make a div disappear/appear on hovering on other div?

How to display the line when I hover over my div circle?
#line {
display: none
}
<div id='circle'>
<div id= 'line'>
Assuming you are using jQuery you can use:
var enterHandler = function(){
$("#line").show();
};
var leaveHandler = function(){
$("#line").hide();
};
$("#circle").hover(enterHandler, leaveHandler);
First thing, with your code, it is not clear if the <div>s are siblings are nested. I will give you the solution for both.
Nested
div {
padding: 10px;
background: #99c;
}
#line {
display: none;
background: #9c9;
}
#circle:hover #line {
display: block;
}
<div id='circle'>
<div id='line'>
</div>
</div>
Siblings
div {
padding: 10px;
background: #99c;
}
#line {
display: none;
background: #9c9;
}
#circle:hover + #line {
display: block;
}
<div id='circle'>
</div>
<div id='line'>
</div>
If you are using jQuery then you can simply try:
$('#circle').on('mouseover', function() {
$('#line').show();
});
$('#circle').on('mouseleave', function() {
$('#line').hide();
});
jQuery would be simplest.
$('#circle').hover(function(){
$('#line').css('display','inline');
});
or whatever display property you are going for.
Try this in script tag and use onmouseover and onmouseout events
<script>
function hidediv() {
document.getElementById('line').style.display = 'none';
}
function showdiv() {
document.getElementById('line').style.display = 'block';
}
</script>
<div id='circle' onmouseover="hidediv();" onmouseout="showdiv();" > this is circle
<div id= 'line'>this is line
</div>
</div>

Img resize on scroll

How can i resize a logo( es width: 100px ) in a header on mouse scrolling?
$('.logo').scroll(function() {
$(this).width(100);
$(this).off(); //removes the handler so that it only resizes once...
})
.header {
background-color: black;
}
.logo {
height:100px;
width: 100%;
background-image: url("http://unika.myarmah.it/skin/frontend/sns_simo/default/images/logo.png");
background-repeat: no-repeat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header">
<div class="logo"></div>
</div>
Just use javascript:
Why? - Because its just as short as using jQuery.
Update #1 -
after seeing the comments to the previous answer from the author, I have adjusted my example to include animation and reset when at the top of the page. Again - just use javascript, and for better performance benefits use CSS classes so that all paints are done in one cycle.
Update #1 jsfiddle - https://jsfiddle.net/113dn29z/16/
var logo = document.querySelector('.logo');
var handleResize = function(e) {
if (document.body.scrollTop === 0) {
logo.classList.remove("resize");
} else {
logo.classList.add("resize");
}
};
document.addEventListener('scroll', handleResize);
<div class="header">
<div class="logo">
</div>
</div>
body {
height: 9999px;
overflow: auto;
}
.header {
background-color: black;
}
.logo {
margin-top: 200px;
height:100px;
width: 100%;
background-color: red;
background-repeat: no-repeat;
transition: width 0.2s ease;
}
.logo.resize {
width: 100px;
}
old jsFiddle example - https://jsfiddle.net/113dn29z/10/
var logoHasResized = false;
$(document).on('scroll', function (e) {
if (window.scrollY == 0) {
$('.logo').animate({'width': '100%'}, 250);
logoHasResized = false;
} else if (logoHasResized == false) {
$('.logo').animate({'width': 100}, 250);
logoHasResized = true;
}
});
edit: Since you want it to go back when you scroll to the top of the page, i've added in a check to see if the animation has happened, as you don't want it to fire constantly.

Vertical distribution of elements (and animation) - jQuery

I like to know the cleanest method to distribute elements vertically with jQuery. I nailed it but it's not very clean right >< ? I would like to get to do it without plugin... Thank you in advance ;-)
Here my JSFiddle
jQuery(document).ready(function($) {
var gap = 10;
var firstElem = $('#lorem');
if(firstElem.length){
var heightCall = (firstElem.offset().top)+(firstElem.outerHeight())+(gap);
var middleElem = $('#dolore');
middleElem.offset({top : heightCall});
var lastElem = $('#amet');
var NewHeightCall = (middleElem.offset().top)+(middleElem.outerHeight())+(gap);
lastElem.offset({top : NewHeightCall});
/* Animation */
$('#lorem, #dolore, #amet').hover(
function(){
$(this).stop().animate({left: (($(this).offset().left)-(20))+'px',opacity:'0.5'},'slow')
},
function(){
$(this).stop().animate({left: (($(this).offset().left)+(20))+'px',opacity:'1'},'slow')
});
}
});
I have fiddled around with your code:
This is a simplified version:
HTML:
<div id="lorem" class="vertical-block">My first ID div</div>
<div id="dolore" class="vertical-block">My second ID div.<br>My second ID div. My second ID div.</div>
<div id="amet" class="vertical-block">My third ID div</div>
CSS:
.vertical-block {
position: absolute;
padding:15px;
}
#lorem{
top:20%;
right:40px;
background:#f79673;
}
#dolore{
right:80px;
background:#cd7454;
}
#amet{
right:40px;
background:#a15338;
}
.vertical-block:hover {
opacity: 0.5;
padding-right: 30px;
-webkit-transition: all 2s;
transition: all 0.4s;
}
Javascript:
jQuery(document).ready(function($) {
var gap = 10;
var firstElem = $('#lorem');
var top = 0;
$('.vertical-block').each(function(element){
var $currentElement = $(this);
if (top === 0) {
top = $currentElement.offset().top + $currentElement.outerHeight() + gap;
} else {
$currentElement.offset({top: top});
top = top + $currentElement.outerHeight() + gap;
}
});
});
https://jsfiddle.net/rae2x4e0/1/
Now if you want to go for a purely css solution, then:
HTML:
<div class="container">
<div id="lorem" class="vertical-block">My first ID div</div>
<br />
<div id="dolore" class="vertical-block">My second ID div.<br>My second ID div. My second ID div.</div>
<br />
<div id="amet" class="vertical-block">My third ID div</div>
</div>
CSS:
.container {
position-relative;
text-align: right;
padding-top: 10%;
}
.vertical-block {
padding:15px;
display: inline-block;
margin-top: 20px;
}
#lorem{
right:40px;
background:#f79673;
}
#dolore{
right:80px;
background:#cd7454;
}
#amet{
right:40px;
background:#a15338;
}
.vertical-block:hover {
opacity: 0.5;
padding-right: 30px;
-webkit-transition: all 2s;
transition: all 0.4s;
}
https://jsfiddle.net/ycdwpjxw/1/

jQuery hide if either div is visible

I have 2 divs that are initially hidden
<div id="whistle" style="display:none;">
<div id="lean" style="display:none;">
I also have a div that is visible
<div id="me" style="display:block">
I have jQuery code that allows only the #whistle or #lean divs to be open at once, their buttons will hide the other.
I currently have code that also hides the #me div, but I would now like the #me div to open back up when both #whistle and #lean are closed.
If you want to see the site, the link is maxdev.tk
The jQuery code is
$(document).ready(function(){
$("#calc").click(function(){
$("#whistle").hide(600);
$("#lean").toggle(900);
});
});
$(document).ready(function(){
$("#whi").click(function(){
$("#lean").hide(600);
$("#whistle").toggle(900);
});
});
This is one way to solve it. Find it also as a pen at the end of this post.
$(document).ready(function() {
function callback() {
if( $('#whistle').hasClass('hidden') && $('#lean').hasClass('hidden') ) {
$('#me').removeClass('hidden');
} else {
$('#me').addClass('hidden');
}
}
$('button[data-for=whistle]').on('click', function() {
$('#whistle').toggleClass('hidden');
$('#lean').addClass('hidden');
callback();
});
$('button[data-for=lean]').on('click', function() {
$('#lean').toggleClass('hidden');
$('#whistle').addClass('hidden');
callback();
});
})
.hidden {
opacity: 0;
height: 0;
overflow: hidden;
padding: 0;
}
div {
background-color: #ccc;
border-radius: 25px;
margin-top: 20px;
padding: 50px;
text-align: center;
transition-duration: 0.4s;
width: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button data-for="whistle">Whistle</button>
<button data-for="lean">Lean</button>
<div id="whistle" class="hidden">Whistle!</div>
<div id="lean" class="hidden">Lean!</div>
<div id="me">Me!</div>
http://codepen.io/anon/pen/yNJrwe
Add this code to the end of whatever buttons' click function.
if( !$('#whistle').is(':visible') && !$('#lean').is(':visible') ) {
$('#me').css("display","block"); // or use .show();
} else {
$('#me').css("display","none"); // or use .hide();
}

Categories

Resources