user2892857
user2892857

Reputation: 435

Smoothly sliding HTML divs up to replace each other

I'll try to explain what I'm trying to do but I think checking out the jsfiddle link would make the point more clearly.

It's a number of phrases (HTML divs) stacked vertically on each other. When the button is clicked, the top phrase disappears while the lower phrases appear to slide up to take the place of the phrase previously above themselves.

Is there a better way to do this? It looks really ugly as it is.

EDIT: also note that the code only works once, then you have to hit 'run' again since the list of phrases is not infinite like in my actual application

https://jsfiddle.net/deddnbrh/1/

HTML:

<br>
<br>
<br>
<div id="phrase1" style="font-size:50px;color:black">Phrase 1</div>
<div id="phrase2" style="font-size:25px;color:gray">Phrase 2</div>
<div id="phrase3" style="font-size:25px;color:gray">Phrase 3</div>
<div id="phrase4" style="font-size:25px;color:gray;opacity:0">Phrase 4</div>
<br>
<br>
<br>
<button id="button" onclick="myFunc2()" onmousedown="myFunc()">CLICK ME</button>

javascript:

document.getElementById('phrase2').addEventListener("webkitAnimationEnd", switchPhraseText);


function switchPhraseText() {
    document.getElementById('phrase1').innerHTML = "Phrase 2";

    document.getElementById('phrase2').innerHTML = "Phrase 3";

    document.getElementById('phrase3').innerHTML = "Phrase 4"; 

    document.getElementById('phrase4').innerHTML = "Phrase 5"; 
}

function myFunc2() {
    document.getElementById('phrase1').style.webkitAnimationName = 'phrase1Anim';

    document.getElementById('phrase2').style.webkitAnimationName = 'phrase2Anim';

    document.getElementById('phrase3').style.webkitAnimationName = 'phrase3Anim';

    document.getElementById('phrase4').style.webkitAnimationName = 'phrase4Anim';


}

function myFunc() {
    document.getElementById('phrase1').style.webkitAnimationName = "";
    document.getElementById('phrase2').style.webkitAnimationName = "";
    document.getElementById('phrase3').style.webkitAnimationName = "";
    document.getElementById('phrase4').style.webkitAnimationName = "";
}

css:

#phrase1 {
    position: relative;
    -webkit-animation-duration: .8s; 
}

#phrase2 {
    position: relative;
    -webkit-animation-duration: 1s; 
}

#phrase3 {
    position: relative;
    -webkit-animation-duration: 1s; 
}

#phrase4 {
    position: relative;
    -webkit-animation-duration: 1s; 
}


@-webkit-keyframes phrase1Anim {
    0%   {left:0px;}
    100% {left:250px; opacity:0}
}

@-webkit-keyframes phrase2Anim {
    0%   {font-size:25px; top:0px;}
    100% {color:black; font-size:50px; top:-50px;}
}

@-webkit-keyframes phrase3Anim {
    0%   {top:0px;}
    100% {top:-50px;}
}

@-webkit-keyframes phrase4Anim {
    0%   {top:0px;}
    100% {top:-50px; opacity:1;}
}

Upvotes: 1

Views: 168

Answers (1)

user4698813
user4698813

Reputation:

This will support an indefinite amount of elements inside of the list. Of course, it's not perfect, and you have to tweak it to your needs, but hopefully it'll get you started. The code is pretty self explanatory, I think.

This will only work with Chrome, in its current state, but for it to work in other browsers, all you need to do is add the relevant vendor-prefixes to the CSS rules and to the animation events. For multi-browser support, just add the relevant CSS fallbacks and listener fixes.

  • It animates (right/fade-out) the element with class active
  • It clones said element and pushes it to the bottom, fading it in.
  • It removes the clone and appends the original one (as the clone was just for aesthetics)
  • It animates (up, font-size, color) the element next to active.

  1. jsFiddle for Chrome

  2. jsFiddle for Firefox (apparently, FF is awesome and doesn't need vendor prefixes).

Finally, this is the Chrome version in snippet form:

var phrases = document.getElementById('phrases'),
    next = document.getElementById('next'),
    ongoing = false;

function animList() {
    var active = document.getElementsByClassName('active')[0],
        next = active.nextElementSibling,
        clone;
    
    if(ongoing) return;
    
    ongoing = true;
  
    function animationStart() {
        clone = this.cloneNode(true);
        clone.id = '_tmp';
        clone.className = '';
        clone.style.transition = 'opacity 1s';
        clone.style.opacity = '0';
        setTimeout(function () { clone.style.opacity = '1' }, 50);
        phrases.appendChild(clone);
        this.removeEventListener('webkitAnimationStart', animationStart);
    }
    function animationEnd() {
        clone.parentNode.removeChild(clone);
        phrases.appendChild(active);
        this.classList.remove('active', 'animActive', 'slideUp');
        this.removeEventListener('webkitAnimationEnd', animationEnd);
        this.removeEventListener('webkitAnimationStart', animationStart);
        next.classList.remove('slideUp');
        next.classList.add('active');
        ongoing = false;
    }
    active.classList.add('animActive');
    next.classList.add('slideUp');
    active.addEventListener('webkitAnimationStart', animationStart);
    active.addEventListener('webkitAnimationEnd', animationEnd);
}
    
next.onclick = animList;
#next {
    position: relative;
    display: inline-block;
    top: 2.5em;
    background: transparent;
    border: 0;
    font-size: 2em;
}
#phrases {
    display: inline-block;
    vertical-align: top;
    max-height: 11em;
}
#phrases div {
    font-size: 2em;
    color: gray;
    position: relative;
}
#phrases div.active {
    font-size: 3em;
    color: black;
}
.animActive {
    -webkit-animation: animActive 1s ease-in-out;
}
.slideUp {
    -webkit-animation: slideUp 1s;
}
#phrases div.slideUp ~ div:nth-child(n+3) {
    -webkit-animation: slideUpRest 1s;
}
@-webkit-keyframes animActive {
    0%   { 
        left: 0; 
    }
    100% { 
        left: 4em;
        opacity: 0 
    }
}

@-webkit-keyframes slideUp {
    0%   { 
        top: 0;
    }
    100% { 
        top: -1.15em;
        font-size: 3em;
        color: black;
    }
}
@-webkit-keyframes slideUpRest {
    0%   { 
        top: 0;
    }
    100% { 
        top: -1.7em; 
    }
}
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>

    <div id="phrases">
        <div id="phrase1" class="active">Phrase 1</div>
        <div id="phrase2">Phrase 2</div>
        <div id="phrase3">Phrase 3</div>
        <div id="phrase4">Phrase 4</div>
        <div id="phrase5">Phrase 5</div>
    </div>
    <button id="next">
        <i class="fa fa-angle-right"></i>
    </button>

Upvotes: 1

Related Questions