srzsanti
srzsanti

Reputation: 300

CSS translate to the top of <ul> with animation

What I'm trying to achieve is to translate an item in a <UL> to the top of the list but with a transition effect. This is what I have till now:

$( "#button" ).click(function() {
  $("#select").addClass("is-moved");
});
.navbar-nav{
  margin 0;
 }

.nav{
  float: none;
  list-style: none;
  padding-left: 0;
}

.singlechatContainer {
    -moz-transition: all 2s;
    -webkit-transition: all 2s;
    -o-transition: all 2s;
    transition: all 2s;
}
.is-moved {
    position: absolute !important;
    z-index: 10 !important;
    left: 0;
    right: 0;
    transform: translateY(calc(-20vw + 70px));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="button">Test button</button>
<ul class="nav navbar-nav">
    <li class="singlechatContainer ">Test</li>
    <li class="singlechatContainer ">Test</li>
    <li class="singlechatContainer ">Test</li>
   <li class="singlechatContainer ">Hello1</li>
   <li id="select" class="singlechatContainer ">Hello2</li>
   <li class="singlechatContainer ">Hello3</li>
<ul>

My problem is that I have to change the container position to absolute to be able to make the animation. But I don't know how to change this back and keep it as first item in the UL.

What I want to achieve looks like this, but with 'hello1' becoming the second item.:

enter image description here

another problem is that if you scroll while it's moving, it will move till the visual top of the list and won't continue (I know that with my current code it's obvious but I have no idea how to achieve this). Here an example of what happens if you scroll down (What I don't want):

enter image description here

I want it to continue moving up but under the block of "new chat"

Does someone know how to achieve this? It can be in javascript or jQuery as well. Thanks in advance! :)

Upvotes: 1

Views: 615

Answers (2)

Phaelax z
Phaelax z

Reputation: 2009

Room for improvement but more or less does what you want I think.

https://jsfiddle.net/phaelax/efgLub1p/4/

        var offset = 0;
        
        
        $(function(){
                    
            $('#thing').on('click', '.singlechatContainer', function(e){
                if (!$('#thing').children('li.moving').length){
                    $('#thing').children('li').removeClass('selected');
                    $(e.target).addClass('moving selected');
                    xi = setInterval("moveItem()", 10);
                }
            });
        
        });
        
        
        function moveItem(t){
            
            var $m = $('#thing').children('li.moving');
            offset += 1;
            
            
            
            if ($m.not(':first-child').length){
                if (offset >= $m.outerHeight()){
                    $m.prev().before($m);
                    offset = 0;
                }
            }else{
                offset = 0;
                clearInterval(xi);
                $m.removeClass('moving');
            }
            
            $m.css('margin-top', '-'+offset+'px').css('margin-bottom', offset+'px');
            

        }

javascript

.singlechatContainer{padding:4px;color:#EEE;position:relative;}
.selected{background:#3399ff;border-radius:3px;color:white}
ul{list-style:none;background:#3a3a3a;font-family:arial}
ul li:hover{cursor:pointer}
.moving{z-index:1;}

css

<body>

    
    <div style="width:300px;">
        <ul id="thing">
            <li class="singlechatContainer ">Apples</li>
            <li class="singlechatContainer ">Bananas </li>
            <li class="singlechatContainer">Grapefruits</li>
            <li class="singlechatContainer ">Peaches</li>
            <li class="singlechatContainer ">Radishes</li>
            <li class="singlechatContainer ">Starfruit</li>
        </ul>   
    </div>

    
</body>

html

Upvotes: 1

Talha Akbar
Talha Akbar

Reputation: 10040

For the first issue where Hello2 moves on top of Hello1, you would need add padding-top in your .nav that is equal to height of a .singlechatContainer.

For the second issue, since, you're only translating to a fixed value of calc(-20vw + 70px), it will stop. Instead, you should use top: 0; to ensure that it goes all the way to the top regardless of the scroll position. You don't need transform. Also, you may need to add position: relative to your .nav.

For both issues, I would revise my CSS to:

.nav {
    position: relative;
}

.nav.has-moved {
    padding-top: 40px; // <-- Adjust according to height of .singlechatContainer
}

.singlechatContainer {
    -moz-transition: all 5s;
    -webkit-transition: all 5s;
    -o-transition: all 5s;
    transition: all 5s;
}
.is-moved {
    position: absolute !important;
    z-index: 10 !important;
    left: 0;
    right: 0;
    top: 0; // <-- Notice, we removed transform
}

It is assumed you would add has-moved class to your .nav when the chat is selected.

Upvotes: 0

Related Questions