JungleDiff
JungleDiff

Reputation: 23

How to make smooth block animation?

A slide opening has twitches, how can I get rid of them?

If with the last block everything is more or less normal, then with the rest are not even close. How do I make all the blocks, except the one that was clicked disappear and the remaining block is smoothly moved to the center of the screen and then opens.

$(document).ready(function() {

  let status = false;

  $(".block").on("click", function() {
    if (status == false) {
      $(".block").not($(this)).slideToggle();
      $(this).animate({
        maxWidth: "100%"
      }, 500).find(".slide").css("display", "flex").animate({
        width: "100%"
      }, 500);
      status = true;
    } else {
      $(this).animate({
        maxWidth: "32%"
      }, 500).find(".slide").css("display", "none").animate({
        width: "0%"
      }, 500);
      $(".block").not($(this)).slideToggle();
      status = false;
    }
  })

});
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600;700;800;900&display=swap');
html,
body {
  font-size: 10px;
}

body {
  background-color: #1c1c1e;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wrapper {
  width: 100%;
  padding: 1rem 0;
}

.flex-block {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.block {
  display: flex;
  margin: 15px;
  justify-content: space-between;
  width: 100%;
  max-width: 32%;
  height: 200px;
  background-color: #464649;
  font-family: 'Montserrat', sans-serif;
  overflow: hidden;
}

.block .slide,
.block .content {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  color: #d7d7df;
}

.block .slide {
  background-color: #303033;
  width: 0%;
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <section class="test">
    <div class="flex-block">
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
    </div>
  </section>
</div>

Upvotes: 1

Views: 272

Answers (2)

Pete
Pete

Reputation: 58442

Not sure what this is what you are after, but I would use the callback functions of your slide toggle and animation so on the first click, you hide the unwanted blocks first and then show the slide and then on your second click, you hide the slide and then show the hidden blocks:

$(document).ready(function() {

  let status = false;

  $(".block").on("click", function() {
    const $currentBlock = $(this); // get current clicked block

    if (status == false) {
      // hide non clicked blocks
      $(".block").not($currentBlock).slideToggle(function() {  
        // run this when slide toggle has finished
        $currentBlock.animate({
          maxWidth: "100%"
        }, 500).find(".slide").css("display", "flex").animate({
          width: "100%"
        }, 500);
      });
      status = true;
    } else {

      $currentBlock.animate({
        maxWidth: "32%"
      }, 500).find(".slide").animate({
        width: "0"
      }, 500, function() {
        // run this when slide has finished animating 
        $(this).css("display", "none");     // only hide the slide once the animation is finished
        $(".block").not($currentBlock).slideToggle();  // show the other blocks
      });
      status = false;
    }
  })

});
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600;700;800;900&display=swap');
html,
body {
  font-size: 10px;
}

body {
  background-color: #1c1c1e;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wrapper {
  width: 100%;
  padding: 1rem 0;
}

.flex-block {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.block {
  display: flex;
  margin: 15px;
  justify-content: space-between;
  width: 100%;
  max-width: 32%;
  height: 200px;
  background-color: #464649;
  font-family: 'Montserrat', sans-serif;
  overflow: hidden;
}

.block .slide,
.block .content {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  color: #d7d7df;
}

.block .slide {
  background-color: #303033;
  width: 0%;
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <section class="test">
    <div class="flex-block">
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
      <div class="block">
        <div class="content">
          <p>Block</p>
        </div>
        <div class="slide">
          <p>Slide</p>
        </div>
      </div>
    </div>
  </section>
</div>

Upvotes: 1

Pedro Oliveira
Pedro Oliveira

Reputation: 76

To start, don't use JQUERY, convert that code into vanilla JS. The best way is to use JS just to apply/remove classes and use CSS for all the transitions.

You have JS events that can tell you if a certain transition applied to a block has ended (look for "ontransitionend" event), this can help you to apply CSS or a class in the exact time you need.

Upvotes: 1

Related Questions