Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove css transitions without delay?

I want a transition a css property smoothly then I want immediate change in css property value and then I want to attach the transition back again. To better understand see the following example:

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
  $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function() {
  
  $('.marquee-wrapper').css("transition", "none");
  $('.marquee-wrapper').css("transform", "translateY(100px)"); //This should Immediately change translateY to 100px without smooth transition. But this doesn't happen without adding a delay before the below written line
  
  // Its weird why javascript engine executes the below line before executing this line

  $('.marquee-wrapper').css("transition", "transform 3s linear");
  $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

As you can see in the setInterval I first set transition to none then translateY to 100px. Now in principle this should suddenly translate the div to 100px but this doesn't happen before moving div to 100px javascript engine executes the next line and reassign transition. In the below example I have given a 100ms delay before reassigning the transition and it works:

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
  $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function() {
  
  $('.marquee-wrapper').css("transition", "none");
  $('.marquee-wrapper').css("transform", "translateY(100px)"); //This  Immedeately change translateY to 100px without smooth transition now

  setTimeout(function(){
      $('.marquee-wrapper').css("transition", "transform 3s linear");
      $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
  },100);
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

My questions are:

  1. How do I stop javscript engine to reassign transition property before making changing translate property, without any delay?
  2. Why does javscript engine excutes a forthcoming line($('.marquee-wrapper').css("transition", "transform 3s linear");) in script before the current line($('.marquee-wrapper').css("transform", "translateY(100px)");)
like image 1000
user31782 Avatar asked Mar 21 '17 15:03

user31782


People also ask

How do you stop a transition in CSS?

To trigger an element's transition, toggle a class name on that element that triggers it. To pause an element's transition, use getComputedStyle and getPropertyValue at the point in the transition you want to pause it. Then set those CSS properties of that element equal to those values you just got.

Which delay CSS property is used for transition effect?

The transition-delay property specifies when the transition effect will start. The transition-delay value is defined in seconds (s) or milliseconds (ms).


1 Answers

Grouping the transition and transform CSS properties in a single statement gives the correct result, without having to use the 100 ms delay:

$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
setInterval(function () {
    $('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
    $('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
    $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}

$('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });

setInterval(function () {
    $('.marquee-wrapper').css({ transition: "none", transform: "translateY(100px)" });
    $('.marquee-wrapper').css({ transition: "transform 3s linear", transform: "translateY(-" + $(".marquee-content").outerHeight(true) + "px)" });
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>

The reason for that behavior could be that setting both CSS properties at once triggers an immediate repaint of the page whereas setting them separately doesn't.

Some Javascript commands are known to cause a repaint. Getting the offsetHeight of an element is the one mentioned most often (see this post). As a matter of fact, it was used in this article to solve a problem with CSS transitions quite similar to the one presented here. And if we test that method by getting the element height between the transitions, we see that the resulting behavior is indeed correct:

$('.marquee-wrapper').css("transition", "none");
$('.marquee-wrapper').css("transform", "translateY(100px)");
$('.marquee-wrapper').height(); // Force a repaint
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

if ($(".marquee").height() < $(".marquee-content").outerHeight(true)) {
    $(".marquee-content").clone().appendTo($(".marquee-wrapper"));
}
$('.marquee-wrapper').css("transition", "transform 3s linear");
$('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");

setInterval(function () {
    $('.marquee-wrapper').css("transition", "none");
    $('.marquee-wrapper').css("transform", "translateY(100px)");
    $('.marquee-wrapper').height(); // Force a repaint
    $('.marquee-wrapper').css("transition", "transform 3s linear");
    $('.marquee-wrapper').css("transform", "translateY(-" + $(".marquee-content").outerHeight(true) + "px)");
}, 3000);
.marquee {
  margin: auto;
  width: 600px;
  height: 200px;
  overflow: auto;
}

.marquee-wrapper {
  transform: translateY(0);
}

.marquee-content {
  margin: 0;
  padding: 30px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="marquee">
  <div class="marquee-wrapper">
    <div class="marquee-content">
      Updates: Update (8 Mar 2016): Now plugin have new option: startVisible The marquee will be visible in the start if set to true. Thanks to @nuke-ellington 👠Update (24 Jan 2014): Note: people who been asking me how to use this plugin with content being
      loaded with Ajax, please read notes about this update. New methods added, so now after you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq = $('.marquee').marquee();, you start the plugin using var $mq
      = $('.marquee').marquee();, then you can pause, resume, togglepause, resume) and desestroy destroy toggle(pause, resume) and destroy toggle(pause, resume) and destroy methods e.g to remove the marquee plugin from your element simply use $mq.marquee('destroy');.
      Similarly you can use pause the marquee any time using $mq.marquee('pause');.
    </div>
  </div>
</section>
like image 82
ConnorsFan Avatar answered Sep 30 '22 06:09

ConnorsFan