How to make jQuery fadeIn/Out element smoothly move in and out of place

Viewed 77

Lets say I have this code:

function hide(num){
 $("#text" + num).fadeOut();
}

function show(num){
  $("#text" + num).fadeIn();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<button onclick="show(1)">
  Show text 1
</button>
<button onclick="show(2)">
  Show text 2
</button>
<button onclick="hide(1)">
  Hide text 1
</button>
<button onclick="hide(2)">
  Hide text 2
</button>

<p id="text1">
  Text1
</p>

<p id="text2">
  Text2
</p>

When you click "Hide Text1" Text1 fades away smoothly but Text2 automatically teleports to its position. Is there a way to make this "teleport" more of a slide?

I know that I can animate every possible movement in JS but that gets really annoying when you autogenerate a lot of elements. Is there a way to do this for all of these automatic teleports?

2 Answers

Yes, you can do it using the animate() function in jQuery.

Here is your code:

function hide(num){
 $("#text" + num).fadeOut();
  if(num == 1) {
   $("#text2").animate({
     top: "25px"
    }, 500, function() {
     
    });
  }
  
  if(num == 2) {
   $("#text1").animate({
     top: "25px"
    }, 500, function() {
     
    });
  }
}

function show(num){
  $("#text" + num).fadeIn();
    
    if(num == 1) {
   $("#text2").animate({
     top: "100px"
    }, 500, function() {
     
    });
  }
  
  if(num == 2) {
   $("#text1").animate({
     top: "25px"
    }, 500, function() {
     
    });
  }
}
p {
  position: absolute;
}

#text2 {
  top: 100px;
}

#text1 {
  top: 25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<button id="button1" onclick="show(1)">
Show text 1
</button>
<button id="button2" onclick="show(2)">
Show text 2
</button>
<button id="button3" onclick="hide(1)">
Hide text 1
</button>
<button  id="button4" onclick="hide(2)">
Hide text 2
</button>
<p id="text1">
Text1
</p>
<br>
<p id="text2">
Text2
</p>
</body>
</html>

Here is a living demo: https://codepen.io/marchmello/pen/rNOBLzL

You can use a combination of slideToggle and animate. The slideToggle handles the display and height of the element, while the animate handles the opacity. You may not need the opacity changed, so you could get rid of that. This will handle all the elements if they are dynamically generated.

function hide(num) {
  var elem = $("#text" + num);
  if (elem.css('display') == 'block') {
    elem.animate({
      'opacity': 0
    });
    elem.slideToggle();
  }
}

function show(num) {
  var elem = $("#text" + num);
  if (elem.css('display') == 'none') {
    elem.slideToggle();
    elem.animate({
      'opacity': 1
    });
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<button onclick="show(1)">
      Show text 1
    </button>
<button onclick="show(2)">
      Show text 2
    </button>
<button onclick="hide(1)">
      Hide text 1
    </button>
<button onclick="hide(2)">
      Hide text 2
    </button>
<p id="text1">
  Text1
</p>
<p id="text2">
  Text2
</p>

I also added a check so the slideToggle doesn't fire if the user clicks on the show buttons and the elements are already there.

OR you can use slideUp and slideDown:

function hide(num) {
  var elem = $("#text" + num);
  if (elem.css('display') == 'block') {
    elem.animate({
      'opacity': 0
    });
  }
  
  elem.slideUp();
}

function show(num) {
  var elem = $("#text" + num);
  if (elem.css('display') == 'none') {
    elem.animate({
      'opacity': 1
    });
  }
  elem.slideDown();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<button onclick="show(1)">
      Show text 1
    </button>
<button onclick="show(2)">
      Show text 2
    </button>
<button onclick="hide(1)">
      Hide text 1
    </button>
<button onclick="hide(2)">
      Hide text 2
    </button>
<p id="text1">
  Text1
</p>
<p id="text2">
  Text2
</p>

OR, if you can change your code, I may recommend created a single show/hide button for each text box. Like this:

function show_hide(num) {
  var elem = $("#text" + num);
  elem.slideToggle('slow', function() {
    if (elem.css('display') == 'none') {
      elem.animate({
        'opacity': 0
      });
    } else {
      elem.animate({
        'opacity': 1
      });
    }
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<button onclick="show_hide(1)">
      Show or Hide text 1
    </button>
<button onclick="show_hide(2)">
      Show or Hide text 2
    </button>
<p id="text1">
  Text1
</p>
<p id="text2">
  Text2
</p>

Related