Jump to content


Slides animation for bootstrap carousel

Recommended Posts

Hi there,


I'm trying to achieve some quite simple animations for my bootstrap carousel slides, but I'm not able to get them rendered at the right moment.


What I want to do, is to animate the slides, which are inside its captions, for each slider image when the next image is sliding/ fading into view. Right now, the carousel is set to "pause", so that the slide effect is managed via the carousel indicators or controls.


I got to work the animations for the first carousel image with a simple timeline, like so:

var tl = new TimelineLite();

tl.from(".tlt", 0.5, { left: 200, autoAlpha: 0 }, "-=0.25")
.from(".tlt2", 0.5, { right: 200, autoAlpha: 0 })
.to("hr", 0.5, { width: 800 })
.from(".fa-angle-double-down", 2.5, { top: 0, autoAlpha: 0, ease: Elastic.easeOut })

where .tlt, .tlt2 etc are the headings and sub heaings to animate.


The problem arises, when I try to achieve animating the elements of the next slides, which are fading in by manually changing to the next slider image.


I don't know how to animate them for the moment the next slider image comes into view. If I continue with the same timeline, the effects already happened before the next image was loaded. So I tried to create a new timeline, but it's the same problem. I've heard that there is the possibility to add a Label, but only could change the animation delayed in time, not when the new slide comes into view.


So, finally I resort to a little, somewhat anarchical trick with an "onClick" function for each indicator. Like so:

<li onclick="myFunction2()" data-target="#carousel-example-generic" data-slide-to="1"></li>


function myFunction2() {
    var tl2 = new TimelineLite();

    tl2.from("#it-h4", 0.5, { left:200, autoAlpha:0, delay:0.8 })
    .from("#it-p", 0.5, { right: 200, autoAlpha: 0 });   

Sure, this is not the finest solution and it only works because of the carousel indicators. So what if I want to set the carousel to fading automatically, setting an interval?


Does GSAP have any solution for this issue? Couldn't find any related post.


Best regards, Pete


Link to comment
Share on other sites

Hi PeTaWeb :),


Without a CodePen, it's going to be a little difficult to fully understand what you're looking to accomplish so I'd definitely recommend setting up a CodePen. Everyone can then see your code in action. (and why it isn't working)


Check this out: http://greensock.com/forums/topic/9002-read-this-first-how-to-create-a-codepen-demo/


I wasn't 100% sure what you're asking, but it sounds like you're trying to animate some elements on the slides after they come into view?


If that's the case, 

Blake has a really good example here: 

See the Pen ZbdxRx by osublake (@osublake) on CodePen


Diaco also recently posted some cool CodePens with sliders that you should see:

See the Pen XmozON by MAW (@MAW) on CodePen

See the Pen yYradO by MAW (@MAW) on CodePen


Hopefully this helps, but as I mentioned, everyone will want to see your CodePen to really be able to help you. :)

  • Like 3
Link to comment
Share on other sites

Hi PointC,


thank you for your quick reply and sorry for the delay.


It's the first time I'm using CodePen, but finally I got it to work (the CodePen, not the GSAP animation ;-)):

See the Pen pgowvM by anon (@anon) on CodePen


  1. What I'm trying to achieve, is to animate the captions, or better said, the headings inside these captions. The first slide works fine directly after the page has finished loading (comes into view). But how do I animate the second and the third slide when they come into view. I tried already a lot of things, amongst others the above described. But the solutions are a little bit weird, there must be a cleaner solution.
  2. Also: The gsap animations work only once. When I get back to the first slide after visiting the second or the third slider, the animation does not repeat. 

The carousel effects are bootstrap-, css- and js-based and work without any problem. Could it be that the gsap animation is not working due to bootstrap settings? Maybe the problem lies there.


And yes,  Blake's example is similar to what I'm looking for, but I got a little confused because of the different slider effects (pushing up instead of fading in).


The example which closest fits to my needs is from Carl Schooff: http://www.snorkl.tv/2011/03/bullet-proof-timelinemax-transitions-part-1-jump-to-section/


But don't know exactly how to convert the code into html.


I'd be really thankful about any help.


Best regards, Pete

Link to comment
Share on other sites

Hi there,


so, does the codepen help you to better understand the issue?


Best regards, Pete

Link to comment
Share on other sites

Hi @PetaWeb,


Take a look at the JS below:

var $myCarousel = $('#carousel-example-generic');
var timelines = [];
timelines[0] = createTimeline('.tlt', '.tlt2');
timelines[1] = createTimeline('.it-h3', '.it-h4');
timelines[2] = createTimeline('.title3', '.caption3');

function doAnimations(elems) {
  var animEndEv = 'webkitAnimationEnd animationend';
  elems.each(function () {
    var $this = $(this), $animationType = $this.data('animation');
    $this.addClass($animationType).one(animEndEv, function () {

var $firstAnimatingElems = $myCarousel.find('.item:first').find('[data-animation ^= "animated"]');
$myCarousel.on('slide.bs.carousel', function (e) {
  var currentSlideIndex = $(e.relatedTarget).index();
  var $animatingElems = $(e.relatedTarget).find("[data-animation ^= 'animated']");

function createTimeline(title1, title2) {
  var timeline = new TimelineMax({ paused: true });
  timeline.from(title1, 0.6, { x: '-=200', autoAlpha: 0, ease: Expo.easeOut }, 0);
  timeline.from(title2, 0.6, { x: 200, autoAlpha: 0, ease: Expo.easeOut }, 0.1);
  return timeline;

Here is what has changed:

  • Timelines are created and put together inside an array called timelines.
  • Inside the slide.bs.carousel callback, we get the index of the upcoming slide (slide.bs.carousel event fires at the _start_ of the transition) by using jQuery's .index() helper method.
  • We then use this index to correctly trigger the timeline present in the timelines array created earlier like so:
  • timelines[currentSlideIndex].restart();

See the Pen BjyWNX?editors=101 by tah_med (@tah_med) on CodePen

is your forked pen.

  • Like 1
Link to comment
Share on other sites

The demos PointC provided are easily some of the best examples of how do do this in a smart and efficient way.


The example you linked to on snorkl.tv is using a very simple technique that isn't very flexible or dynamic. 

its just a single timeline that has each transition marked with a label and the buttons just tell the timeline which label to play.


This is a very simple, bare-bones conversion of that technique:




I would really only recommend it if the other solutions seem to complicated.




Some of the examples above, started with this from Chrysto: http://codepen.io/bassta/pen/kDvmC/ that might help as well. 

Blake recently spent many hours explaining a litany of cool techniques for this type of project here: http://greensock.com/forums/topic/13268-how-to-toggle-tweens-in-a-dry-fashion/


And I see Tahir just came in with an excellent solution as well. 

  • Like 1
Link to comment
Share on other sites

Hi Tahir and hi Carl,


thank you very much for the great support.


@Carl: I've seen already Chrysto's and Blake's examples that you provided, but I was not able to apply these techniques to my bootstrap carousel. Thank you anyways.


So, Tahir, I think your JS code is exactly what I needed. I knew before, that I had to adapt the JS for the carousel slide- (fade-) effects to get the gsap animations to work in the right place, but didn't know how.


As I can see, you are using arrays for the timelines. So I was wondering what would happen if I'd like to add more gsap animations on more than just two elements (title1, title2). Would I just add more array elements to the "timelines" array and then append just the associated timelines?


And what if I'd like to have more elements to animate on one slide but less on another slide. e.g.:

var timelines = [];
timelines[0] = createTimeline('.tlt', '.tlt2');
timelines[1] = createTimeline('.it-h3', '.it-h4');
timelines[2] = createTimeline('.title3', '.caption3', '.anotherElement3');
timelines[3] = createTimeline('.title4');
timelines[4] = createTimeline('.title5', '.caption5', '.anotherElement1-5', 'anotherElement2-5');

How would that effect the timelines? just adding more of them inside the createTimeline() function?


Thanks very much for help. Much appreciated.


Best regards, Pete

Link to comment
Share on other sites

Hi @PetaWeb,


1. To answer your question about "have more elements to animate on one slide but less on another slide", here is what I think that should be done to cater that:


Currently, the `.createTimeline()` function animates the 2 elements you were already animating. It is just a more re-usable way of doing that. Nothing else.


If for example, there is a timeline that needs to animate more elements other the typical `title` and `caption` that you were previously animating, then this function alone won't deem so useful anymore. It will either need to be extended in a way to expect more elements and then animate these elements respectively or, there doesn't even need to be a need for a function and all timelines are created on a per-need basis because it may seem that the requirements for each timeline is different and unique.


Having said that, you may want to share how you intend to animate the `.anotherElement3`, `.anotherElement1-5` and `.anotherElement2-5` elements.


As an example of what I am talking about when I say "extend the same function to expect more elements", you could do something like:

function createTimeline(title, caption, element1, element2) {
  var timeline = new TimelineMax({ paused: true });
  if (title !== '') { timeline.from(title, *duration*, { /* whatever you want to do with it */ }, *position*); }
  if (caption !== '') { timeline.from(caption, *duration*, { /* whatever you want to do with it */ }, *position*); }
  if (element1 !== '') { timeline.from(element1, *duration*, { /* whatever you want to do with it */ }, *position*); }
  if (element2 !== '') { timeline.from(element2, *duration*, { /* whatever you want to do with it */ }, *position*); }
  return timeline;

and the usage will look like:

timelines[*index*] = createTimeline('.someTitle', '.someCaption', '.someElement', '.anotherElement');

and for those you don't want to animate other elements, pass in empty strings:

timelines[*index*] = createTimeline('.someTitle', '.someCaption', '', '');

Seems like an overkill but then again, it depends on what exactly are you animating and if we can optimise it even further.


2. I am not sure if I understand it correctly, the part where you say "add more gsap animations on more than just two elements". `.createTimeline()` is just a function, you can add as many elements as you'd like. Just receive them as parameters first and then do what you want to do with them, as shown above.


Let me know if it helps or if you need anything clarified.

  • Like 1
Link to comment
Share on other sites

Hi Tahir,


thank you very much for further investigate the issues.


I'm currently trying out if the code you provided works on my bootstrap carousel. But I found out that there is a part that I don't really understand:

if (title !== '')...etc.

What do I have to put into the empty strings here? Right now the animations are not working.


In any case, I will work out the animations of the other elements to provide you more detailed information.


Thanks a lot and best regards,



Link to comment
Share on other sites

Hi Pete :),


That condition is just asking if there is something in your title to tween.

!== // means not equal value or not equal type

So, as long as there is something available, it will tween it. 


Here's some more reading on comparison operators.



Happy tweening :)

  • Like 2
Link to comment
Share on other sites

Hi there,


yes, of course I know the meaning of the "!==" operator, but I'm still confused about it.


So, right now I'm trying it out and hopefully can get it to work.


Thanks for your patience, Pete

Link to comment
Share on other sites

if (foo !== '') {
 // This happens if foo exists and isn't falsy

Tahir put that there to prevent a tween being from being created if you didn't pass in a value for the target. It's not necessary for the code to run, but it's a good idea. Using an empty string may not be the most common way to check if something exists, but it's perfectly valid.


There's a lot of different ways to get truthy and falsy values. Look at the console in this demo to see how stuff evaluates. One thing I use in my code that seems to confuse people is checking the length of an array or jQuery object. Go see how that evaluates.


See the Pen 680469290799414ecfcd635843c283a3?editors=001 by osublake (@osublake) on CodePen

  • Like 4
Link to comment
Share on other sites

Hi guys,


thank you very much for supporting me with this issue.


Finally, with your help, I got it to work as I wanted to, and I know now how to animate different elements on the different sliders. There is, though, one last point I cannot figure out how to solve:


Right now, the animations happen directly after the next slider comes into view, very fast for my taste. I solved this issue by adding a delay to each timeline.


My question is, if that way is the only one that exist to achieve the delay?


So, thank you very much again.


Best regards, Pete

Link to comment
Share on other sites

Hi @PeTaWeb


TimelineMax's `.from()` & `.to()` methods have fourth, `.fromTo()`, `.staggerFrom()` & `.staggerTo()` methods have fifth and `.staggerFromTo()` method has sixth (and other methods have), parameter which takes care of `position` of your tween.

Please take a look at this tutorial on understanding this position parameter and how you can use it: Timeline Tip: Understanding the Position Parameter. Also look into the documentation of each of those methods linked above.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

I'm trying to rearrange a Bootstrap carousel news slider on my website based on the Pixel Storm theme from Template Monster (http://www.templatemonster.com/properties/features/bootstrap-templates/). It seems like the slides' timing is getting all wrong after few seconds. I tried to modify custom.js and reset a timer, but this only works on the news button, while the slides keep moving faster when needed. Any ideas on how to fix this? A week has passed since the purchase and I'm still stuck. Thanks.

Link to comment
Share on other sites

  • 3 weeks later...

Hello again,


after I marked this issue as solved a few weeks ago, I now had to mark it as unsolved, because I´m facing another problem regarding the same issue.


Finally I decided to apply Tahir´s suggestions to use the "timelines[]" array and the "createTimeline" function to achieve my purposes as it is the solution that best suits.


But, what if I want to reverse the animations by clicking the next-button before the next slide comes into view?


1) Would it be a good idea to create another array similar to the "timelines" array and then create, let´s say, a "reverseTimeline" function that renders on next-button click event with reversed animations.


I´m just trying that out, but can´t get it to work. And:


2) What about the time between the fade effect from one slide to the next, as it is about a bootstrap carousel with css transition-property of opacity with no time delay waiting for completing the reverse animations?


Hope, the questions are not going to far, as it´s maybe not pure gsap issue.


Anyway, any help would be appreciated.


Best regards, Pete

Link to comment
Share on other sites



o.k., I'm progressing with the issue. But it still isn't working smoothly.


As I said before, I'm applying Tahir's suggestion to built a timelines array and then a timeline for each slide of the bootstrap carousel. Here is the modified codepen:

See the Pen pgowvM by anon (@anon) on CodePen


What I want to achieve is to reverse the timeline of each slide before the next slide comes into view. As you can see in the pen, I applied an onComplete function ("reverseFunction") for the slide indicators (not for the controls) as a parameter of the TimelineMax, like so:

// Timeline for slider 1
function createTimeline1(element1, element2, element3, element4, element5) {
    var timeline1 = new TimelineMax({ onComplete: reverseFunction1 });
    if (element1 !== '') { timeline1.from(element1, 0.9, { x: -1420, autoAlpha: 0, ease: Power4.ease, delay: 0.8 }); }
    if (element2 !== '') { timeline1.from(element2, 0.9, { x: 1420, autoAlpha: 0, ease: Power4.ease }, "-=0.9"); } // There can be more animations by just adding more "if()..."    
    if (element3 !== '') { timeline1.from(element3, 0.8, { scale: 0, autoAlpha: 0 }, "-=0.2"); }
    return timeline1;
    function reverseFunction1() {
        $(".ind2").not(".ind1").click(function () {
            timeline1.reverse().timeScale(3); // timeScale because of slide transition speed

But the problem is:


I had to apply a timescale() to the reverse function, because the reversed animation lasts more than the slide fading in, so you hardly can appreciate the reversing animations. But the timescale() makes also the timeline going faster when going back to one of the slides.


So, is there any possibility to apply the timescale to the reversed timeline but not to the "normal" timeline? Or is there a way to pause the bootstrap carousel during the reversed animation until the fade in of the next slide starts?


Any help would be much appreciated.


Best regards, Pete

Link to comment
Share on other sites

i'm really not familiar at all with the inner workings of the bootstrap carousel so I can't really dive into your code and try to fix it. but to answer your question about the timelines playing too fast once you have set the timeScale(3) when reversed you can just set the timeScale(1) when you restart() like




From what I can tell of reading your code I worry that putting that onComplete callback on the timelines to set up the reverseFunction() is not going to be a stable approach. If you are relying on something like the bootstrap carousel to manage events and basic state changes I would strongly suggest you tap into that API as much as possible.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.