How to open div smoothly - javascript

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%;
}

Related

Smooth scrolling slider with play/pause button

I'm doing a project where I need a scrollable slider with play pause button like www.gap.com. I got this below code from W3C but not sure why multiple images are not showing fully. If I change the width value in CSS code, only first image portion scrolls but it totally ignores the 2nd image. Please anyone help me.
var speed=20 // speed of scroller
var step=3 // smoothness of movement
var StartActionText= "Scroll" // Text for start link
var StopActionText = "Pause" // Text for stop link
var x, scroll, divW, sText=""
function onclickIE(idAttr,handler,call){
if ((document.all)&&(document.getElementById)){idAttr[handler]="Javascript:"+call}
}
function addLink(id,call,txt){
var e=document.createElement('a')
e.setAttribute('href',call)
var linktext=document.createTextNode(txt)
e.appendChild(linktext)
document.getElementById(id).appendChild(e)
}
function getElementStyle() {
var elem = document.getElementById('scroller');
if (elem.currentStyle) {
return elem.currentStyle.overflow;
} else if (window.getComputedStyle) {
var compStyle = window.getComputedStyle(elem, '');
return compStyle.getPropertyValue("overflow");
}
return "";
}
function addControls(){
// test for CSS support first
// test for the overlow property value set in style element or external file
if (getElementStyle()=="hidden") {
var f=document.createElement('div');
f.setAttribute('id','controls');
document.getElementById('scroller').parentNode.appendChild(f);
addLink('controls','Javascript:clickAction(0)',StopActionText);
onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction(0)');
document.getElementById('controls').style.display='block';
}
}
function stopScroller(){clearTimeout(scroll)}
function setAction(callvalue,txt){
var c=document.getElementById('controls')
c.childNodes[0].setAttribute('href','Javascript:clickAction('+callvalue+')')
onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction('+callvalue+')')
c.childNodes[0].firstChild.nodeValue=txt
}
function clickAction(no){
switch(no) {
case 0:
stopScroller();
setAction(1,StartActionText);
break;
case 1:
startScroller();
setAction(0,StopActionText);
}
}
function startScroller(){
document.getElementById('tag').style.whiteSpace='nowrap'
var p=document.createElement('p')
p.id='testP'
p.style.fontSize='25%' //fix for mozilla. multiply by 4 before using
x-=step
if (document.getElementById('tag').className) p.className=document.getElementById('tag').className
p.appendChild(document.createTextNode(sText))
document.body.appendChild(p)
pw=p.offsetWidth
document.body.removeChild(p)
if (x<(pw*4)*-1){x=divW}
document.getElementById('tag').style.left=x+'px'
scroll=setTimeout('startScroller()',speed)
}
function initScroller(){
if (document.getElementById && document.createElement && document.body.appendChild) {
addControls();
divW=document.getElementById('scroller').offsetWidth;
x=divW;
document.getElementById('tag').style.position='relative';
document.getElementById('tag').style.left=divW+'px';
var ss=document.getElementById('tag').childNodes;
for (i=0;i<ss.length;i++) {sText+=ss[i].nodeValue+" "};
scroll=setTimeout('startScroller()',speed);
}
}
function addLoadEvent(func) {
if (!document.getElementById | !document.getElementsByTagName) return
var oldonload = window.onload
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload()
func()
}
}
}
addLoadEvent(initScroller)
body {font:1em verdana,sans-serif; color:#000; margin:0}
/* position:relative and overflow:hidden are required */
#scroller { position:relative; overflow:hidden; width:30em; border:1px solid #008080; }
/* add formatting for the scrolling text */
#tag { margin:2px 0; }
/* #testP must also contain all text-sizing properties of #tag */
#testP { visibility:hidden; position:absolute; white-space:nowrap; }
/* used as a page top marker and to limit width */
#top { width:350px; margin:auto; }
<div id="scroller">
<div id="tag">
<img src="https://picsum.photos/1500/600/?image=1"/>
<img src="https://picsum.photos/1500/600/?image=2"/>
</div>
</div>
I got a bit lost in the given JS, and wonder if it is necessary for this relatively simple task.
Here is a method using HTML and CSS for the continuous scrolling and with JS just for the pause/play part.
Because you want continuous scrolling with no gap or jump when the sequence of images goes back to the beginning you need two copies. The tag element is scrolled to the left by half of its width which means that the set of images overwrite themselves so giving a smooth effect.
The JS for the button uses the running value and toggles that.
.playpause {
top: 10%;
left: 10%;
position: absolute;
z-index: 1;
}
#scroller {
width: min(30em, 100vw);
height: min(20em, 100vh);
display: inline-block;
white-space: nowrap;
overflow: hidden;
position: relative;
}
#scroller #tag {
height: 100%;
animation: scroll 10s linear infinite;
animation-fill-mode: forwards;
display: inline-block;
font-size: 0;
}
#keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
img {
height: 100%;
width: auto;
display: inline-block;
}
<div id="scroller">
<button class="playpause" onclick="document.querySelector('#tag').style.animationPlayState = (document.querySelector('#tag').style.animationPlayState != 'paused') ? 'paused' : 'running';">PLAY/PAUSE</button>
<div id="tag">
<img src="https://picsum.photos/1500/600/?image=1" />
<img src="https://picsum.photos/1500/600/?image=2" />
<!-- second copy of all the imaages -->
<img src="https://picsum.photos/1500/600/?image=1" />
<img src="https://picsum.photos/1500/600/?image=2" />
</div>
</div>
Observation: the site linked to in the question (gap) has a slightly unpleasant 'jump' half way through the images so I think they must be using a different method to achieve continuous scrolling.

In what cases are CSS transitions removed?

I'm pretty new to Javascript, and I have a webpage I'm trying to make that uses the same HTML file, and just cross-fades content instead of redirecting to new pages. I'm using event listeners to know when the current page has faded out and that triggers the new page to come in. Why is it that in the example below, the new pages don't fade in slowly (they just appear suddenly, ignoring the transition property)? Why is the content no longer responding to the CSS transition?
Edit: I'll try to clarify what I'm asking here. I'm aware that the display feature cannot be transitioned, and that's actually why I'm using the event listener at all. I'm trying to make it so that when the content of one page fades out, the next one fades in in the same place, which I believe cannot be achieved with visibility.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<!-- CSS -->
<style>
/* navagation bar style */
#navbar {
overflow: hidden;
background-color: #000000;
text-align: center;
width: 100%;
height: 36px;
}
#navbar a {
display: inline-block;
color: #ffffff;
padding: 10px 15px 10px 15px;
font-size: 16px;
}
/* content style*/
.page {
padding: 50px;
text-align: center;
transition: opacity 1s;
}
</style>
<!-- Javascript -->
<script>
window.onload = function() {setup()};
function setup() {
var page1link = document.getElementById("page1link");
var page1 = document.getElementById("page1");
page1.style["opacity"] = "1";
var page2link = document.getElementById("page2link");
var page2 = document.getElementById("page2");
page2.style["opacity"] = "0";
page2.style["display"] = "none";
var page3link = document.getElementById("page3link");
var page3 = document.getElementById("page3");
page3.style["opacity"] = "0";
page3.style["display"] = "none";
page1link.onclick = function() {fade(page1, page2, page3)};
page2link.onclick = function() {fade(page2, page1, page3)};
page3link.onclick = function() {fade(page3, page1, page2)};
}
function fade(page_1, page_2, page_3) {
let on_page;
if (page_2.style["opacity"] != "0") {
on_page = page_2
} else if (page_3.style["opacity"] != "0") {
on_page = page_3
} if (on_page != undefined) {
on_page.addEventListener('transitionend', fadePageIn)
on_page.style["opacity"] = "0";
function fadePageIn() {
on_page.style["display"] = "none";
page_1.style["display"] = "";
page_1.style["opacity"] = "1";
on_page.removeEventListener('transitionend', fadePageIn);
}
}
}
</script>
<title>Example</title>
</head>
<body>
<div id="navbar">
<a id="page1link" href="javascript:void(0)">Page 1</a>
<a id="page2link" href="javascript:void(0)">Page 2</a>
<a id="page3link" href="javascript:void(0)">Page 3</a>
</div>
<div class="page" id="page1">
page 1 content here
</div>
<div class="page" id="page2">
page 2 content here
</div>
<div class="page" id="page3">
page 3 content here
</div>
</body>
</html>
You can't animate the display property. So when you set opacity and display at the same time, the opacity will transition but the display value changes immediately.
As an alternative, the visibility property can be animated. Interpolation between its values happens at the halfway point, so if you want to make it work with transition that might complicate things. But I've had success in the past using CSS animations to change opacity and visibility at the same time. Using animations like this:
#keyframes becomeVisible {
0% { visibility: visible; }
100% { visibility: visible; }
}
#keyframes becomeHidden {
0% { visibility: visible; }
100% { visibility: visible; }
100% { visibility: hidden; }
}
#keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
#keyframes fadeout {
0% { opacity: 1; }
100% { opacity: 0; }
}
This is an interesting question.
Basically, as Mark points out, you can't animate it because setting the display property isn't possible to animate, thus nullifying your other transitions.
Therefore, as long as you can update the transition-able properties later in the event loop, then it will work as intended. A very easy way to do this is to use a setTimeout with 0 time.
function transitionEndCallback() {
oldPage.style["display"] = "none";
newPage.style["display"] = "block";
// add the setTimeout somewhere in this function
setTimeout(() => {
page_1.style["opacity"] = "1";
}, 0)
on_page.removeEventListener('transitionend', transitionEndCallback);
}
This way, it gets called in a different event loop callback, but still updates almost immediately afterwards. There maybe a better callback function or feature because it's a bit hacky, but I can verify it works.

JavaScript animation hide element using jquery

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

CSS Transition on height not working when fully done from Javascript

I'm trying to make an animation for sliding up and sliding down. To toggle parts of the page. When the height is "hardcoded" in CSS to 210px before rendering the page and I call the Javascript function from a button it all works.
But when I try to do this dynamically, with Javascript to keep "hardcoding" to a minimum. It still does the change to the height. But the transition effect does not happen.
Here is the code snippet to high light the problem. I don't understand as to why this difference sabotages the transition.
function slideUp() {
var target = document.getElementById("targetDiv");
target.style.height = "" + target.clientHeight+"px"; // taking the rendered height of the div and setting it in CSS to mimic the pre set height in CSS
target.style.transition = "height 1.0s ease-in 0s";
target.style.height = "0px";
}
.divStyle {
/* height: 200px; without this the animation does not work */
background: blue;
overflow: hidden;
}
<div id="targetDiv" class="divStyle">
random content
</div>
<button onclick="slideUp()"> Slide up </button>
Use of max-height combined with setTimeout "hack" worked for me:
function slideUp() {
var target = document.getElementById("targetDiv");
target.style.maxHeight = target.clientHeight + "px";
setTimeout(function() {
target.style.maxHeight = 0;
}, 10);
}
.divStyle {
background: blue;
overflow: hidden;
transition: max-height 1s ease-in 0s;
}
<div id="targetDiv" class="divStyle">
random content
</div>
<button onclick="slideUp()"> Slide up </button>
However, it is not a clean way. Think of using transform: scaleY(0) instead.
There are multiple ways to achieve the goal, in your case you just require to init the style which is supposed to change at the later time so just use window.onload and init the value.
var org = "";
window.onload = function() {
var target = document.getElementById("targetDiv");
org = target.clientHeight;
target.style.height = "" + target.clientHeight + "px";
}
function slideUp() {
var target = document.getElementById("targetDiv");
target.style.transition = "height 1.0s ease-in 0s";
if (target.clientHeight == org) {
target.style.height = "0px";
} else {
target.style.height = org + "px";
}
}
.divStyle {
/* height: 200px; without this the animation does not work */
background: blue;
overflow: hidden;
}
<div id="targetDiv" class="divStyle">
random content
</div>
<button onclick="slideUp()"> Slide up </button>
Just so that if anyone comes along here, the given answers are good, just not in the current case I need. The way I managed finally is as follows.
function slideDown( targetId ){
var target = document.getElementById(targetId);
target.style.height = target.children[0].clientHeight + "px";
}
function slideUp( targetId ) {
var target = document.getElementById(targetId);
target.style.height = "0px";
}
.parentDivStyle{
overflow: hidden;
transition: height 0.5s ease-in 0s;
height: 0px;
background: blue;
}
.childDivStyle {
background: green;
padding: 10px 10px 10px 10px;
}
<div id="parent" class="parentDivStyle">
<div class="childDivStyle">
random stuff
text text text...........
</div>
</div>
<button onclick="slideUp('parent')"> Slide Up </button>
<button onclick="slideDown('parent')"> Slide Down </button>
This was actually a comment in a deleted answer. Idk why it was deleted. Was useful.
As mentioned before: having a height/max-height value set to auto/none stops
the transition from working.
Rather than setting the max-height to a specified, larger than needed
max-height by guesswork (if set to really high number causes a delay in the
transition), I added transition and a max-height to the content wrapper instead,
and used JavaScript to read the actual height of the contents. This way the
wrapper max-height is set to the currently rendered height of its contents.
This gives it a fixed inline height.
The problem with this solution, is that if the user decides to resize his
window, into say, a narrower screen (i.e. rotating from landscape to portrait
mode on mobile), the fixed max-height causes to content to be cut-off. The
work-around for this is setting a setTimeout() function to set the max-height
of the wrapper back to none just after the transition has ended. (none is
the default, initial CSS value of the max-height property)
The same thing needs to happen before the "contracting" transition. The
wrapper's max-height needs to be a fixed value for the transition to work.
Therefore, the height needs to again be read from its contents (which might have
actually changed in the meantime), applied to the wrapper, then after a short
delay (50ms seemed to work in my case, and the delay wasn't noticeable) begin
the transition.
Here's an example that expands the div contents when a button is pressed:
HTML:
<div id="content-wrapper">
<div id="content">
<!-- a lot of text content -->
</div>
</div>
<button id="show-more" type="button">Show More</button>
CSS:
#content-wrapper {
/* Initial max-height, can be any value including 0 */
max-height: 270px;
overflow: hidden;
/* transition occurs on max-height change with specified delay; */
transition: max-height 0.7s;
}
#content {
/* This makes margin of the contents be respected by the container
i.e. the height of the container its childrens' margins */
overflow: hidden;
}
JS:
function resetHeight() {
// make max-height of wrapper responsive again
wrapper.style.maxHeight = "none";
}
function toggleText() {
// check if content-wrapper is open
if (wrapper.className.includes("open")) {
// if is open, close content-wrapper and set initial max-height to wrapper
let contentHeight = window.getComputedStyle(content).height;
// sets max-height back from none to computed content height
wrapper.style.maxHeight = contentHeight;
// give it some time to reset the transition trigger caused by previous statement
setTimeout(function() {
wrapper.classList.remove("open");
wrapper.style.maxHeight = "270px"; // reset to our initial max-height
button.textContent = "Show More";
}, 50)
} else {
// if not open, open content-wrapper then use content's height to set the
// max-height of wrapper
wrapper.classList.add("open");
let contentHeight = window.getComputedStyle(content).height;
wrapper.style.maxHeight = contentHeight;
button.textContent = "Show Less";
setTimeout(resetHeight, 700) // the timeout is the same as the transition time
}
}
const content = document.getElementById("content")
const wrapper = document.getElementById("content-wrapper");
const button = document.getElementById("show-more");
button.addEventListener("click", toggleText);
This is my first answer on StackOverflow, so if there is anything I can improve
please do let me know.

Change the content of a style class

I use css to have animation (using transition) in a div. The content of the div is dynamical (can be 1 line or multiple lines).
I have 2 classes I switch to get the animation effect:
.class1{
max-height: 200px;
}
.class2{
max-height: 0;
}
My problem occurs when the I have only 1 line in the div, so there's "delay" until the 1 line disappears (because the height changes from 200px to 0 while the actual size is only 30px).
I tried to use element.style.maxHeight = elem.offsetHeight + "px" to set the max-height size but it didn't work so I want to change max-height in the class (class1 or class2) to fit the actual size.
How can I change the content of a class (I don't want to have: "style = max-height: 100px" in my div)?
You could use the transition in combination with the transform.
Not only because solve your problem, but also because has better performance then change the height.
Doesn't make sense changing the height and using CSS, in terms of performance you can use JS, it is the same.
I did an example for you on jsfiddle because on here seems to do not work.
jQuery(document).ready(function() {
jQuery('.click-me').on('click', function() {
var $this = jQuery(this);
if ($this.hasClass('show')) {
jQuery(this).removeClass('show').addClass('hide');
}
});
});
.hide {
transform: translateY(-100%);
z-index: -1;
}
.show {
transform: translateX(0);
z-index: 0;
}
.animate {
transition: transform 1s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="parent">
<div class="click-me animate show">
<div>one line</div>
</div>
</div>

Categories